about summary refs log tree commit diff stats
path: root/html
diff options
context:
space:
mode:
Diffstat (limited to 'html')
-rw-r--r--html/001help.cc.html137
-rw-r--r--html/003trace.cc.html151
-rw-r--r--html/003trace.test.cc.html8
-rw-r--r--html/010vm.cc.html409
-rw-r--r--html/011load.cc.html177
-rw-r--r--html/012transform.cc.html27
-rw-r--r--html/013update_operation.cc.html67
-rw-r--r--html/014literal_string.cc.html (renamed from html/013literal_string.cc.html)65
-rw-r--r--html/015literal_noninteger.cc.html (renamed from html/014literal_noninteger.cc.html)24
-rw-r--r--html/020run.cc.html117
-rw-r--r--html/021arithmetic.cc.html266
-rw-r--r--html/021check_instruction.cc.html183
-rw-r--r--html/022arithmetic.cc.html353
-rw-r--r--html/023boolean.cc.html (renamed from html/022boolean.cc.html)62
-rw-r--r--html/024jump.cc.html (renamed from html/023jump.cc.html)72
-rw-r--r--html/025compare.cc.html (renamed from html/024compare.cc.html)108
-rw-r--r--html/029tools.cc.html186
-rw-r--r--html/030container.cc.html461
-rw-r--r--html/031address.cc.html165
-rw-r--r--html/032array.cc.html221
-rw-r--r--html/033exclusive_container.cc.html76
-rw-r--r--html/034call.cc.html68
-rw-r--r--html/035call_ingredient.cc.html93
-rw-r--r--html/036call_reply.cc.html95
-rw-r--r--html/037recipe.cc.html62
-rw-r--r--html/038scheduler.cc.html157
-rw-r--r--html/039wait.cc.html47
-rw-r--r--html/040brace.cc.html244
-rw-r--r--html/041jump_target.cc.html48
-rw-r--r--html/042name.cc.html135
-rw-r--r--html/043new.cc.html249
-rw-r--r--html/044space.cc.html97
-rw-r--r--html/045space_surround.cc.html18
-rw-r--r--html/046closure_name.cc.html90
-rw-r--r--html/047global.cc.html30
-rw-r--r--html/048check_type_by_name.cc.html137
-rw-r--r--html/048typecheck.cc.html128
-rw-r--r--html/050scenario.cc.html167
-rw-r--r--html/052tangle.cc.html52
-rw-r--r--html/053continuation.cc.html278
-rw-r--r--html/054dilated_reagent.cc.html140
-rw-r--r--html/055parse_tree.cc.html117
-rw-r--r--html/056recipe_header.cc.html395
-rw-r--r--html/057static_dispatch.cc.html223
-rw-r--r--html/058shape_shifting_container.cc.html294
-rw-r--r--html/059shape_shifting_recipe.cc.html482
-rw-r--r--html/060string.mu.html60
-rw-r--r--html/061channel.mu.html28
-rw-r--r--html/062array.mu.html16
-rw-r--r--html/063list.mu.html70
-rw-r--r--html/064random.cc.html30
-rw-r--r--html/065duplex_list.mu.html502
-rw-r--r--html/066stream.mu.html4
-rw-r--r--html/070display.cc.html188
-rw-r--r--html/071print.mu.html22
-rw-r--r--html/072scenario_screen.cc.html122
-rw-r--r--html/073scenario_screen_test.mu.html8
-rw-r--r--html/074console.mu.html14
-rw-r--r--html/075scenario_console.cc.html105
-rw-r--r--html/076scenario_console_test.mu.html8
-rw-r--r--html/080trace_browser.cc.html26
-rw-r--r--html/081run_interactive.cc.html287
-rw-r--r--html/082persist.cc.html70
-rw-r--r--html/098check_type_pointers.cc.html67
-rw-r--r--html/999spaces.cc.html11
-rw-r--r--html/channel.mu.html14
<span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Globals&quot;)</span> +<span class="Comment">// word boundaries</span> +string Terminators<span class="Delimiter">(</span><span class="Constant">&quot;(){}&quot;</span><span class="Delimiter">);</span> +string Ignore<span class="Delimiter">(</span><span class="Constant">&quot;,&quot;</span><span class="Delimiter">);</span> <span class="Comment">// meaningless except within [] strings</span> +<span class="Delimiter">:(code)</span> void slurp_word<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> char c<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> &amp;&amp; in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> &amp;&amp; Terminators<span class="Delimiter">.</span>find<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> in &gt;&gt; c<span class="Delimiter">;</span> out &lt;&lt; c<span class="Delimiter">;</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> while <span class="Delimiter">(</span>in &gt;&gt; c<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>c<span class="Delimiter">)</span> || c == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>c<span class="Delimiter">)</span> || Terminators<span class="Delimiter">.</span>find<span class="Delimiter">(</span>c<span class="Delimiter">)</span> != string::npos || Ignore<span class="Delimiter">.</span>find<span class="Delimiter">(</span>c<span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>putback<span class="Delimiter">(</span>c<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -219,8 +224,8 @@ void slurp_word<span class="Delimiter">(</span>istream&amp; in<span class="Delim <span class="Delimiter">}</span> <span class="Delimiter">}</span> -void skip_whitespace<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> - while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> &amp;&amp; isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> &amp;&amp; in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +void skip_ignored_characters<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> || Ignore<span class="Delimiter">.</span>find<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -229,6 +234,7 @@ void skip_whitespace_and_comments<span class="Delimiter">(</span>istream&amp; in while <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()))</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> else <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -241,12 +247,6 @@ void skip_comment<span class="Delimiter">(</span>istream&amp; in<span class="Del <span class="Delimiter">}</span> <span class="Delimiter">}</span> -void skip_comma<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> &amp;&amp; in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="Delimiter">}</span> - <span class="Comment">//: Warn if a recipe gets redefined, because large codebases can accidentally</span> <span class="Comment">//: step on their own toes. But there'll be many occasions later where</span> <span class="Comment">//: we'll want to disable the warnings.</span> @@ -261,11 +261,8 @@ bool warn_on_redefine<span class="Delimiter">(</span>const string&amp; recipe_na <span class="Delimiter">}</span> <span class="Comment">// for debugging</span> -<span class="Delimiter">:(before &quot;End Globals&quot;)</span> -bool Show_rest_of_stream = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> void show_rest_of_stream<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!Show_rest_of_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> cerr &lt;&lt; <span class="Constant">'^'</span><span class="Delimiter">;</span> char c<span class="Delimiter">;</span> while <span class="Delimiter">(</span>in &gt;&gt; c<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -281,13 +278,15 @@ vector&lt;recipe_ordinal&gt; recently_added_recipes<span class="Delimiter">;</sp long long int Reserved_for_tests = <span class="Constant">1000</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Setup&quot;)</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &gt;= Reserved_for_tests<span class="Delimiter">)</span> <span class="Comment">// don't renumber existing recipes, like 'interactive'</span> - Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe[recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &gt;= Reserved_for_tests <span class="Comment">// don't renumber existing recipes, like 'interactive'</span> + &amp;&amp; contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Comment">// in case previous test had duplicate definitions</span> + Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Comment">// Clear Other State For recently_added_recipes</span> recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Delimiter">:(code)</span> <span class="Delimiter">:(scenario parse_comment_outside_recipe)</span> <span class="Comment"># this comment will be dropped by the tangler, so we need a dummy recipe to stop that</span> recipe f1 [ ] @@ -296,8 +295,8 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_comment_amongst_instruction)</span> recipe main [ @@ -305,8 +304,8 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_comment_amongst_instruction_2)</span> recipe main [ @@ -315,8 +314,8 @@ recipe main [ <span class="Comment"># comment</span> ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_comment_amongst_instruction_3)</span> recipe main [ @@ -325,19 +324,19 @@ recipe main [ <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;2&quot;, properties: [&quot;2&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;2&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_comment_after_instruction)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> <span class="Comment"># comment</span> ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_label)</span> recipe main [ @@ -356,43 +355,43 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span>/foo:bar:baz ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;, &quot;foo&quot;: &quot;bar&quot;:&quot;baz&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;, &quot;foo&quot;: &lt;&quot;bar&quot; : &lt;&quot;baz&quot; : &lt;&gt;&gt;&gt;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_multiple_products)</span> recipe main [ <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;2&quot;, properties: [&quot;2&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> +<span class="traceContains">+parse: product: {&quot;2&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_multiple_ingredients)</span> recipe main [ <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">4</span>:number ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: ingredient: {name: &quot;4&quot;, properties: [&quot;4&quot;: &quot;number&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;2&quot;, properties: [&quot;2&quot;: &quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: ingredient: {&quot;4&quot;: &quot;number&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> +<span class="traceContains">+parse: product: {&quot;2&quot;: &quot;number&quot;}</span> <span class="Delimiter">:(scenario parse_multiple_types)</span> recipe main [ <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">4</span>:number ] <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;23&quot;, properties: [&quot;23&quot;: &quot;literal&quot;]}</span> -<span class="traceContains">+parse: ingredient: {name: &quot;4&quot;, properties: [&quot;4&quot;: &quot;number&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;2&quot;, properties: [&quot;2&quot;: &quot;address&quot;:&quot;number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;23&quot;: &quot;literal&quot;}</span> +<span class="traceContains">+parse: ingredient: {&quot;4&quot;: &quot;number&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;}</span> +<span class="traceContains">+parse: product: {&quot;2&quot;: &lt;&quot;address&quot; : &lt;&quot;number&quot; : &lt;&gt;&gt;&gt;}</span> <span class="Delimiter">:(scenario parse_properties)</span> recipe main [ <span class="Constant">1</span>:number:address/lookup<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> ] -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;number&quot;:&quot;address&quot;, &quot;lookup&quot;: ]}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &lt;&quot;number&quot; : &lt;&quot;address&quot; : &lt;&gt;&gt;&gt;, &quot;lookup&quot;: &lt;&gt;}</span> <span class="Comment">//: this test we can't represent with a scenario</span> <span class="Delimiter">:(code)</span> diff --git a/html/012transform.cc.html b/html/012transform.cc.html index 24c3b436..6770e137 100644 --- a/html/012transform.cc.html +++ b/html/012transform.cc.html @@ -13,10 +13,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } -.Identifier { color: #804000; } +.CommentedCode { color: #6c6c6c; } --> </style> @@ -32,10 +33,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment">//:</span> <span class="Comment">//: The hope is that this framework of transform tools will provide a</span> <span class="Comment">//: deconstructed alternative to conventional compilers.</span> +<span class="Comment">//:</span> +<span class="Comment">//: We're going to have many transforms in mu, and getting their order right</span> +<span class="Comment">//: (not the same as ordering of layers) is a well-known problem. Some tips:</span> +<span class="Comment">//: a) Design each layer to rely on as few previous layers as possible.</span> +<span class="Comment">//:</span> +<span class="Comment">//: b) When positioning transforms, try to find the tightest constraint in</span> +<span class="Comment">//: each transform relative to previous layers.</span> +<span class="Comment">//:</span> +<span class="Comment">//: c) Even so you'll periodically need to try adjusting each transform</span> +<span class="Comment">//: relative to those in previous layers to find a better arrangement.</span> <span class="Delimiter">:(before &quot;End recipe Fields&quot;)</span> long long int transformed_until<span class="Delimiter">;</span> - recipe<span class="Delimiter">()</span> :transformed_until<span class="Delimiter">(</span>-<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> +<span class="Delimiter">:(before &quot;End recipe Constructor&quot;)</span> +transformed_until = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Types&quot;)</span> typedef void <span class="Delimiter">(</span>*transform_fn<span class="Delimiter">)(</span>recipe_ordinal<span class="Delimiter">);</span> @@ -43,22 +55,31 @@ typedef void <span class="Delimiter">(</span>*transform_fn<span class="Delimiter <span class="Delimiter">:(before &quot;End Globals&quot;)</span> vector&lt;transform_fn&gt; Transform<span class="Delimiter">;</span> +<span class="Delimiter">:(after &quot;int main&quot;)</span> + <span class="Comment">// Begin Transforms</span> + <span class="Comment">// End Transforms</span> + <span class="Delimiter">:(code)</span> void transform_all<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9990</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;=== transform_all()&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> for <span class="Delimiter">(</span>long long int t = <span class="Constant">0</span><span class="Delimiter">;</span> t &lt; SIZE<span class="Delimiter">(</span>Transform<span class="Delimiter">);</span> ++t<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;transform &quot; &lt;&lt; t &lt;&lt; '\n';</span> for <span class="Delimiter">(</span>map&lt;recipe_ordinal<span class="Delimiter">,</span> recipe&gt;::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> recipe&amp; r = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span> if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>transformed_until != t-<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// End Transform Checks</span> <span class="Delimiter">(</span>*Transform<span class="Delimiter">.</span>at<span class="Delimiter">(</span>t<span class="Delimiter">))(</span><span class="Comment">/*</span><span class="Comment">recipe_ordinal</span><span class="Comment">*/</span>p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">);</span> r<span class="Delimiter">.</span>transformed_until = t<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> parse_int_reagents<span class="Delimiter">();</span> <span class="Comment">// do this after all other transforms have run</span> - <span class="Comment">// End Transform</span> + <span class="Comment">// End Transform All</span> <span class="Delimiter">}</span> void parse_int_reagents<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- parsing any uninitialized reagents as integers&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- parsing any uninitialized reagents as integers&quot; &lt;&lt; '\n';</span> for <span class="Delimiter">(</span>map&lt;recipe_ordinal<span class="Delimiter">,</span> recipe&gt;::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> recipe&amp; r = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span> if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> diff --git a/html/013update_operation.cc.html b/html/013update_operation.cc.html new file mode 100644 index 00000000..c2377b97 --- /dev/null +++ b/html/013update_operation.cc.html @@ -0,0 +1,67 @@ +<!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 - 013update_operation.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.Identifier { color: #804000; } +.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Once all code is loaded, save operation ids of instructions and check that</span> +<span class="Comment">//: nothing's undefined.</span> + +<span class="Delimiter">:(before &quot;End Transforms&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>update_instruction_operations<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void update_instruction_operations<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- compute instruction operations for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- compute instruction operations for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;instruction &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; has no recipe</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + inst<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">// hook to suppress inserting recipe name into errors and warnings (for later layers)</span> +string maybe<span class="Delimiter">(</span>string s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> s + <span class="Constant">&quot;: &quot;</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">// temporarily suppress run</span> +void transform<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> + load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> + transform_all<span class="Delimiter">();</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/013literal_string.cc.html b/html/014literal_string.cc.html index 56fff30c..b137323a 100644 --- a/html/013literal_string.cc.html +++ b/html/014literal_string.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 013literal_string.cc</title> +<title>Mu - 014literal_string.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v1"> <meta name="syntax" content="cpp"> @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -43,18 +43,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy [abc def] <span class="Comment"># copy can't really take a string</span> ] -<span class="traceContains">+parse: ingredient: {name: &quot;abc def&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;abc def&quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(scenario string_literal_with_colons)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy [abc:def/ghi] ] -<span class="traceContains">+parse: ingredient: {name: &quot;abc:def/ghi&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;abc:def/ghi&quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -Type_ordinal[<span class="Constant">&quot;literal-string&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span class="Delimiter">:(after &quot;string next_word(istream&amp; in)&quot;)</span> +<span class="Delimiter">:(before &quot;End next_word Special-cases&quot;)</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string result = slurp_quoted<span class="Delimiter">(</span>in<span class="Delimiter">);</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> @@ -66,7 +66,7 @@ Type_ordinal[<span class="Constant">&quot;literal-string&quot;</span>] = <span c string slurp_quoted<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> ostringstream out<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span> assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">);</span> out &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">());</span> <span class="Comment">// slurp the '['</span> - if <span class="Delimiter">(</span>code_string<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">))</span> + if <span class="Delimiter">(</span>is_code_string<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">))</span> slurp_quoted_comment_aware<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">);</span> else slurp_quoted_comment_oblivious<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">);</span> @@ -75,7 +75,7 @@ string slurp_quoted<span class="Delimiter">(</span>istream&amp; in<span class="D <span class="Comment">// A string is a code string if it contains a newline before any non-whitespace</span> <span class="Comment">// todo: support comments before the newline. But that gets messy.</span> -bool code_string<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostringstream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> +bool is_code_string<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> char c = in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> if <span class="Delimiter">(</span>!isspace<span class="Delimiter">(</span>c<span class="Delimiter">))</span> <span class="Delimiter">{</span> @@ -92,7 +92,7 @@ bool code_string<span class="Delimiter">(</span>istream&amp; in<span class="Deli <span class="Comment">// Read a regular string. Regular strings can only contain other regular</span> <span class="Comment">// strings.</span> -void slurp_quoted_comment_oblivious<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostringstream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> +void slurp_quoted_comment_oblivious<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> int brace_depth = <span class="Constant">1</span><span class="Delimiter">;</span> while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> char c = in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> @@ -106,13 +106,13 @@ void slurp_quoted_comment_oblivious<span class="Delimiter">(</span>istream&amp; if <span class="Delimiter">(</span>brace_depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> &amp;&amp; brace_depth &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;unbalanced '['</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;unbalanced '['</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> out<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// Read a code string. Code strings can contain either code or regular strings.</span> -void slurp_quoted_comment_aware<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostringstream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> +void slurp_quoted_comment_aware<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span> char c<span class="Delimiter">;</span> while <span class="Delimiter">(</span>in &gt;&gt; c<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>c == <span class="cSpecial">'\\'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -133,7 +133,7 @@ void slurp_quoted_comment_aware<span class="Delimiter">(</span>istream&amp; in<s out &lt;&lt; c<span class="Delimiter">;</span> if <span class="Delimiter">(</span>c == <span class="Constant">']'</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - raise &lt;&lt; <span class="Constant">&quot;unbalanced '['</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;unbalanced '['</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> out<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">}</span> @@ -142,18 +142,15 @@ if <span class="Delimiter">(</span>s<span class="Delimiter">.</span>at<span clas 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="Comment">// delete [] delimiters</span> s<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> - s<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>s<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">);</span> + strip_last<span class="Delimiter">(</span>s<span class="Delimiter">);</span> name = s<span class="Delimiter">;</span> - types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span>name<span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> - properties<span class="Delimiter">.</span>back<span class="Delimiter">().</span>second<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">);</span> + type = new type_tree<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span>name<span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span><span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">)));</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Comment">//: Two tweaks to printing literal strings compared to other reagents:</span> -<span class="Comment">//: a) Don't print the string twice in the representation, just put '_' in</span> -<span class="Comment">//: the property list.</span> -<span class="Comment">//: b) Escape newlines in the string to make it more friendly to trace().</span> +<span class="Comment">//: Unlike other reagents, escape newlines in literal strings to make them</span> +<span class="Comment">//: more friendly to trace().</span> <span class="Delimiter">:(after &quot;string reagent::to_string()&quot;)</span> if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>*this<span class="Delimiter">))</span> @@ -161,14 +158,14 @@ if <span class="Delimiter">(</span>s<span class="Delimiter">.</span>at<span clas <span class="Delimiter">:(code)</span> bool is_literal_string<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> !x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second &amp;&amp; x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> string emit_literal_string<span class="Delimiter">(</span>string name<span class="Delimiter">)</span> <span class="Delimiter">{</span> size_t pos = <span class="Constant">0</span><span class="Delimiter">;</span> while <span class="Delimiter">(</span>pos != string::npos<span class="Delimiter">)</span> pos = replace<span class="Delimiter">(</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;</span><span class="cSpecial">\\</span><span class="Constant">n&quot;</span><span class="Delimiter">,</span> pos<span class="Delimiter">);</span> - <span class="Identifier">return</span> <span class="Constant">&quot;{name: </span><span class="cSpecial">\&quot;</span><span class="Constant">&quot;</span>+name+<span class="Constant">&quot;</span><span class="cSpecial">\&quot;</span><span class="Constant">, properties: [_: </span><span class="cSpecial">\&quot;</span><span class="Constant">literal-string</span><span class="cSpecial">\&quot;</span><span class="Constant">]}&quot;</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">&quot;{</span><span class="cSpecial">\&quot;</span><span class="Constant">&quot;</span>+name+<span class="Constant">&quot;</span><span class="cSpecial">\&quot;</span><span class="Constant">: </span><span class="cSpecial">\&quot;</span><span class="Constant">literal-string</span><span class="cSpecial">\&quot;</span><span class="Constant">}&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> size_t replace<span class="Delimiter">(</span>string&amp; str<span class="Delimiter">,</span> const string&amp; from<span class="Delimiter">,</span> const string&amp; to<span class="Delimiter">,</span> size_t n<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -178,41 +175,45 @@ size_t replace<span class="Delimiter">(</span>string&amp; str<span class="Delimi <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> +void strip_last<span class="Delimiter">(</span>string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!s<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> s<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>s<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario string_literal_nested)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy [abc [def]] ] -<span class="traceContains">+parse: ingredient: {name: &quot;abc [def]&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;abc [def]&quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(scenario string_literal_escaped)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy [abc \[def] ] -<span class="traceContains">+parse: ingredient: {name: &quot;abc [def&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;abc [def&quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(scenario string_literal_escaped_comment_aware)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy [ abc \\\[def] ] -<span class="traceContains">+parse: ingredient: {name: &quot;\nabc \[def&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;\nabc \[def&quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(scenario string_literal_and_comment)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy [abc] <span class="Comment"># comment</span> ] +<span class="traceContains">+parse: --- defining main</span> <span class="traceContains">+parse: instruction: copy</span> -<span class="traceContains">+parse: ingredient: {name: &quot;abc&quot;, properties: [_: &quot;literal-string&quot;]}</span> -<span class="traceContains">+parse: product: {name: &quot;1&quot;, properties: [&quot;1&quot;: &quot;address&quot;:&quot;array&quot;:&quot;character&quot;]}</span> -<span class="Comment"># no other ingredients</span> -$parse: <span class="Constant">3</span> +<span class="traceContains">+parse: number of ingredients: 1</span> +<span class="traceContains">+parse: ingredient: {&quot;abc&quot;: &quot;literal-string&quot;}</span> +<span class="traceContains">+parse: product: {&quot;1&quot;: &lt;&quot;address&quot; : &lt;&quot;array&quot; : &lt;&quot;character&quot; : &lt;&gt;&gt;&gt;&gt;}</span> <span class="Delimiter">:(scenario string_literal_escapes_newlines_in_trace)</span> recipe main [ copy [abc def] ] -<span class="traceContains">+parse: ingredient: {name: &quot;abc\ndef&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;abc\ndef&quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(scenario string_literal_can_skip_past_comments)</span> recipe main [ @@ -221,13 +222,13 @@ recipe main [ bar ] ] -<span class="traceContains">+parse: ingredient: {name: &quot;\n # ']' inside comment\n bar\n &quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;\n # ']' inside comment\n bar\n &quot;: &quot;literal-string&quot;}</span> <span class="Delimiter">:(scenario string_literal_empty)</span> recipe main [ copy [] ] -<span class="traceContains">+parse: ingredient: {name: &quot;&quot;, properties: [_: &quot;literal-string&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;&quot;: &quot;literal-string&quot;}</span> </pre> </body> </html> diff --git a/html/014literal_noninteger.cc.html b/html/015literal_noninteger.cc.html index eb054c75..4c0f8852 100644 --- a/html/014literal_noninteger.cc.html +++ b/html/015literal_noninteger.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 014literal_noninteger.cc</title> +<title>Mu - 015literal_noninteger.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v1"> <meta name="syntax" content="cpp"> @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -38,14 +38,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3.14159</span> ] -<span class="traceContains">+parse: ingredient: {name: &quot;3.14159&quot;, properties: [&quot;3.14159&quot;: &quot;literal-number&quot;]}</span> +<span class="traceContains">+parse: ingredient: {&quot;3.14159&quot;: &quot;literal-number&quot;}</span> <span class="Delimiter">:(after &quot;Parsing reagent(string s)&quot;)</span> if <span class="Delimiter">(</span>is_noninteger<span class="Delimiter">(</span>s<span class="Delimiter">))</span> <span class="Delimiter">{</span> name = s<span class="Delimiter">;</span> - types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span>name<span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> - properties<span class="Delimiter">.</span>back<span class="Delimiter">().</span>second<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;literal-number&quot;</span><span class="Delimiter">);</span> + type = new type_tree<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span>name<span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span><span class="Constant">&quot;literal-number&quot;</span><span class="Delimiter">)));</span> set_value<span class="Delimiter">(</span>to_double<span class="Delimiter">(</span>s<span class="Delimiter">));</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -53,7 +52,8 @@ if <span class="Delimiter">(</span>is_noninteger<span class="Delimiter">(</span> <span class="Delimiter">:(code)</span> bool is_noninteger<span class="Delimiter">(</span>const string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> s<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789-.&quot;</span><span class="Delimiter">)</span> == string::npos - &amp;&amp; s<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">'.'</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">;</span> + &amp;&amp; s<span class="Delimiter">.</span>find_first_of <span class="Delimiter">(</span><span class="Constant">&quot;0123456789-&quot;</span><span class="Delimiter">)</span> != string::npos + &amp;&amp; std::count<span class="Delimiter">(</span>s<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> s<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> <span class="Constant">'.'</span><span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> double to_double<span class="Delimiter">(</span>string n<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -63,6 +63,16 @@ double to_double<span class="Delimiter">(</span>string n<span class="Delimiter"> assert<span class="Delimiter">(</span>*end == <span class="cSpecial">'\0'</span><span class="Delimiter">);</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> + +void test_is_noninteger<span class="Delimiter">()</span> <span class="Delimiter">{</span> + CHECK<span class="Delimiter">(</span>!is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;1234&quot;</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>!is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;1a2&quot;</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;234.0&quot;</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>!is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;...&quot;</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>!is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;.&quot;</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;2.&quot;</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>is_noninteger<span class="Delimiter">(</span><span class="Constant">&quot;.2&quot;</span><span class="Delimiter">));</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/020run.cc.html b/html/020run.cc.html index 92ad8931..38ffeb73 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -16,9 +16,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .SalientComment { color: #00ffff; } .CommentedCode { color: #6c6c6c; } .PreProc { color: #c000c0; } -.traceAbsent { color: #c00000; } .Delimiter { color: #a04060; } .traceContains { color: #008000; } +.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } @@ -99,10 +99,10 @@ void run_current_routine<span class="Delimiter">()</span> <span class="Comment">// Running One Instruction</span> <span class="CommentedCode">//? Instructions_running[current_recipe_name()]++;</span> if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> ++current_step_index<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - trace<span class="Delimiter">(</span>Initial_callstack_depth+Callstack_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Memory[<span class="Constant">0</span>] != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;something wrote to location 0; this should never happen</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - Memory[<span class="Constant">0</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span>Initial_callstack_depth + Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;something wrote to location 0; this should never happen</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// Read all ingredients from memory.</span> <span class="Comment">// Each ingredient loads a vector of values rather than a single value; mu</span> @@ -120,20 +120,6 @@ void run_current_routine<span class="Delimiter">()</span> switch <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// Primitive Recipe Implementations</span> case COPY: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;ingredients and products should match in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &amp;&amp; is_mu_array<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;can't copy &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot; to array &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>is_mu_array<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &amp;&amp; !is_mu_array<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;can't copy array &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> copy<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> ingredients<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>products<span class="Delimiter">,</span> products<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -142,9 +128,8 @@ void run_current_routine<span class="Delimiter">()</span> cout &lt;&lt; <span class="Constant">&quot;not a primitive op: &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>operation &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - finish_instruction: if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; vs &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;: failed to write to all products! &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; vs &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;: failed to write to all products! &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -171,21 +156,23 @@ inline long long int&amp; current_step_index<span class="Delimiter">()</span> <s <span class="Delimiter">}</span> inline const string&amp; current_recipe_name<span class="Delimiter">()</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-&gt;</span>running_recipe]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>running_recipe<span class="Delimiter">).</span>name<span class="Delimiter">;</span> <span class="Delimiter">}</span> inline const instruction&amp; current_instruction<span class="Delimiter">()</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-&gt;</span>running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>running_step_index<span class="Delimiter">);</span> + <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>running_recipe<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>running_step_index<span class="Delimiter">);</span> <span class="Delimiter">}</span> inline bool routine::completed<span class="Delimiter">()</span> const <span class="Delimiter">{</span> - <span class="Identifier">return</span> running_step_index &gt;= SIZE<span class="Delimiter">(</span>Recipe[running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> + <span class="Identifier">return</span> running_step_index &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> running_recipe<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: Startup flow</span> <span class="Comment">//: Step 1: load all .mu files with numeric prefixes (in order)</span> <span class="Delimiter">:(before &quot;End Load Recipes&quot;)</span> +<span class="CommentedCode">//? Trace_file = &quot;interactive&quot;;</span> +<span class="CommentedCode">//? START_TRACING_UNTIL_END_OF_SCOPE;</span> load_permanently<span class="Delimiter">(</span><span class="Constant">&quot;core.mu&quot;</span><span class="Delimiter">);</span> transform_all<span class="Delimiter">();</span> @@ -203,24 +190,26 @@ if <span class="Delimiter">(</span>argc &gt; <span class="Constant">1</span><spa argc--<span class="Delimiter">;</span> <span class="Delimiter">}</span> transform_all<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">)</span>]<span class="Delimiter">);</span> +<span class="CommentedCode">//? dump_recipe(&quot;handle-keyboard-event&quot;), exit(0);</span> + if <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> string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">)));</span> + <span class="Comment">// End Loading .mu Files</span> <span class="Delimiter">}</span> <span class="Comment">//: Step 3: if we aren't running tests, locate a recipe called 'main' and</span> <span class="Comment">//: start running it.</span> <span class="Delimiter">:(before &quot;End Main&quot;)</span> -if <span class="Delimiter">(</span>!Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span> +if <span class="Delimiter">(</span>!Run_tests &amp;&amp; contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">))</span> &amp;&amp; contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">))))</span> <span class="Delimiter">{</span> setup<span class="Delimiter">();</span> <span class="CommentedCode">//? Trace_file = &quot;interactive&quot;;</span> <span class="CommentedCode">//? START_TRACING_UNTIL_END_OF_SCOPE;</span> -<span class="CommentedCode">//? Trace_stream-&gt;collect_layers.insert(&quot;app&quot;);</span> + trace<span class="Delimiter">(</span><span class="Constant">9990</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;=== Starting to run&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> run_main<span class="Delimiter">(</span>argc<span class="Delimiter">,</span> argv<span class="Delimiter">);</span> teardown<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> void run_main<span class="Delimiter">(</span>int argc<span class="Delimiter">,</span> char* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - recipe_ordinal r = Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span> + recipe_ordinal r = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">));</span> if <span class="Delimiter">(</span>r<span class="Delimiter">)</span> run<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -261,10 +250,11 @@ void load_permanently<span class="Delimiter">(</span>string filename<span class= ifstream fin<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">());</span> fin<span class="Delimiter">.</span>peek<span class="Delimiter">();</span> if <span class="Delimiter">(</span>!fin<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;no such file &quot;</span> &lt;&lt; filename &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;no such file &quot;</span> &lt;&lt; filename &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> fin &gt;&gt; std::noskipws<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9990</span><span class="Delimiter">,</span> <span class="Constant">&quot;load&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;=== &quot;</span> &lt;&lt; filename &lt;&lt; end<span class="Delimiter">();</span> load<span class="Delimiter">(</span>fin<span class="Delimiter">);</span> fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span> <span class="Comment">// freeze everything so it doesn't get cleared by tests</span> @@ -292,6 +282,7 @@ void load_all_permanently<span class="Delimiter">(</span>string dir<span class=" <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Includes&quot;)</span> <span class="PreProc">#include</span><span class="Constant">&lt;dirent.h&gt;</span> +<span class="PreProc">#include</span><span class="Constant">&lt;sys/stat.h&gt;</span> <span class="SalientComment">//:: Reading from memory, writing to memory.</span> @@ -305,59 +296,69 @@ vector&lt;double&gt; read_memory<span class="Delimiter">(</span>reagent x<span c long long int base = x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> long long int size = size_of<span class="Delimiter">(</span>x<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int offset = <span class="Constant">0</span><span class="Delimiter">;</span> offset &lt; size<span class="Delimiter">;</span> ++offset<span class="Delimiter">)</span> <span class="Delimiter">{</span> - double val = Memory[base+offset]<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; base+offset &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; val &lt;&lt; end<span class="Delimiter">();</span> + double val = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base+offset<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; base+offset &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>val<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>val<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> void write_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter">,</span> vector&lt;double&gt; data<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't write to &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;; no type</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> if <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> long long int base = x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> if <span class="Delimiter">(</span>size_mismatch<span class="Delimiter">(</span>x<span class="Delimiter">,</span> data<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: size mismatch in storing to &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; (&quot;</span> &lt;&lt; size_of<span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; vs &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;) at '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;size mismatch in storing to &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; (&quot;</span> &lt;&lt; size_of<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; vs &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;) at '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> for <span class="Delimiter">(</span>long long int offset = <span class="Constant">0</span><span class="Delimiter">;</span> offset &lt; SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> ++offset<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;storing &quot;</span> &lt;&lt; data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; in location &quot;</span> &lt;&lt; base+offset &lt;&lt; end<span class="Delimiter">();</span> - Memory[base+offset] = data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>base+offset == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;storing &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot; in location &quot;</span> &lt;&lt; base+offset &lt;&lt; end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base+offset<span class="Delimiter">,</span> data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> long long int size_of<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + if <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="Comment">// End size_of(reagent) Cases</span> - <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">);</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> -long long int size_of<span class="Delimiter">(</span>const vector&lt;type_ordinal&gt;&amp; types<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Comment">// End size_of(types) Cases</span> +long long int size_of<span class="Delimiter">(</span>const type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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="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> bool size_mismatch<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">,</span> const vector&lt;double&gt;&amp; data<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <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="Comment">// End size_mismatch(x) Cases</span> <span class="CommentedCode">//? if (size_of(x) != SIZE(data)) cerr &lt;&lt; size_of(x) &lt;&lt; &quot; vs &quot; &lt;&lt; SIZE(data) &lt;&lt; '\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> <span class="Delimiter">}</span> -bool is_dummy<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +inline bool is_dummy<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> x<span class="Delimiter">.</span>name == <span class="Constant">&quot;_&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -bool is_literal<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">)</span> == <span class="Constant">1</span> &amp;&amp; r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">;</span> +inline bool is_literal<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> + assert<span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left &amp;&amp; !r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -bool is_mu_array<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> !r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">&quot;array&quot;</span>]<span class="Delimiter">;</span> +inline bool scalar<span class="Delimiter">(</span>const vector&lt;long long int&gt;&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>x<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +inline bool scalar<span class="Delimiter">(</span>const vector&lt;double&gt;&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>x<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> <span class="Comment">// helper for tests</span> void run<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> vector&lt;recipe_ordinal&gt; tmp = load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> @@ -383,32 +384,12 @@ recipe main [ <span class="traceContains">+run: _ &lt;- copy 0</span> <span class="Delimiter">:(scenario write_to_0_disallowed)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ - <span class="Constant">0</span><span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">0</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> ] <span class="traceAbsent">-mem: storing 34 in location 0</span> -<span class="Delimiter">:(scenario copy_checks_reagent_count)</span> -<span class="Special">% Hide_warnings = true;</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> -] -<span class="traceContains">+warn: ingredients and products should match in '1:number &lt;- copy 34, 35'</span> - -<span class="Delimiter">:(scenario write_scalar_to_array_disallowed)</span> -<span class="Special">% Hide_warnings = true;</span> -recipe main [ - <span class="Constant">1</span>:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> -] -<span class="traceContains">+warn: can't copy 34 to array 1:array:number</span> - -<span class="Delimiter">:(scenario write_scalar_to_array_disallowed_2)</span> -<span class="Special">% Hide_warnings = true;</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> -] -<span class="traceContains">+warn: can't copy 35 to array 2:array:number</span> - <span class="Comment">//: mu is robust to various combinations of commas and spaces. You just have</span> <span class="Comment">//: to put spaces around the '&lt;-'.</span> diff --git a/html/021arithmetic.cc.html b/html/021arithmetic.cc.html deleted file mode 100644 index 7575dd28..00000000 --- a/html/021arithmetic.cc.html +++ /dev/null @@ -1,266 +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 - 021arithmetic.cc</title> -<meta name="Generator" content="Vim/7.4"> -<meta name="plugin-version" content="vim7.4_v1"> -<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-family: monospace; color: #eeeeee; background-color: #080808; } -* { font-size: 1.05em; } -.cSpecial { color: #008000; } -.traceContains { color: #008000; } -.Comment { color: #9090ff; } -.Delimiter { color: #a04060; } -.Special { color: #ff6060; } -.Identifier { color: #804000; } -.Constant { color: #00a0a0; } ---> -</style> - -<script type='text/javascript'> -<!-- - ---> -</script> -</head> -<body> -<pre id='vimCodeElement'> -<span class="Comment">//: Arithmetic primitives</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -ADD<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;add&quot;</span>] = ADD<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case ADD: <span class="Delimiter">{</span> - double result = <span class="Constant">0</span><span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'add' requires number ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - result += ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario add_literal)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">34</span> -] -<span class="traceContains">+mem: storing 57 in location 1</span> - -<span class="Delimiter">:(scenario add)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number -] -<span class="traceContains">+mem: storing 57 in location 3</span> - -<span class="Delimiter">:(scenario add_multiple)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">5</span> -] -<span class="traceContains">+mem: storing 12 in location 1</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -SUBTRACT<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;subtract&quot;</span>] = SUBTRACT<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case SUBTRACT: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'subtract' has no ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'subtract' requires number ingredients, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - double result = 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> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'subtract' requires number ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - result -= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario subtract_literal)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>subtract <span class="Constant">5</span><span class="Delimiter">,</span> <span class="Constant">2</span> -] -<span class="traceContains">+mem: storing 3 in location 1</span> - -<span class="Delimiter">:(scenario subtract)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>subtract <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number -] -<span class="traceContains">+mem: storing -11 in location 3</span> - -<span class="Delimiter">:(scenario subtract_multiple)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>subtract <span class="Constant">6</span><span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">2</span> -] -<span class="traceContains">+mem: storing 1 in location 1</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -MULTIPLY<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;multiply&quot;</span>] = MULTIPLY<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case MULTIPLY: <span class="Delimiter">{</span> - double result = <span class="Constant">1</span><span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'multiply' requires number ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - result *= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario multiply_literal)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>multiply <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">3</span> -] -<span class="traceContains">+mem: storing 6 in location 1</span> - -<span class="Delimiter">:(scenario multiply)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">4</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">6</span> - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>multiply <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number -] -<span class="traceContains">+mem: storing 24 in location 3</span> - -<span class="Delimiter">:(scenario multiply_multiple)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>multiply <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> -] -<span class="traceContains">+mem: storing 24 in location 1</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -DIVIDE<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;divide&quot;</span>] = DIVIDE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case DIVIDE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'divide' has no ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'divide' requires number ingredients, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - double result = 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> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'divide' requires number ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - result /= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario divide_literal)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">8</span><span class="Delimiter">,</span> <span class="Constant">2</span> -] -<span class="traceContains">+mem: storing 4 in location 1</span> - -<span class="Delimiter">:(scenario divide)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">27</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span> - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number -] -<span class="traceContains">+mem: storing 9 in location 3</span> - -<span class="Delimiter">:(scenario divide_multiple)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">12</span><span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">2</span> -] -<span class="traceContains">+mem: storing 2 in location 1</span> - -<span class="Comment">//: Integer division</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -DIVIDE_WITH_REMAINDER<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;divide-with-remainder&quot;</span>] = DIVIDE_WITH_REMAINDER<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case DIVIDE_WITH_REMAINDER: <span class="Delimiter">{</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'divide-with-remainder' requires exactly two ingredients, but got '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> || !scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'divide-with-remainder' requires number ingredients, but got '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - long long int quotient = 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>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> - long long int remainder = static_cast&lt;long long int&gt;<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> % static_cast&lt;long long int&gt;<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="Comment">// very large integers will lose precision</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>quotient<span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>remainder<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario divide_with_remainder_literal)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">9</span><span class="Delimiter">,</span> <span class="Constant">2</span> -] -<span class="traceContains">+mem: storing 4 in location 1</span> -<span class="traceContains">+mem: storing 1 in location 2</span> - -<span class="Delimiter">:(scenario divide_with_remainder)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">27</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">11</span> - <span class="Constant">3</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number -] -<span class="traceContains">+mem: storing 2 in location 3</span> -<span class="traceContains">+mem: storing 5 in location 4</span> - -<span class="Delimiter">:(scenario divide_with_decimal_point)</span> -recipe main [ - <span class="Comment"># todo: literal floats?</span> - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">5</span><span class="Delimiter">,</span> <span class="Constant">2</span> -] -<span class="traceContains">+mem: storing 2.5 in location 1</span> - -<span class="Delimiter">:(code)</span> -inline bool scalar<span class="Delimiter">(</span>const vector&lt;long long int&gt;&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>x<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -inline bool scalar<span class="Delimiter">(</span>const vector&lt;double&gt;&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>x<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/021check_instruction.cc.html b/html/021check_instruction.cc.html new file mode 100644 index 00000000..f0238926 --- /dev/null +++ b/html/021check_instruction.cc.html @@ -0,0 +1,183 @@ +<!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 - 021check_instruction.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Identifier { color: #804000; } +.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Introduce a new transform to perform various checks in instructions before</span> +<span class="Comment">//: we start running them. It'll be extensible, so that we can add checks for</span> +<span class="Comment">//: new recipes as we extend 'run' to support them.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Doing checking in a separate part complicates things, because the values</span> +<span class="Comment">//: of variables in memory and the processor (current_recipe_name,</span> +<span class="Comment">//: current_instruction) aren't available at checking time. If I had a more</span> +<span class="Comment">//: sophisticated layer system I'd introduce the simpler version first and</span> +<span class="Comment">//: transform it in a separate layer or set of layers.</span> + +<span class="Delimiter">:(after &quot;Transform.push_back(update_instruction_operations)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_instruction<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void check_instruction<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- perform checks for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- perform checks for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> + map&lt;string<span class="Delimiter">,</span> vector&lt;type_ordinal&gt; &gt; metadata<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + switch <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// Primitive Recipe Checks</span> + case COPY: <span class="Delimiter">{</span> + if <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_error &lt;&lt; <span class="Constant">&quot;ingredients and products should match in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<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> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;can't copy &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;; types don't match</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Primitive Recipe Checks</span> + default: <span class="Delimiter">{</span> + <span class="Comment">// Defined Recipe Checks</span> + <span class="Comment">// End Defined Recipe Checks</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + finish_checking_instruction:<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario copy_checks_reagent_count)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </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 &lt;- copy 34, 35'</span> + +<span class="Delimiter">:(scenario write_scalar_to_array_disallowed)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+error: main: can't copy 34 to 1:array:number; types don't match</span> + +<span class="Delimiter">:(scenario write_scalar_to_array_disallowed_2)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> +] +<span class="traceContains">+error: main: can't copy 35 to 2:array:number; types don't match</span> + +<span class="Delimiter">:(scenario write_scalar_to_address_disallowed)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+error: main: can't copy 34 to 1:address:number; types don't match</span> + +<span class="Delimiter">:(code)</span> +bool types_match<span class="Delimiter">(</span>reagent lhs<span class="Delimiter">,</span> reagent rhs<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// '_' never raises type error</span> + if <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Comment">// to sidestep type-checking, use /raw in the source.</span> + <span class="Comment">// this is unsafe, and will be highlighted in red inside vim. just for some tests.</span> + if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>rhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Comment">// allow writing 0 to any address</span> + if <span class="Delimiter">(</span>rhs<span class="Delimiter">.</span>name == <span class="Constant">&quot;0&quot;</span> &amp;&amp; is_mu_address<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>rhs<span class="Delimiter">))</span> <span class="Identifier">return</span> !is_mu_array<span class="Delimiter">(</span>lhs<span class="Delimiter">)</span> &amp;&amp; !is_mu_address<span class="Delimiter">(</span>lhs<span class="Delimiter">)</span> &amp;&amp; size_of<span class="Delimiter">(</span>rhs<span class="Delimiter">)</span> == size_of<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!lhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> !rhs<span class="Delimiter">.</span>type<span class="Delimiter">;</span> + <span class="Identifier">return</span> types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">,</span> rhs<span class="Delimiter">.</span>type<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">// two types match if the second begins like the first</span> +<span class="Comment">// (trees perform the same check recursively on each subtree)</span> +bool types_match<span class="Delimiter">(</span>type_tree* lhs<span class="Delimiter">,</span> type_tree* rhs<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!lhs<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!rhs || rhs<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>lhs<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>lhs<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>rhs<span class="Delimiter">)</span> == size_of<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>lhs<span class="Delimiter">-&gt;</span>value != rhs<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> rhs<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> &amp;&amp; types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> rhs<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">// hacky version that allows 0 addresses</span> +bool types_match<span class="Delimiter">(</span>const reagent lhs<span class="Delimiter">,</span> const type_tree* rhs<span class="Delimiter">,</span> const vector&lt;double&gt;&amp; data<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>rhs<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> scalar<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &amp;&amp; data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>rhs<span class="Delimiter">)</span> == size_of<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value != rhs<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> rhs<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> &amp;&amp; types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> rhs<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_raw<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">&quot;raw&quot;</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_mu_array<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_mu_address<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_mu_number<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;literal-number&quot;</span> + || r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;literal&quot;</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;character&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// permit arithmetic on unicode code points</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_mu_scalar<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> + <span class="Identifier">return</span> !r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second || r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value != <span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_mu_array<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>r<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/022arithmetic.cc.html b/html/022arithmetic.cc.html new file mode 100644 index 00000000..0a353d6d --- /dev/null +++ b/html/022arithmetic.cc.html @@ -0,0 +1,353 @@ +<!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 - 022arithmetic.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.cSpecial { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.Identifier { color: #804000; } +.Constant { color: #00a0a0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Arithmetic primitives</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +ADD<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;add&quot;</span><span class="Delimiter">,</span> ADD<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case ADD: <span class="Delimiter">{</span> + <span class="Comment">// primary goal of these checks is to forbid address arithmetic</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'add' requires number ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'add' yields exactly one product in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; !is_dummy<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> &amp;&amp; !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'add' should yield a number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case ADD: <span class="Delimiter">{</span> + double result = <span class="Constant">0</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result += ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario add_literal)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">34</span> +] +<span class="traceContains">+mem: storing 57 in location 1</span> + +<span class="Delimiter">:(scenario add)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +<span class="traceContains">+mem: storing 57 in location 3</span> + +<span class="Delimiter">:(scenario add_multiple)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +<span class="traceContains">+mem: storing 12 in location 1</span> + +<span class="Delimiter">:(scenario add_checks_type)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span>:boolean<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+error: main: 'add' requires number ingredients, but got 2:boolean</span> + +<span class="Delimiter">:(scenario add_checks_return_type)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+error: main: 'add' should yield a number, but got 1:address:number</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +SUBTRACT<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;subtract&quot;</span><span class="Delimiter">,</span> SUBTRACT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SUBTRACT: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'subtract' has no ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_raw<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="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// permit address offset computations in tests</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'subtract' requires number ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'subtract' yields exactly one product in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; !is_dummy<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> &amp;&amp; !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'subtract' should yield a number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case SUBTRACT: <span class="Delimiter">{</span> + double result = 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> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + result -= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + 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">:(scenario subtract_literal)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>subtract <span class="Constant">5</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 3 in location 1</span> + +<span class="Delimiter">:(scenario subtract)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>subtract <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +<span class="traceContains">+mem: storing -11 in location 3</span> + +<span class="Delimiter">:(scenario subtract_multiple)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>subtract <span class="Constant">6</span><span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 1 in location 1</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +MULTIPLY<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;multiply&quot;</span><span class="Delimiter">,</span> MULTIPLY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MULTIPLY: <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'multiply' requires number ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'multiply' yields exactly one product in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; !is_dummy<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> &amp;&amp; !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'multiply' should yield a number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case MULTIPLY: <span class="Delimiter">{</span> + double result = <span class="Constant">1</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result *= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario multiply_literal)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>multiply <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">3</span> +] +<span class="traceContains">+mem: storing 6 in location 1</span> + +<span class="Delimiter">:(scenario multiply)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">4</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">6</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>multiply <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +<span class="traceContains">+mem: storing 24 in location 3</span> + +<span class="Delimiter">:(scenario multiply_multiple)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>multiply <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> +] +<span class="traceContains">+mem: storing 24 in location 1</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +DIVIDE<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;divide&quot;</span><span class="Delimiter">,</span> DIVIDE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case DIVIDE: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide' has no ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide' requires number ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide' yields exactly one product in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; !is_dummy<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> &amp;&amp; !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide' should yield a number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case DIVIDE: <span class="Delimiter">{</span> + double result = 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> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + result /= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + 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">:(scenario divide_literal)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">8</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 4 in location 1</span> + +<span class="Delimiter">:(scenario divide)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">27</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +<span class="traceContains">+mem: storing 9 in location 3</span> + +<span class="Delimiter">:(scenario divide_multiple)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">12</span><span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 2 in location 1</span> + +<span class="Comment">//: Integer division</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +DIVIDE_WITH_REMAINDER<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;divide-with-remainder&quot;</span><span class="Delimiter">,</span> DIVIDE_WITH_REMAINDER<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case DIVIDE_WITH_REMAINDER: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide-with-remainder' requires exactly two ingredients, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> || !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide-with-remainder' requires number ingredients, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide-with-remainder' yields two products in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> &amp;&amp; !is_mu_number<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> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'divide-with-remainder' should yield a number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case DIVIDE_WITH_REMAINDER: <span class="Delimiter">{</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> + long long int a = static_cast&lt;long long int&gt;<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> + long long int b = static_cast&lt;long long int&gt;<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> + if <span class="Delimiter">(</span>b == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;divide by zero in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + long long int quotient = a / b<span class="Delimiter">;</span> + long long int remainder = a % b<span class="Delimiter">;</span> + <span class="Comment">// very large integers will lose precision</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>quotient<span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>remainder<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario divide_with_remainder_literal)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">9</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 4 in location 1</span> +<span class="traceContains">+mem: storing 1 in location 2</span> + +<span class="Delimiter">:(scenario divide_with_remainder)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">27</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">11</span> + <span class="Constant">3</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +<span class="traceContains">+mem: storing 2 in location 3</span> +<span class="traceContains">+mem: storing 5 in location 4</span> + +<span class="Delimiter">:(scenario divide_with_decimal_point)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">5</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 2.5 in location 1</span> + +<span class="Delimiter">:(scenario divide_by_zero)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> +] +<span class="traceContains">+mem: storing inf in location 1</span> + +<span class="Delimiter">:(scenario divide_by_zero_2)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> +] +<span class="Comment"># integer division can't return floating-point infinity</span> +<span class="traceContains">+error: main: divide by zero in '1:number &lt;- divide-with-remainder 4, 0'</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/022boolean.cc.html b/html/023boolean.cc.html index f1c0b5b2..1daa8686 100644 --- a/html/022boolean.cc.html +++ b/html/023boolean.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 022boolean.cc</title> +<title>Mu - 023boolean.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v1"> <meta name="syntax" content="cpp"> @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -36,17 +36,22 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> AND<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;and&quot;</span>] = AND<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;and&quot;</span><span class="Delimiter">,</span> AND<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case AND: <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_scalar<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> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'and' requires boolean ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case AND: <span class="Delimiter">{</span> bool result = <span class="Constant">true</span><span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'and' requires boolean ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> result = result &amp;&amp; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -81,17 +86,22 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> OR<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;or&quot;</span>] = OR<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;or&quot;</span><span class="Delimiter">,</span> OR<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case OR: <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_scalar<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> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'and' requires boolean ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case OR: <span class="Delimiter">{</span> bool result = <span class="Constant">false</span><span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'or' requires boolean ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> result = result || ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -126,15 +136,25 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> NOT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;not&quot;</span>] = NOT<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;not&quot;</span><span class="Delimiter">,</span> NOT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case NOT: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'not' cannot have fewer ingredients than products in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_scalar<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> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'not' requires boolean ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case NOT: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">));</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'not' requires boolean ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> - <span class="Delimiter">}</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>!ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> diff --git a/html/023jump.cc.html b/html/024jump.cc.html index 9e239685..8f392805 100644 --- a/html/023jump.cc.html +++ b/html/024jump.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 023jump.cc</title> +<title>Mu - 024jump.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v1"> <meta name="syntax" content="cpp"> @@ -13,6 +13,7 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } @@ -20,7 +21,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -46,26 +46,30 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> JUMP<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;jump&quot;</span>] = JUMP<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;jump&quot;</span><span class="Delimiter">,</span> JUMP<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case JUMP: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'jump' should be a label or offset, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_scalar<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'jump' should be a label or offset, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case JUMP: <span class="Delimiter">{</span> assert<span class="Delimiter">(</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>initialized<span class="Delimiter">);</span> current_step_index<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="Constant">1</span><span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jumping to instruction &quot;</span> &lt;&lt; current_step_index<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jumping to instruction &quot;</span> &lt;&lt; current_step_index<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// skip rest of this instruction</span> <span class="Delimiter">}</span> <span class="Comment">//: special type to designate jump targets</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -Type_ordinal[<span class="Constant">&quot;offset&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;offset&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">:(scenario jump_backward)</span> recipe main [ @@ -81,28 +85,32 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> JUMP_IF<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;jump-if&quot;</span>] = JUMP_IF<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;jump-if&quot;</span><span class="Delimiter">,</span> JUMP_IF<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case JUMP_IF: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump-if' requires exactly two ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump-if' requires exactly two ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump-if' requires a boolean for its first ingredient, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_scalar<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump-if' requires a boolean for its first ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump-if' requires a label or offset for its second ingredient, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_scalar<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump-if' requires a label or offset for its second ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case JUMP_IF: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>initialized<span class="Delimiter">);</span> if <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> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump-if fell through&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump-if fell through&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> current_step_index<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="Constant">1</span><span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jumping to instruction &quot;</span> &lt;&lt; current_step_index<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jumping to instruction &quot;</span> &lt;&lt; current_step_index<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// skip rest of this instruction</span> <span class="Delimiter">}</span> @@ -129,28 +137,32 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> JUMP_UNLESS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;jump-unless&quot;</span>] = JUMP_UNLESS<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;jump-unless&quot;</span><span class="Delimiter">,</span> JUMP_UNLESS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case JUMP_UNLESS: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump-unless' requires exactly two ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump-unless' requires exactly two ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump-unless' requires a boolean for its first ingredient, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_scalar<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump-unless' requires a boolean for its first ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'jump-unless' requires a label or offset for its second ingredient, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_scalar<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'jump-unless' requires a label or offset for its second ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case JUMP_UNLESS: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>initialized<span class="Delimiter">);</span> if <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> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump-unless fell through&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump-unless fell through&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> current_step_index<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="Constant">1</span><span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jumping to instruction &quot;</span> &lt;&lt; current_step_index<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jumping to instruction &quot;</span> &lt;&lt; current_step_index<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// skip rest of this instruction</span> <span class="Delimiter">}</span> diff --git a/html/024compare.cc.html b/html/025compare.cc.html index 1fb7c4a5..9d4fc286 100644 --- a/html/024compare.cc.html +++ b/html/025compare.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 024compare.cc</title> +<title>Mu - 025compare.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v1"> <meta name="syntax" content="cpp"> @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -36,13 +36,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> EQUAL<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;equal&quot;</span>] = EQUAL<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;equal&quot;</span><span class="Delimiter">,</span> EQUAL<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case EQUAL: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'equal' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'equal' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case EQUAL: <span class="Delimiter">{</span> vector&lt;double&gt;&amp; exemplar = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> bool result = <span class="Constant">true</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -91,26 +95,29 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> GREATER_THAN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;greater-than&quot;</span>] = GREATER_THAN<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;greater-than&quot;</span><span class="Delimiter">,</span> GREATER_THAN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case GREATER_THAN: <span class="Delimiter">{</span> - bool result = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'greater-than' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'greater-than' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'greater-than' can only compare numbers; got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_greater_than<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'greater-than' can only compare numbers; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case GREATER_THAN: <span class="Delimiter">{</span> + bool result = <span class="Constant">true</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Comment">/**/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i-<span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt;= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> result = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - finish_greater_than: 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> @@ -147,26 +154,29 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> LESSER_THAN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;lesser-than&quot;</span>] = LESSER_THAN<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;lesser-than&quot;</span><span class="Delimiter">,</span> LESSER_THAN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case LESSER_THAN: <span class="Delimiter">{</span> - bool result = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'lesser-than' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'lesser-than' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'lesser-than' can only compare numbers; got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_lesser_than<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'lesser-than' can only compare numbers; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case LESSER_THAN: <span class="Delimiter">{</span> + bool result = <span class="Constant">true</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Comment">/**/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i-<span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> result = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - finish_lesser_than: 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> @@ -203,26 +213,29 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> GREATER_OR_EQUAL<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;greater-or-equal&quot;</span>] = GREATER_OR_EQUAL<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;greater-or-equal&quot;</span><span class="Delimiter">,</span> GREATER_OR_EQUAL<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case GREATER_OR_EQUAL: <span class="Delimiter">{</span> - bool result = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'greater-or-equal' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'greater-or-equal' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'greater-or-equal' can only compare numbers; got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_greater_or_equal<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'greater-or-equal' can only compare numbers; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case GREATER_OR_EQUAL: <span class="Delimiter">{</span> + bool result = <span class="Constant">true</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Comment">/**/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i-<span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> result = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - finish_greater_or_equal: 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> @@ -267,26 +280,29 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> LESSER_OR_EQUAL<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;lesser-or-equal&quot;</span>] = LESSER_OR_EQUAL<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;lesser-or-equal&quot;</span><span class="Delimiter">,</span> LESSER_OR_EQUAL<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case LESSER_OR_EQUAL: <span class="Delimiter">{</span> - bool result = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'lesser-or-equal' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt;= <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'lesser-or-equal' needs at least two ingredients to compare in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'lesser-or-equal' can only compare numbers; got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_lesser_or_equal<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'lesser-or-equal' can only compare numbers; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_checking_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case LESSER_OR_EQUAL: <span class="Delimiter">{</span> + bool result = <span class="Constant">true</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Comment">/**/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i-<span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> result = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - finish_lesser_or_equal: 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> diff --git a/html/029tools.cc.html b/html/029tools.cc.html index 77e709c2..018e0f01 100644 --- a/html/029tools.cc.html +++ b/html/029tools.cc.html @@ -13,12 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } +.traceContains { color: #008000; } .SalientComment { color: #00ffff; } -.Special { color: #ff6060; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } -.traceContains { color: #008000; } +.Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } --> @@ -43,22 +43,26 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> TRACE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;trace&quot;</span>] = TRACE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;trace&quot;</span><span class="Delimiter">,</span> TRACE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case TRACE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &lt; <span class="Constant">3</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'trace' takes three or more ingredients rather than '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt; <span class="Constant">3</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'trace' takes three or more ingredients rather than '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'trace' should be a number (depth), but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'trace' should be a number (depth), but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int depth = 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> - if <span class="Delimiter">(</span>!is_literal_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'trace' should be a literal string (label), but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'trace' should be a literal string (label), but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case TRACE: <span class="Delimiter">{</span> + long long int depth = 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> string label = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">;</span> ostringstream out<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">2</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -73,14 +77,18 @@ case TRACE: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> STASH<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;stash&quot;</span>] = STASH<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;stash&quot;</span><span class="Delimiter">,</span> STASH<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case STASH: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case STASH: <span class="Delimiter">{</span> ostringstream out<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> out &lt;&lt; print_mu<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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">1</span><span class="Delimiter">,</span> <span class="Constant">&quot;app&quot;</span><span class="Delimiter">)</span> &lt;&lt; out<span class="Delimiter">.</span>str<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">&quot;app&quot;</span><span class="Delimiter">)</span> &lt;&lt; out<span class="Delimiter">.</span>str<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -110,63 +118,53 @@ string print_mu<span class="Delimiter">(</span>const reagent&amp; r<span class=" <span class="Comment">// End print Special-cases(reagent r, data)</span> ostringstream out<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - out &lt;&lt; data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> + out &lt;&lt; no_scientific<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -HIDE_WARNINGS<span class="Delimiter">,</span> +HIDE_ERRORS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;hide-warnings&quot;</span>] = HIDE_WARNINGS<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;hide-errors&quot;</span><span class="Delimiter">,</span> HIDE_ERRORS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case HIDE_ERRORS: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case HIDE_WARNINGS: <span class="Delimiter">{</span> +case HIDE_ERRORS: <span class="Delimiter">{</span> + Hide_errors = <span class="Constant">true</span><span class="Delimiter">;</span> Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -SHOW_WARNINGS<span class="Delimiter">,</span> +SHOW_ERRORS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;show-warnings&quot;</span>] = SHOW_WARNINGS<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case SHOW_WARNINGS: <span class="Delimiter">{</span> - Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;show-errors&quot;</span><span class="Delimiter">,</span> SHOW_ERRORS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SHOW_ERRORS: <span class="Delimiter">{</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -_START_TRACING<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$start-tracing&quot;</span>] = _START_TRACING<span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case _START_TRACING: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - Trace_stream<span class="Delimiter">-&gt;</span>dump_layer = <span class="Constant">&quot;all&quot;</span><span class="Delimiter">;</span> - else - Trace_stream<span class="Delimiter">-&gt;</span>dump_layer = 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="Delimiter">;</span> +case SHOW_ERRORS: <span class="Delimiter">{</span> + Hide_errors = <span class="Constant">false</span><span class="Delimiter">;</span> + Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -_STOP_TRACING<span class="Delimiter">,</span> +TRACE_UNTIL<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$stop-tracing&quot;</span>] = _STOP_TRACING<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case _STOP_TRACING: <span class="Delimiter">{</span> - Trace_stream<span class="Delimiter">-&gt;</span>dump_layer = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;trace-until&quot;</span><span class="Delimiter">,</span> TRACE_UNTIL<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case TRACE_UNTIL: <span class="Delimiter">{</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -_CLOSE_TRACE<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$close-trace&quot;</span>] = _CLOSE_TRACE<span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case _CLOSE_TRACE: <span class="Delimiter">{</span> +case TRACE_UNTIL: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> - delete Trace_stream<span class="Delimiter">;</span> - Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-&gt;</span>collect_depth = 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> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -174,7 +172,11 @@ case _CLOSE_TRACE: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _DUMP_TRACE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$dump-trace&quot;</span>] = _DUMP_TRACE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$dump-trace&quot;</span><span class="Delimiter">,</span> _DUMP_TRACE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _DUMP_TRACE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _DUMP_TRACE: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> @@ -189,42 +191,68 @@ case _DUMP_TRACE: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _CLEAR_TRACE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$clear-trace&quot;</span>] = _CLEAR_TRACE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$clear-trace&quot;</span><span class="Delimiter">,</span> _CLEAR_TRACE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _CLEAR_TRACE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _CLEAR_TRACE: <span class="Delimiter">{</span> - CLEAR_TRACE<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +_SAVE_TRACE<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$save-trace&quot;</span><span class="Delimiter">,</span> _SAVE_TRACE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _SAVE_TRACE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case _SAVE_TRACE: <span class="Delimiter">{</span> + if <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> + fout &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>readable_contents<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span> + <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">//: assert: perform sanity checks at runtime</span> <span class="Delimiter">:(scenario assert)</span> -<span class="Special">% Hide_warnings = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line.</span> +<span class="Special">% Hide_errors = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line.</span> recipe main [ assert <span class="Constant">0</span><span class="Delimiter">,</span> [this is an assert in mu] ] -<span class="traceContains">+warn: this is an assert in mu</span> +<span class="traceContains">+error: this is an assert in mu</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> ASSERT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;assert&quot;</span>] = ASSERT<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;assert&quot;</span><span class="Delimiter">,</span> ASSERT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case ASSERT: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'assert' takes exactly two ingredients rather than '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'assert' takes exactly two ingredients rather than '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'assert' requires a boolean for its first ingredient, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_scalar<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'assert' requires a boolean for its first ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'assert' requires a literal string for its second ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'assert' requires a literal string for its second ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case ASSERT: <span class="Delimiter">{</span> if <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 &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -234,12 +262,16 @@ case ASSERT: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _PRINT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$print&quot;</span>] = _PRINT<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$print&quot;</span><span class="Delimiter">,</span> _PRINT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _PRINT: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _PRINT: <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>current_instruction<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>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;$print: &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;$print: &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">&quot;newline&quot;</span><span class="Delimiter">))</span> cout &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> else @@ -247,9 +279,9 @@ case _PRINT: <span class="Delimiter">{</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;$print: &quot;</span> &lt;&lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;$print: &quot;</span> &lt;&lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>j &gt; <span class="Constant">0</span><span class="Delimiter">)</span> cout &lt;&lt; <span class="Constant">&quot; &quot;</span><span class="Delimiter">;</span> - cout &lt;&lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> + cout &lt;&lt; no_scientific<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -259,7 +291,11 @@ case _PRINT: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _EXIT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$exit&quot;</span>] = _EXIT<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$exit&quot;</span><span class="Delimiter">,</span> _EXIT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _EXIT: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _EXIT: <span class="Delimiter">{</span> exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> @@ -269,25 +305,31 @@ case _EXIT: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _SYSTEM<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$system&quot;</span>] = _SYSTEM<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$system&quot;</span><span class="Delimiter">,</span> _SYSTEM<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case _SYSTEM: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: '$system' requires exactly one ingredient, but got none</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'$system' requires exactly one ingredient, but got none</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case _SYSTEM: <span class="Delimiter">{</span> int status = system<span class="Delimiter">(</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="Delimiter">.</span>c_str<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>status<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="SalientComment">//:: helpers for debugging</span> - <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _DUMP_MEMORY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$dump-memory&quot;</span>] = _DUMP_MEMORY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$dump-memory&quot;</span><span class="Delimiter">,</span> _DUMP_MEMORY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _DUMP_MEMORY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _DUMP_MEMORY: <span class="Delimiter">{</span> dump_memory<span class="Delimiter">();</span> diff --git a/html/030container.cc.html b/html/030container.cc.html index 7d0d4a26..403c6a60 100644 --- a/html/030container.cc.html +++ b/html/030container.cc.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .SalientComment { color: #00ffff; } -.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } +.traceAbsent { color: #c00000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -37,21 +37,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> <span class="Comment">//: We'll use this container as a running example, with two number elements.</span> -type_ordinal point = Type_ordinal[<span class="Constant">&quot;point&quot;</span>] = Next_type_ordinal++<span class="Delimiter">;</span> -Type[point]<span class="Delimiter">.</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> -Type[point]<span class="Delimiter">.</span>kind = container<span class="Delimiter">;</span> -Type[point]<span class="Delimiter">.</span>name = <span class="Constant">&quot;point&quot;</span><span class="Delimiter">;</span> -vector&lt;type_ordinal&gt; i<span class="Delimiter">;</span> -i<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>number<span class="Delimiter">);</span> -Type[point]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>i<span class="Delimiter">);</span> -Type[point]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +type_ordinal point = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;point&quot;</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> +get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>kind = CONTAINER<span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>name = <span class="Constant">&quot;point&quot;</span><span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new type_tree<span class="Delimiter">(</span>number<span class="Delimiter">));</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;x&quot;</span><span class="Delimiter">);</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new type_tree<span class="Delimiter">(</span>number<span class="Delimiter">));</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;y&quot;</span><span class="Delimiter">);</span> <span class="Comment">//: Containers can be copied around with a single instruction just like</span> <span class="Comment">//: numbers, no matter how large they are.</span> <span class="Comment">//: Tests in this layer often explicitly setup memory before reading it as a</span> <span class="Comment">//: container. Don't do this in general. I'm tagging exceptions with /raw to</span> -<span class="Comment">//: avoid warnings.</span> +<span class="Comment">//: avoid errors.</span> <span class="Delimiter">:(scenario copy_multiple_locations)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> @@ -61,27 +61,25 @@ recipe main [ <span class="traceContains">+mem: storing 34 in location 3</span> <span class="traceContains">+mem: storing 35 in location 4</span> -<span class="Comment">//: trying to copy to a differently-sized destination will fail</span> +<span class="Comment">//: trying to copy to a differently-typed destination will fail</span> <span class="Delimiter">:(scenario copy_checks_size)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">2</span>:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number ] -<span class="traceContains">+warn: main: size mismatch in storing to 2:point (2 vs 1) at '2:point &lt;- copy 1:number'</span> +<span class="traceContains">+error: main: can't copy 1:number to 2:point; types don't match</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> <span class="Comment">// A more complex container, containing another container as one of its</span> <span class="Comment">// elements.</span> -type_ordinal point_number = Type_ordinal[<span class="Constant">&quot;point-number&quot;</span>] = Next_type_ordinal++<span class="Delimiter">;</span> -Type[point_number]<span class="Delimiter">.</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> -Type[point_number]<span class="Delimiter">.</span>kind = container<span class="Delimiter">;</span> -Type[point_number]<span class="Delimiter">.</span>name = <span class="Constant">&quot;point-number&quot;</span><span class="Delimiter">;</span> -vector&lt;type_ordinal&gt; p2<span class="Delimiter">;</span> -p2<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>point<span class="Delimiter">);</span> -Type[point_number]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>p2<span class="Delimiter">);</span> -vector&lt;type_ordinal&gt; i2<span class="Delimiter">;</span> -i2<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>number<span class="Delimiter">);</span> -Type[point_number]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>i2<span class="Delimiter">);</span> +type_ordinal point_number = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;point-number&quot;</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> +get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>kind = CONTAINER<span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>name = <span class="Constant">&quot;point-number&quot;</span><span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new type_tree<span class="Delimiter">(</span>point<span class="Delimiter">));</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;xy&quot;</span><span class="Delimiter">);</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new type_tree<span class="Delimiter">(</span>number<span class="Delimiter">));</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;z&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">:(scenario copy_handles_nested_container_elements)</span> recipe main [ @@ -119,17 +117,26 @@ recipe main [ ] <span class="traceContains">+mem: storing 0 in location 7</span> -<span class="Delimiter">:(before &quot;End size_of(types) Cases&quot;)</span> -type_info t = Type[types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span> -if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == container<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Delimiter">:(before &quot;End size_of(type) Cases&quot;)</span> +if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// error value, but we'll raise it elsewhere</span> + <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>left &amp;&amp; !type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +type_info t = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> +if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// size of a container is the sum of the sizes of its elements</span> long long int result = <span class="Constant">0</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// todo: strengthen assertion to disallow mutual type recursion</span> - if <span class="Delimiter">(</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;container &quot;</span> &lt;&lt; t<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; can't include itself as a member</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>value == type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;container &quot;</span> &lt;&lt; t<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; can't include itself as a member</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + <span class="Comment">// End size_of(type) Container Cases</span> result += size_of<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> @@ -156,48 +163,81 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> GET<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;get&quot;</span>] = GET<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;get&quot;</span><span class="Delimiter">,</span> GET<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case GET: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'get' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'get' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent base = 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> - long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// new copy for every invocation</span> + <span class="Comment">// Update GET base in Check</span> + if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'get' should be a container, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + reagent offset = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>offset<span class="Delimiter">)</span> || !is_mu_scalar<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'get' should have type 'offset', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + long long int offset_value = <span class="Constant">0</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Comment">// later layers permit non-integer offsets</span> + offset_value = to_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + else + offset_value = offset<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>offset_value &lt; <span class="Constant">0</span> || offset_value &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;invalid offset &quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot; for &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || Type[base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>kind != container<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'get' should be a container, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + reagent product = 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="Comment">// Update GET product in Check</span> + const reagent element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> offset_value<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'get' &quot;</span> &lt;&lt; offset<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; (&quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot;) on &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; can't be saved in &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;; type should be &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>product<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - type_ordinal base_type = base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'get' should have type 'offset', but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case GET: <span class="Delimiter">{</span> + reagent base = 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">// Update GET base in Run</span> + long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span> + type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> long long int offset = 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> + if <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// copied from Check above</span> long long int src = base_address<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - src += size_of<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Comment">// End GET field Cases</span> + src += size_of<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: invalid offset &quot;</span> &lt;&lt; offset &lt;&lt; <span class="Constant">&quot; for &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - type_ordinal src_type = Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; Type[src_type]<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> - reagent tmp<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src &lt;&lt; end<span class="Delimiter">();</span> + reagent tmp = element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> offset<span class="Delimiter">);</span> tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span> - tmp<span class="Delimiter">.</span>types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>src_type<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> +const reagent element_type<span class="Delimiter">(</span>const reagent&amp; canonized_base<span class="Delimiter">,</span> long long int offset_value<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>offset_value &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + const type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">);</span> + reagent element<span class="Delimiter">;</span> + element<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>*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> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario get_handles_nested_container_elements)</span> recipe main [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> @@ -207,92 +247,143 @@ recipe main [ ] <span class="traceContains">+mem: storing 36 in location 15</span> -<span class="SalientComment">//:: To write to elements of containers, you need their address.</span> - -<span class="Delimiter">:(scenario get_address)</span> +<span class="Delimiter">:(scenario get_out_of_bounds)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> - <span class="Constant">15</span>:address:number<span class="Special"> &lt;- </span>get-address <span class="Constant">12</span>:point/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:offset <span class="Comment"># unsafe</span> + <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span> + get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:offset <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span> ] -<span class="traceContains">+mem: storing 13 in location 15</span> +<span class="traceContains">+error: main: invalid offset 2 for point-number</span> -<span class="Delimiter">:(scenario get_out_of_bounds)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario get_out_of_bounds_2)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span> - get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:offset <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span> + get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> -<span class="Constant">1</span>:offset ] -<span class="traceContains">+warn: main: invalid offset 2 for point-number</span> +<span class="traceContains">+error: main: invalid offset -1 for point-number</span> -<span class="Delimiter">:(scenario get_out_of_bounds_2)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario get_product_type_mismatch)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span> - get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> -<span class="Constant">1</span>:offset + <span class="Constant">15</span>:address:number<span class="Special"> &lt;- </span>get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+error: main: 'get' 1:offset (1) on point-number can't be saved in 15:address:number; type should be number but is &lt;address : &lt;number : &lt;&gt;&gt;&gt;</span> + +<span class="SalientComment">//:: To write to elements of containers, you need their address.</span> + +<span class="Delimiter">:(scenario get_address)</span> +recipe main [ + <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> + <span class="Constant">15</span>:address:number<span class="Special"> &lt;- </span>get-address <span class="Constant">12</span>:point/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:offset <span class="Comment"># unsafe</span> ] -<span class="traceContains">+warn: main: invalid offset -1 for point-number</span> +<span class="traceContains">+mem: storing 13 in location 15</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> GET_ADDRESS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;get-address&quot;</span>] = GET_ADDRESS<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;get-address&quot;</span><span class="Delimiter">,</span> GET_ADDRESS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case GET_ADDRESS: <span class="Delimiter">{</span> - reagent base = 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> - long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'get-address' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || Type[base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>kind != container<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'get-address' should be a container, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Comment">// Update GET_ADDRESS base in Check</span> + if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'get-address' should be a container, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - type_ordinal base_type = base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'get-address' should have type 'offset', but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + reagent offset = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>offset<span class="Delimiter">)</span> || !is_mu_scalar<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'get' should have type 'offset', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span> - long long int offset = 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> - if <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;invalid offset &quot;</span> &lt;&lt; offset &lt;&lt; <span class="Constant">&quot; for &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + long long int offset_value = <span class="Constant">0</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// later layers permit non-integer offsets</span> + offset_value = to_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>offset_value &lt; <span class="Constant">0</span> || offset_value &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;invalid offset &quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot; for &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + offset_value = offset<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + reagent product = 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="Comment">// Update GET_ADDRESS product in Check</span> + <span class="Comment">// same type as for GET..</span> + reagent element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> offset_value<span class="Delimiter">);</span> + <span class="Comment">// ..except for an address at the start</span> + element<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">),</span> element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'get-address' &quot;</span> &lt;&lt; offset<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; (&quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot;) on &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; can't be saved in &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;; type should be &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case GET_ADDRESS: <span class="Delimiter">{</span> + reagent base = 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">// Update GET_ADDRESS base in Run</span> + long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + long long int offset = 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> + if <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// copied from Check above</span> long long int result = base_address<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - result += size_of<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Comment">// End GET_ADDRESS field Cases</span> + result += size_of<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; result &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; result &lt;&lt; end<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">:(scenario get_address_out_of_bounds)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span> get-address <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:offset <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span> ] -<span class="traceContains">+warn: invalid offset 2 for point-number</span> +<span class="traceContains">+error: main: invalid offset 2 for point-number</span> <span class="Delimiter">:(scenario get_address_out_of_bounds_2)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span> get-address <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> -<span class="Constant">1</span>:offset ] -<span class="traceContains">+warn: invalid offset -1 for point-number</span> +<span class="traceContains">+error: main: invalid offset -1 for point-number</span> + +<span class="Delimiter">:(scenario get_address_product_type_mismatch)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> + <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span> + <span class="Constant">15</span>:number<span class="Special"> &lt;- </span>get-address <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+error: main: 'get-address' 1:offset (1) on point-number can't be saved in 15:number; type should be &lt;address : &lt;number : &lt;&gt;&gt;&gt;</span> <span class="SalientComment">//:: Allow containers to be defined in mu code.</span> @@ -302,11 +393,11 @@ container foo [ x:number y:number ] -<span class="traceContains">+parse: reading container foo</span> -<span class="traceContains">+parse: element name: x</span> -<span class="traceContains">+parse: type: 1</span> -<span class="traceContains">+parse: element name: y</span> -<span class="traceContains">+parse: type: 1</span> +<span class="traceContains">+parse: --- defining container foo</span> +<span class="traceContains">+parse: element name: x</span> +<span class="traceContains">+parse: type: 1</span> +<span class="traceContains">+parse: element name: y</span> +<span class="traceContains">+parse: type: 1</span> <span class="Delimiter">:(scenario container_use_before_definition)</span> container foo [ @@ -318,57 +409,66 @@ container bar [ x:number y:number ] -<span class="traceContains">+parse: reading container foo</span> +<span class="traceContains">+parse: --- defining container foo</span> <span class="traceContains">+parse: type number: 1000</span> <span class="traceContains">+parse: element name: x</span> <span class="traceContains">+parse: type: 1</span> <span class="traceContains">+parse: element name: y</span> <span class="traceContains">+parse: type: 1001</span> -<span class="traceContains">+parse: reading container bar</span> +<span class="traceContains">+parse: --- defining container bar</span> <span class="traceContains">+parse: type number: 1001</span> <span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span> else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;container&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> container<span class="Delimiter">,</span> in<span class="Delimiter">);</span> + insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> CONTAINER<span class="Delimiter">,</span> in<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> void insert_container<span class="Delimiter">(</span>const string&amp; command<span class="Delimiter">,</span> kind_of_type kind<span class="Delimiter">,</span> istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;reading &quot;</span> &lt;&lt; command &lt;&lt; <span class="Constant">' '</span> &lt;&lt; name &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>name<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">()</span> - || Type_ordinal[name] == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - Type_ordinal[name] = Next_type_ordinal++<span class="Delimiter">;</span> + <span class="Comment">// End container Name Refinements</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- defining &quot;</span> &lt;&lt; command &lt;&lt; <span class="Constant">' '</span> &lt;&lt; name &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> + || get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</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">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type number: &quot;</span> &lt;&lt; Type_ordinal[name] &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type number: &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">&quot;'container' must begin with '['&quot;</span><span class="Delimiter">);</span> - type_info&amp; t = Type[Type_ordinal[name]]<span class="Delimiter">;</span> - recently_added_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[name]<span class="Delimiter">);</span> - t<span class="Delimiter">.</span>name = name<span class="Delimiter">;</span> - t<span class="Delimiter">.</span>kind = kind<span class="Delimiter">;</span> + type_info&amp; 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> + recently_added_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">));</span> + info<span class="Delimiter">.</span>name = name<span class="Delimiter">;</span> + info<span class="Delimiter">.</span>kind = kind<span class="Delimiter">;</span> while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</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> if <span class="Delimiter">(</span>element == <span class="Constant">&quot;]&quot;</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Comment">// End insert_container Special Definitions(element)</span> istringstream inner<span class="Delimiter">(</span>element<span class="Delimiter">);</span> - t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; element name: &quot;</span> &lt;&lt; t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>back<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> - vector&lt;type_ordinal&gt; types<span class="Delimiter">;</span> - while <span class="Delimiter">(</span>!inner<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + info<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; element name: &quot;</span> &lt;&lt; info<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>back<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + type_tree* new_type = <span class="Constant">NULL</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>type_tree** curr_type = &amp;new_type<span class="Delimiter">;</span> !inner<span class="Delimiter">.</span>eof<span class="Delimiter">();</span> curr_type = &amp;<span class="Delimiter">(</span>*curr_type<span class="Delimiter">)-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> string type_name = slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">()</span> + <span class="Comment">// End insert_container Special Uses(type_name)</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">)</span> <span class="Comment">// types can contain integers, like for array sizes</span> &amp;&amp; !is_integer<span class="Delimiter">(</span>type_name<span class="Delimiter">))</span> <span class="Delimiter">{</span> - Type_ordinal[type_name] = Next_type_ordinal++<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> <span class="Delimiter">}</span> - types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[type_name]<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; type: &quot;</span> &lt;&lt; types<span class="Delimiter">.</span>back<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + *curr_type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; type: &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> - t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>types<span class="Delimiter">);</span> + info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_type<span class="Delimiter">);</span> <span class="Delimiter">}</span> - assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">)</span> == SIZE<span class="Delimiter">(</span>t<span class="Delimiter">.</span>element_names<span class="Delimiter">));</span> - t<span class="Delimiter">.</span>size = SIZE<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">)</span> == SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>element_names<span class="Delimiter">));</span> + info<span class="Delimiter">.</span>size = SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void skip_bracket<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> string message<span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> + raise_error &lt;&lt; message &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenarios run)</span> @@ -397,7 +497,12 @@ vector&lt;type_ordinal&gt; recently_added_types<span class="Delimiter">;</span> recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">:(before &quot;End Setup&quot;)</span> <span class="Comment">//: for tests</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Type[recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> + <span class="Comment">// todo: why do I explicitly need to provide this?</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>Type<span class="Delimiter">.</span>at<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>elements<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + delete Type<span class="Delimiter">.</span>at<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> + <span class="Delimiter">}</span> Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> @@ -411,9 +516,7 @@ while<span class="Delimiter">(</span>p != Type_ordinal<span class="Delimiter">.< <span class="Comment">// increment iterator</span> ++p<span class="Delimiter">;</span> <span class="Comment">// now delete current item if necessary</span> - if <span class="Delimiter">(</span>t &gt;= <span class="Constant">1000</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>name<span class="Delimiter">);</span> - <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>t &gt;= <span class="Constant">1000</span><span class="Delimiter">)</span> Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>name<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">//: lastly, ensure scenarios are consistent by always starting them at the</span> <span class="Comment">//: same type number.</span> @@ -423,60 +526,72 @@ assert<span class="Delimiter">(</span>Next_type_ordinal &lt; <span class="Consta <span class="Delimiter">:(before &quot;End Setup&quot;)</span> Next_type_ordinal = <span class="Constant">1000</span><span class="Delimiter">;</span> -<span class="SalientComment">//:: Allow container definitions anywhere in the codebase, but warn if you</span> -<span class="SalientComment">//:: can't find a definition.</span> +<span class="SalientComment">//:: Allow container definitions anywhere in the codebase, but complain if you</span> +<span class="SalientComment">//:: can't find a definition at the end.</span> -<span class="Delimiter">:(scenario run_warns_on_unknown_types)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario run_complains_on_unknown_types)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Comment"># integer is not a type</span> <span class="Constant">1</span>:integer<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] -<span class="traceContains">+warn: unknown type: integer</span> +<span class="traceContains">+error: main: unknown type in '1:integer &lt;- copy 0'</span> <span class="Delimiter">:(scenario run_allows_type_definition_after_use)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ - <span class="Constant">1</span>:bar<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> + <span class="Constant">1</span>:bar<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Special">raw</span> ] container bar [ x:number ] -<span class="traceAbsent">-warn: unknown type: bar</span> -$warn: <span class="Constant">0</span> +<span class="traceAbsent">-error: unknown type: bar</span> +$error: <span class="Constant">0</span> -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_invalid_types<span class="Delimiter">);</span> +<span class="Delimiter">:(after &quot;Begin Transforms&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_or_set_invalid_types<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(code)</span> -void check_invalid_types<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> +void check_or_set_invalid_types<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - check_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + check_or_set_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> + 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">&quot;'&quot;</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">&quot;'&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - check_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + check_or_set_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> + 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">&quot;'&quot;</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">&quot;'&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -void check_invalid_types<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Type<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> == Type<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;unknown type: &quot;</span> &lt;&lt; r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> +void check_or_set_invalid_types<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> const string_tree* type_name<span class="Delimiter">,</span> const string&amp; block<span class="Delimiter">,</span> const string&amp; name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// can't assert that type_name is non-null, even at the top of a recursive call tree</span> + if <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// will throw a more precise error elsewhere</span> + <span class="Comment">// End Container Type Checks</span> + if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>left &amp;&amp; !type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>type_name &amp;&amp; contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> + type<span class="Delimiter">-&gt;</span>value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> + else + raise_error &lt;&lt; block &lt;&lt; <span class="Constant">&quot;unknown type in &quot;</span> &lt;&lt; name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + check_or_set_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> type_name ? type_name<span class="Delimiter">-&gt;</span>left : <span class="Constant">NULL</span><span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span> + check_or_set_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> type_name ? type_name<span class="Delimiter">-&gt;</span>right : <span class="Constant">NULL</span><span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario container_unknown_field)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> container foo [ x:number y:bar ] -<span class="traceContains">+warn: unknown type for field y in foo</span> +<span class="traceContains">+error: foo: unknown type in y</span> <span class="Delimiter">:(scenario read_container_with_bracket_in_comment)</span> container foo [ @@ -484,35 +599,62 @@ container foo [ <span class="Comment"># ']' in comment</span> y:number ] -<span class="traceContains">+parse: reading container foo</span> -<span class="traceContains">+parse: element name: x</span> -<span class="traceContains">+parse: type: 1</span> -<span class="traceContains">+parse: element name: y</span> -<span class="traceContains">+parse: type: 1</span> +<span class="traceContains">+parse: --- defining container foo</span> +<span class="traceContains">+parse: element name: x</span> +<span class="traceContains">+parse: type: 1</span> +<span class="traceContains">+parse: element name: y</span> +<span class="traceContains">+parse: type: 1</span> -<span class="Delimiter">:(before &quot;End Transform&quot;)</span> +<span class="Delimiter">:(before &quot;End Transform All&quot;)</span> check_container_field_types<span class="Delimiter">();</span> <span class="Delimiter">:(code)</span> void check_container_field_types<span class="Delimiter">()</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>map&lt;type_ordinal<span class="Delimiter">,</span> type_info&gt;::iterator p = Type<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Type<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> const type_info&amp; info = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Type<span class="Delimiter">.</span>find<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">))</span> == Type<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;unknown type for field &quot;</span> &lt;&lt; info<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; in &quot;</span> &lt;&lt; info<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Delimiter">}</span> + <span class="Comment">// Check Container Field Types(info)</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + check_invalid_types<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> maybe<span class="Delimiter">(</span>info<span class="Delimiter">.</span>name<span class="Delimiter">),</span> info<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void check_invalid_types<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + check_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> + 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">&quot;'&quot;</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">&quot;'&quot;</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + check_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> + 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">&quot;'&quot;</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">&quot;'&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +void check_invalid_types<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> const string&amp; block<span class="Delimiter">,</span> const string&amp; name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// will throw a more precise error elsewhere</span> + <span class="Comment">// End Container Type Checks</span> + if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>left &amp;&amp; !type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> + raise_error &lt;&lt; block &lt;&lt; <span class="Constant">&quot;unknown type in &quot;</span> &lt;&lt; name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + check_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span> + check_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + <span class="SalientComment">//:: Construct types out of their constituent fields. Doesn't currently do</span> <span class="SalientComment">//:: type-checking but *does* match sizes.</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MERGE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;merge&quot;</span>] = MERGE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;merge&quot;</span><span class="Delimiter">,</span> MERGE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MERGE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MERGE: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -533,15 +675,6 @@ recipe main [ ] <span class="traceContains">+mem: storing 3 in location 1</span> <span class="traceContains">+mem: storing 4 in location 2</span> - -<span class="SalientComment">//:: helpers</span> - -<span class="Delimiter">:(code)</span> -void skip_bracket<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> string message<span class="Delimiter">)</span> <span class="Delimiter">{</span> - skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> - raise &lt;&lt; message &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> -<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/031address.cc.html b/html/031address.cc.html index caad95d7..f2b0e28f 100644 --- a/html/031address.cc.html +++ b/html/031address.cc.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.SalientComment { color: #00ffff; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } .cSpecial { color: #008000; } +.SalientComment { color: #00ffff; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -38,7 +38,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(scenario copy_indirect)</span> recipe main [ - <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span>/<span class="Special">raw</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Comment"># This loads location 1 as an address and looks up *that* location.</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:number/lookup @@ -46,76 +46,104 @@ recipe main [ <span class="traceContains">+mem: storing 34 in location 3</span> <span class="Delimiter">:(before &quot;long long int base = x.value&quot; following &quot;vector&lt;double&gt; read_memory(reagent x)&quot;)</span> -x = canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Comment">//: similarly, write to addresses pointing at other locations using the</span> <span class="Comment">//: 'lookup' property</span> <span class="Delimiter">:(scenario store_indirect)</span> recipe main [ - <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span>/<span class="Special">raw</span> <span class="Constant">1</span>:address:number/lookup<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> ] <span class="traceContains">+mem: storing 34 in location 2</span> <span class="Delimiter">:(before &quot;long long int base = x.value&quot; following &quot;void write_memory(reagent x, vector&lt;double&gt; data)&quot;)</span> -x = canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;can't write to location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't write to location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(after &quot;bool is_mu_array(reagent r)&quot;)</span> -r = canonize<span class="Delimiter">(</span>r<span class="Delimiter">);</span> - <span class="Comment">//: writes to address 0 always loudly fail</span> -<span class="Delimiter">:(scenario store_to_0_warns)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario store_to_0_fails)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Constant">1</span>:address:number/lookup<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> ] <span class="traceAbsent">-mem: storing 34 in location 0</span> -<span class="traceContains">+warn: can't write to location 0 in '1:address:number/lookup &lt;- copy 34'</span> +<span class="traceContains">+error: can't write to location 0 in '1:address:number/lookup &lt;- copy 34'</span> <span class="Delimiter">:(code)</span> -reagent canonize<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> - reagent r = x<span class="Delimiter">;</span> - while <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">))</span> - r = lookup_memory<span class="Delimiter">(</span>r<span class="Delimiter">);</span> - <span class="Identifier">return</span> r<span class="Delimiter">;</span> +void canonize<span class="Delimiter">(</span>reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Comment">// End canonize(x) Special-cases</span> + while <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">))</span> + lookup_memory<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Delimiter">}</span> -reagent lookup_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - static const type_ordinal ADDRESS = Type_ordinal[<span class="Constant">&quot;address&quot;</span>]<span class="Delimiter">;</span> - reagent result<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != ADDRESS<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to /lookup &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; but it isn't an address</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> +void lookup_memory<span class="Delimiter">(</span>reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to /lookup &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; but it isn't an address</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Comment">// compute value</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to /lookup 0</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to /lookup 0</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> - result<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>Memory[x<span class="Delimiter">.</span>value]<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; result<span class="Delimiter">.</span>value &lt;&lt; end<span class="Delimiter">();</span> - - <span class="Comment">// populate types</span> - copy<span class="Delimiter">(</span>++x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>result<span class="Delimiter">.</span>types<span class="Delimiter">,</span> result<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> - - <span class="Comment">// drop-one 'lookup'</span> - long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> - long long int len = SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">);</span> - for <span class="Delimiter">(</span>i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; len<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first == <span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> - result<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">))</span> &lt;&lt; end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">));</span> + drop_address_from_type<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + drop_one_lookup<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after &quot;bool types_match(reagent lhs, reagent rhs)&quot;)</span> + if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after &quot;bool is_mu_array(reagent r)&quot;)</span> + if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after &quot;bool is_mu_address(reagent r)&quot;)</span> + if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after &quot;bool is_mu_number(reagent r)&quot;)</span> + if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(code)</span> +bool canonize_type<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type || r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't lookup non-address: &quot;</span> &lt;&lt; r<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + drop_address_from_type<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + drop_one_lookup<span class="Delimiter">(</span>r<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> + +void drop_address_from_type<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + type_tree* tmp = r<span class="Delimiter">.</span>type<span class="Delimiter">;</span> + r<span class="Delimiter">.</span>type = tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span> + tmp<span class="Delimiter">-&gt;</span>right = <span class="Constant">NULL</span><span class="Delimiter">;</span> + delete tmp<span class="Delimiter">;</span> + <span class="Comment">// property</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string_tree* tmp2 = r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">;</span> + r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second = tmp2<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span> + tmp2<span class="Delimiter">-&gt;</span>right = <span class="Constant">NULL</span><span class="Delimiter">;</span> + delete tmp2<span class="Delimiter">;</span> <span class="Delimiter">}</span> - ++i<span class="Delimiter">;</span> <span class="Comment">// skip first lookup</span> - for <span class="Delimiter">(;</span> i &lt; len<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - result<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + +void drop_one_lookup<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>vector&lt;pair&lt;string<span class="Delimiter">,</span> string_tree*&gt; &gt;::iterator p = r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>first == <span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>p<span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: 'get' can read from container address</span> @@ -128,6 +156,16 @@ recipe main [ ] <span class="traceContains">+mem: storing 34 in location 4</span> +<span class="Delimiter">:(scenario get_indirect2)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> + <span class="Constant">4</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span>/<span class="Special">raw</span> + *<span class="Constant">4</span>:address:number<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:address:point/lookup<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+mem: storing 34 in location 5</span> + <span class="Delimiter">:(scenario include_nonlookup_properties)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> @@ -137,8 +175,12 @@ recipe main [ ] <span class="traceContains">+mem: storing 34 in location 4</span> -<span class="Delimiter">:(after &quot;reagent base = &quot; following &quot;case GET:&quot;)</span> -base = canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> +<span class="Delimiter">:(after &quot;Update GET base in Check&quot;)</span> +if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after &quot;Update GET product in Check&quot;)</span> +if <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 &quot;Update GET base in Run&quot;)</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> <span class="Delimiter">:(scenario get_address_indirect)</span> <span class="Comment"># 'get' can read from container address</span> @@ -146,31 +188,37 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get-address <span class="Constant">1</span>:address:point/lookup<span class="Delimiter">,</span> <span class="Constant">0</span>:offset + <span class="Constant">4</span>:address:number<span class="Special"> &lt;- </span>get-address <span class="Constant">1</span>:address:point/lookup<span class="Delimiter">,</span> <span class="Constant">0</span>:offset ] <span class="traceContains">+mem: storing 2 in location 4</span> -<span class="Delimiter">:(after &quot;reagent base = &quot; following &quot;case GET_ADDRESS:&quot;)</span> -base = canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> +<span class="Delimiter">:(after &quot;Update GET_ADDRESS base in Check&quot;)</span> +if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after &quot;Update GET_ADDRESS product in Check&quot;)</span> +if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after &quot;Update GET_ADDRESS base in Run&quot;)</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> <span class="SalientComment">//:: abbreviation for '/lookup': a prefix '*'</span> <span class="Delimiter">:(scenario lookup_abbreviation)</span> recipe main [ - <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span>/<span class="Special">raw</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:number ] +<span class="traceContains">+parse: ingredient: {&quot;1&quot;: &lt;&quot;address&quot; : &lt;&quot;number&quot; : &lt;&gt;&gt;&gt;, &quot;lookup&quot;: &lt;&gt;}</span> <span class="traceContains">+mem: storing 34 in location 3</span> <span class="Delimiter">:(before &quot;End Parsing reagent&quot;)</span> <span class="Delimiter">{</span> while <span class="Delimiter">(</span>!name<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; name<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> 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> - properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span><span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;illegal name &quot;</span> &lt;&lt; original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;illegal name &quot;</span> &lt;&lt; original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>first = name<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: helpers for debugging</span> @@ -178,11 +226,12 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _DUMP<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$dump&quot;</span>] = _DUMP<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$dump&quot;</span><span class="Delimiter">,</span> _DUMP<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _DUMP: <span class="Delimiter">{</span> - reagent after_canonize = canonize<span class="Delimiter">(</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> - cerr &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; 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 &lt;&lt; <span class="Constant">' '</span> &lt;&lt; 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>value &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; after_canonize<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; Memory[after_canonize<span class="Delimiter">.</span>value] &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + reagent after_canonize = 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> + canonize<span class="Delimiter">(</span>after_canonize<span class="Delimiter">);</span> + cerr &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; 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 &lt;&lt; <span class="Constant">' '</span> &lt;&lt; no_scientific<span class="Delimiter">(</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>value<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>after_canonize<span class="Delimiter">.</span>value<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> after_canonize<span class="Delimiter">.</span>value<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -193,15 +242,17 @@ long long int foo = -<span class="Constant">1</span><span class="Delimiter">;</s <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _FOO<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$foo&quot;</span>] = _FOO<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$foo&quot;</span><span class="Delimiter">,</span> _FOO<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _FOO: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>foo != -<span class="Constant">1</span><span class="Delimiter">)</span> cerr &lt;&lt; foo &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; Memory[foo] &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>foo != -<span class="Constant">1</span><span class="Delimiter">)</span> cerr &lt;&lt; foo &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> foo<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> else cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> - foo = canonize<span class="Delimiter">(</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>value<span class="Delimiter">;</span> + reagent tmp = 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> + canonize<span class="Delimiter">(</span>tmp<span class="Delimiter">);</span> + foo = tmp<span class="Delimiter">.</span>value<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/032array.cc.html b/html/032array.cc.html index c73052a4..8c0ce105 100644 --- a/html/032array.cc.html +++ b/html/032array.cc.html @@ -13,6 +13,7 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .SalientComment { color: #00ffff; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } @@ -20,7 +21,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -50,40 +50,47 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CREATE_ARRAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;create-array&quot;</span>] = CREATE_ARRAY<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;create-array&quot;</span><span class="Delimiter">,</span> CREATE_ARRAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case CREATE_ARRAY: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'create-array' needs one product and no ingredients but got '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'create-array' needs one product and no ingredients but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent product = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + reagent product = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'create-array' cannot create non-array &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'create-array' cannot create non-array &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int base_address = product<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>product<span class="Delimiter">.</span>types<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: create array of what? &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;create array of what? &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">// 'create-array' will need to check properties rather than types</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> &lt;= <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: create array of what size? &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second || !product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>right || !product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;create array of what size? &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'create-array' product should specify size of array after its element type, but got &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'create-array' product should specify size of array after its element type, but got &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int array_size= to_integer<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">));</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case CREATE_ARRAY: <span class="Delimiter">{</span> + reagent product = current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + long long int base_address = product<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + long long int array_size = to_integer<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> <span class="Comment">// initialize array size, so that size_of will work</span> - Memory[base_address] = array_size<span class="Delimiter">;</span> <span class="Comment">// in array elements</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">,</span> array_size<span class="Delimiter">);</span> <span class="Comment">// in array elements</span> long long int size = size_of<span class="Delimiter">(</span>product<span class="Delimiter">);</span> <span class="Comment">// in locations</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;creating array of size &quot;</span> &lt;&lt; size &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;creating array of size &quot;</span> &lt;&lt; size &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Comment">// initialize array</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt;= size_of<span class="Delimiter">(</span>product<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Memory[base_address+i] = <span class="Constant">0</span><span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address+i<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// dummy product; doesn't actually do anything</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -112,7 +119,7 @@ recipe main [ <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> <span class="Comment"># unsafe</span> + <span class="Constant">5</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>/<span class="Special">raw</span> <span class="Constant">6</span>:array:number<span class="Special"> &lt;- </span>copy *<span class="Constant">5</span>:address:array:number ] <span class="traceContains">+mem: storing 3 in location 6</span> @@ -132,15 +139,15 @@ recipe main [ <span class="Comment">//: disable the size mismatch check since the destination array need not be initialized</span> <span class="Delimiter">:(before &quot;End size_mismatch(x) Cases&quot;)</span> -if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">&quot;array&quot;</span>]<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End size_of(reagent) Cases&quot;)</span> -if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">&quot;array&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: '&quot;</span> &lt;&lt; r<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;' is an array of what?</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> +if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type &amp;&amp; r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'&quot;</span> &lt;&lt; r<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;' is an array of what?</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">// skip the 'array' type to get at the element type</span> - <span class="Identifier">return</span> <span class="Constant">1</span> + Memory[r<span class="Delimiter">.</span>value]*size_of<span class="Delimiter">(</span>array_element<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">));</span> + <span class="Identifier">return</span> <span class="Constant">1</span> + get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> r<span class="Delimiter">.</span>value<span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>array_element<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: To access elements of an array, use 'index'</span> @@ -169,43 +176,60 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> INDEX<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;index&quot;</span>] = INDEX<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;index&quot;</span><span class="Delimiter">,</span> INDEX<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case INDEX: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'index' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'index' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent base = canonize<span class="Delimiter">(</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> + reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'index' on a non-array &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'index' on a non-array &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + reagent product = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + reagent element<span class="Delimiter">;</span> + element<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>*array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'index' on &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; can't be saved in &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;; type should be &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case INDEX: <span class="Delimiter">{</span> + reagent base = 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> + canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span> + reagent offset = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + canonize<span class="Delimiter">(</span>offset<span class="Delimiter">);</span> vector&lt;double&gt; offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> - vector&lt;type_ordinal&gt; element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; <span class="Constant">0</span> || offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= Memory[base_address]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: invalid index &quot;</span> &lt;&lt; offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + type_tree* element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; <span class="Constant">0</span> || offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;invalid index &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> long long int src = base_address + <span class="Constant">1</span> + offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src &lt;&lt; end<span class="Delimiter">();</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; Type[element_type<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> element_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> reagent tmp<span class="Delimiter">;</span> tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span> - copy<span class="Delimiter">(</span>element_type<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> element_type<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>types<span class="Delimiter">,</span> tmp<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> + tmp<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>*element_type<span class="Delimiter">);</span> products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -vector&lt;type_ordinal&gt; array_element<span class="Delimiter">(</span>const vector&lt;type_ordinal&gt;&amp; types<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> vector&lt;type_ordinal&gt;<span class="Delimiter">(</span>++types<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> types<span class="Delimiter">.</span>end<span class="Delimiter">());</span> +type_tree* array_element<span class="Delimiter">(</span>const type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario index_indirect)</span> @@ -214,13 +238,13 @@ recipe main [ <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + <span class="Constant">5</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>/<span class="Special">raw</span> <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>index *<span class="Constant">5</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">1</span> ] <span class="traceContains">+mem: storing 15 in location 6</span> <span class="Delimiter">:(scenario index_out_of_bounds)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> @@ -232,10 +256,10 @@ recipe main [ <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> index *<span class="Constant">8</span>:address:array:point<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">+warn: main: invalid index 4</span> +<span class="traceContains">+error: main: invalid index 4</span> <span class="Delimiter">:(scenario index_out_of_bounds_2)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> @@ -244,10 +268,25 @@ recipe main [ <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>/<span class="Special">raw</span> index *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span> ] -<span class="traceContains">+warn: main: invalid index -1</span> +<span class="traceContains">+error: main: invalid index -1</span> + +<span class="Delimiter">:(scenario index_product_type_mismatch)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> + <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> + <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> + <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> + <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> + <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>/<span class="Special">raw</span> + <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>index *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> <span class="Constant">0</span> +] +<span class="traceContains">+error: main: 'index' on *8:address:array:point can't be saved in 9:number; type should be point</span> <span class="SalientComment">//:: To write to elements of containers, you need their address.</span> @@ -257,35 +296,53 @@ recipe main [ <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>index-address <span class="Constant">1</span>:array:number<span class="Delimiter">,</span> <span class="Constant">0</span> + <span class="Constant">5</span>:address:number<span class="Special"> &lt;- </span>index-address <span class="Constant">1</span>:array:number<span class="Delimiter">,</span> <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 2 in location 5</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> INDEX_ADDRESS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;index-address&quot;</span>] = INDEX_ADDRESS<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;index-address&quot;</span><span class="Delimiter">,</span> INDEX_ADDRESS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case INDEX_ADDRESS: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'index-address' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'index-address' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent base = canonize<span class="Delimiter">(</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> + reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'index-address' on a non-array &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'index-address' on a non-array &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + reagent product = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + reagent element<span class="Delimiter">;</span> + element<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>*array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">));</span> + element<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">),</span> element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'index' on &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; can't be saved in &quot;</span> &lt;&lt; product<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;; type should be &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case INDEX_ADDRESS: <span class="Delimiter">{</span> + reagent base = 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> + canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span> + reagent offset = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + canonize<span class="Delimiter">(</span>offset<span class="Delimiter">);</span> vector&lt;double&gt; offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> - vector&lt;type_ordinal&gt; element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; <span class="Constant">0</span> || offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= Memory[base_address]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: invalid index &quot;</span> &lt;&lt; offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + type_tree* element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; <span class="Constant">0</span> || offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;invalid index &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> long long int result = base_address + <span class="Constant">1</span> + offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> @@ -295,7 +352,7 @@ case INDEX_ADDRESS: <span class="Delimiter">{</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario index_address_out_of_bounds)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> @@ -307,10 +364,10 @@ recipe main [ <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> <span class="Comment"># unsafe</span> index-address *<span class="Constant">8</span>:address:array:point<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">+warn: main: invalid index 4</span> +<span class="traceContains">+error: main: invalid index 4</span> <span class="Delimiter">:(scenario index_address_out_of_bounds_2)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> @@ -319,10 +376,25 @@ recipe main [ <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> <span class="Comment"># unsafe</span> + <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>/<span class="Special">raw</span> index-address *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span> ] -<span class="traceContains">+warn: main: invalid index -1</span> +<span class="traceContains">+error: main: invalid index -1</span> + +<span class="Delimiter">:(scenario index_address_product_type_mismatch)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> + <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> + <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span> + <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span> + <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span> + <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>/<span class="Special">raw</span> + <span class="Constant">9</span>:address:number<span class="Special"> &lt;- </span>index-address *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> <span class="Constant">0</span> +] +<span class="traceContains">+error: main: 'index' on *8:address:array:point can't be saved in 9:address:number; type should be &lt;address : &lt;point : &lt;&gt;&gt;&gt;</span> <span class="SalientComment">//:: compute the length of an array</span> @@ -339,24 +411,31 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> LENGTH<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;length&quot;</span>] = LENGTH<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;length&quot;</span><span class="Delimiter">,</span> LENGTH<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case LENGTH: <span class="Delimiter">{</span> - if <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> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'length' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'length' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent x = canonize<span class="Delimiter">(</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> + reagent x = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>x<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;tried to calculate length of non-array &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;tried to calculate length of non-array &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case LENGTH: <span class="Delimiter">{</span> + reagent x = 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> + canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - 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>Memory[x<span class="Delimiter">.</span>value]<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>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/033exclusive_container.cc.html b/html/033exclusive_container.cc.html index beea9b0e..a4fc191a 100644 --- a/html/033exclusive_container.cc.html +++ b/html/033exclusive_container.cc.html @@ -13,9 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } -.SalientComment { color: #00ffff; } .traceContains { color: #008000; } +.SalientComment { color: #00ffff; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -41,23 +41,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> <span class="Comment">//: We'll use this container as a running example, with two number elements.</span> <span class="Delimiter">{</span> -type_ordinal tmp = Type_ordinal[<span class="Constant">&quot;number-or-point&quot;</span>] = Next_type_ordinal++<span class="Delimiter">;</span> -Type[tmp]<span class="Delimiter">.</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> -Type[tmp]<span class="Delimiter">.</span>kind = exclusive_container<span class="Delimiter">;</span> -Type[tmp]<span class="Delimiter">.</span>name = <span class="Constant">&quot;number-or-point&quot;</span><span class="Delimiter">;</span> -vector&lt;type_ordinal&gt; t1<span class="Delimiter">;</span> -t1<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>number<span class="Delimiter">);</span> -Type[tmp]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>t1<span class="Delimiter">);</span> -vector&lt;type_ordinal&gt; t2<span class="Delimiter">;</span> -t2<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>point<span class="Delimiter">);</span> -Type[tmp]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>t2<span class="Delimiter">);</span> -Type[tmp]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;i&quot;</span><span class="Delimiter">);</span> -Type[tmp]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;p&quot;</span><span class="Delimiter">);</span> +type_ordinal tmp = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;number-or-point&quot;</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> +get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>kind = EXCLUSIVE_CONTAINER<span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>name = <span class="Constant">&quot;number-or-point&quot;</span><span class="Delimiter">;</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new type_tree<span class="Delimiter">(</span>number<span class="Delimiter">));</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;i&quot;</span><span class="Delimiter">);</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new type_tree<span class="Delimiter">(</span>point<span class="Delimiter">));</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;p&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">//: Tests in this layer often explicitly setup memory before reading it as an</span> <span class="Comment">//: array. Don't do this in general. I'm tagging exceptions with /raw to</span> -<span class="Comment">//: avoid warnings.</span> +<span class="Comment">//: avoid errors.</span> <span class="Delimiter">:(scenario copy_exclusive_container)</span> <span class="Comment"># Copying exclusive containers copies all their contents and an extra location for the tag.</span> recipe main [ @@ -70,8 +66,8 @@ recipe main [ <span class="traceContains">+mem: storing 34 in location 5</span> <span class="traceContains">+mem: storing 35 in location 6</span> -<span class="Delimiter">:(before &quot;End size_of(types) Cases&quot;)</span> -if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == exclusive_container<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Delimiter">:(before &quot;End size_of(type) Cases&quot;)</span> +if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// size of an exclusive container is the size of its largest variant</span> <span class="Comment">// (So like containers, it can't contain arrays.)</span> long long int result = <span class="Constant">0</span><span class="Delimiter">;</span> @@ -91,7 +87,7 @@ if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == excl <span class="Comment">//: 'maybe-convert' requires a literal in ingredient 1. We'll use a synonym</span> <span class="Comment">//: called 'variant'.</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -Type_ordinal[<span class="Constant">&quot;variant&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;variant&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">:(scenario maybe_convert)</span> recipe main [ @@ -114,30 +110,37 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MAYBE_CONVERT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;maybe-convert&quot;</span>] = MAYBE_CONVERT<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;maybe-convert&quot;</span><span class="Delimiter">,</span> MAYBE_CONVERT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case MAYBE_CONVERT: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'maybe-convert' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'maybe-convert' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - reagent base = canonize<span class="Delimiter">(</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> - long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind != EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'maybe-convert' should be an exclusive-container, but got &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || Type[base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>kind != exclusive_container<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name <span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'maybe-convert' should be an exclusive-container, but got &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'maybe-convert' should have type 'variant', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'maybe-convert' should have type 'variant', but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case MAYBE_CONVERT: <span class="Delimiter">{</span> + reagent base = 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> + canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> + long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> long long int tag = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">;</span> long long int result<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>tag == static_cast&lt;long long int&gt;<span class="Delimiter">(</span>Memory[base_address]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>tag == static_cast&lt;long long int&gt;<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> result = base_address+<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> @@ -155,7 +158,7 @@ exclusive-container foo [ x:number y:number ] -<span class="traceContains">+parse: reading exclusive-container foo</span> +<span class="traceContains">+parse: --- defining exclusive-container foo</span> <span class="traceContains">+parse: element name: x</span> <span class="traceContains">+parse: type: 1</span> <span class="traceContains">+parse: element name: y</span> @@ -163,7 +166,7 @@ exclusive-container foo [ <span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span> else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;exclusive-container&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> exclusive_container<span class="Delimiter">,</span> in<span class="Delimiter">);</span> + insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> EXCLUSIVE_CONTAINER<span class="Delimiter">,</span> in<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: To construct exclusive containers out of variant types, use 'merge'.</span> @@ -188,9 +191,10 @@ recipe main [ <span class="Delimiter">:(before &quot;End size_mismatch(x) Cases&quot;)</span> if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation == MERGE &amp;&amp; !current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> - &amp;&amp; !current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - reagent x = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> - if <span class="Delimiter">(</span>Type[x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>kind == exclusive_container<span class="Delimiter">)</span> <span class="Delimiter">{</span> + &amp;&amp; current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + reagent x = current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> &lt; SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> diff --git a/html/034call.cc.html b/html/034call.cc.html index 8c95766f..10ad7632 100644 --- a/html/034call.cc.html +++ b/html/034call.cc.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.PreProc { color: #c000c0; } +.traceContains { color: #008000; } .SalientComment { color: #00ffff; } .cSpecial { color: #008000; } +.PreProc { color: #c000c0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -77,6 +77,9 @@ struct call <span class="Delimiter">{</span> running_step_index = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">// End call Constructor</span> <span class="Delimiter">}</span> + ~call<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// End call Destructor</span> + <span class="Delimiter">}</span> <span class="Delimiter">};</span> typedef list&lt;call&gt; call_stack<span class="Delimiter">;</span> @@ -90,57 +93,80 @@ struct routine <span class="Delimiter">{</span> <span class="Delimiter">};</span> <span class="Delimiter">:(code)</span> routine::routine<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ++Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;trace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new routine; incrementing callstack depth to &quot;</span> &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt;&lt; end<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt; <span class="Constant">9000</span><span class="Delimiter">);</span> <span class="Comment">// 9998-101 plus cushion</span> + <span class="Delimiter">}</span> calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>r<span class="Delimiter">));</span> <span class="Comment">// End routine Constructor</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> +inline call&amp; current_call<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + <span class="SalientComment">//:: now update routine's helpers</span> <span class="Delimiter">:(replace{} &quot;inline long long int&amp; current_step_index()&quot;)</span> inline long long int&amp; current_step_index<span class="Delimiter">()</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - <span class="Identifier">return</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_step_index<span class="Delimiter">;</span> + <span class="Identifier">return</span> current_call<span class="Delimiter">().</span>running_step_index<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(replace{} &quot;inline const string&amp; current_recipe_name()&quot;)</span> inline const string&amp; current_recipe_name<span class="Delimiter">()</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_recipe]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> current_call<span class="Delimiter">().</span>running_recipe<span class="Delimiter">).</span>name<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(replace{} &quot;inline const instruction&amp; current_instruction()&quot;)</span> inline const instruction&amp; current_instruction<span class="Delimiter">()</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_step_index<span class="Delimiter">);</span> + <span class="Identifier">return</span> to_instruction<span class="Delimiter">(</span>current_call<span class="Delimiter">());</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> +inline const instruction&amp; to_instruction<span class="Delimiter">(</span>const call&amp; call<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> call<span class="Delimiter">.</span>running_recipe<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>call<span class="Delimiter">.</span>running_step_index<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(after &quot;Defined Recipe Checks&quot;)</span> +<span class="Comment">// not a primitive; check that it's present in the book of recipes</span> +if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;undefined operation in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(replace{} &quot;default:&quot; following &quot;End Primitive Recipe Implementations&quot;)</span> default: <span class="Delimiter">{</span> - <span class="Comment">// not a primitive; try to look up the book of recipes</span> - if <span class="Delimiter">(</span>Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">)</span> == Recipe<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: undefined operation in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + const instruction&amp; call_instruction = current_instruction<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">)</span> == Recipe<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> <span class="Comment">// duplicate from Checks</span> <span class="Comment">// stop running this instruction immediately</span> ++current_step_index<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + <span class="Comment">// not a primitive; look up the book of recipes</span> + if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ++Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;trace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;incrementing callstack depth to &quot;</span> &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt;&lt; end<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt; <span class="Constant">9000</span><span class="Delimiter">);</span> <span class="Comment">// 9998-101 plus cushion</span> + <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">));</span> - call_housekeeping: - ++Callstack_depth<span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>Callstack_depth &lt; <span class="Constant">9000</span><span class="Delimiter">);</span> <span class="Comment">// 9998-101 plus cushion</span> + <span class="Comment">// End Call Housekeeping</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="Delimiter">:(scenario calling_undefined_recipe_warns)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario calling_undefined_recipe_fails)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ foo ] -<span class="traceContains">+warn: main: undefined operation in 'foo '</span> +<span class="traceContains">+error: main: undefined operation in 'foo '</span> <span class="Delimiter">:(scenario calling_undefined_recipe_handles_missing_result)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number<span class="Special"> &lt;- </span>foo ] -<span class="traceContains">+warn: main: undefined operation in 'x:number &lt;- foo '</span> +<span class="traceContains">+error: main: undefined operation in 'x:number &lt;- foo '</span> <span class="SalientComment">//:: finally, we need to fix the termination conditions for the run loop</span> @@ -151,7 +177,7 @@ inline bool routine::completed<span class="Delimiter">()</span> const <span clas inline const vector&lt;instruction&gt;&amp; routine::steps<span class="Delimiter">()</span> const <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - <span class="Identifier">return</span> Recipe[calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">;</span> + <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_recipe<span class="Delimiter">).</span>steps<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;Running One Instruction&quot;)</span> @@ -159,11 +185,15 @@ inline const vector&lt;instruction&gt;&amp; routine::steps<span class="Delimiter <span class="Comment">// it, and the one below that, and so on</span> while <span class="Delimiter">(</span>current_step_index<span class="Delimiter">()</span> &gt;= SIZE<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>steps<span class="Delimiter">()))</span> <span class="Delimiter">{</span> <span class="Comment">// Falling Through End Of Recipe</span> - --Callstack_depth<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Trace_stream<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">&quot;trace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;fall-through: exiting &quot;</span> &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;; decrementing callstack depth from &quot;</span> &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt;&lt; end<span class="Delimiter">();</span> + --Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>pop_front<span class="Delimiter">();</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// Complete Call Fallthrough</span> - <span class="Comment">// todo: no products returned warning</span> + <span class="Comment">// todo: fail if no products returned</span> ++current_step_index<span class="Delimiter">();</span> <span class="Delimiter">}</span> diff --git a/html/035call_ingredient.cc.html b/html/035call_ingredient.cc.html index 517cf646..104c66dc 100644 --- a/html/035call_ingredient.cc.html +++ b/html/035call_ingredient.cc.html @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -55,41 +55,79 @@ recipe f [ <span class="Delimiter">:(before &quot;End call Fields&quot;)</span> vector&lt;vector&lt;double&gt; &gt; ingredient_atoms<span class="Delimiter">;</span> +vector&lt;type_tree*&gt; ingredient_types<span class="Delimiter">;</span> long long int next_ingredient_to_process<span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End call Constructor&quot;)</span> next_ingredient_to_process = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="Delimiter">:(after &quot;call_housekeeping:&quot;)</span> +<span class="Delimiter">:(before &quot;End Call Housekeeping&quot;)</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + reagent ingredient = call_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> + current_call<span class="Delimiter">().</span>ingredient_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + ingredient<span class="Delimiter">.</span>type = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Comment">// release long-lived pointer</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End call Destructor&quot;)</span> +for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredient_types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + delete ingredient_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> NEXT_INGREDIENT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;next-ingredient&quot;</span>] = NEXT_INGREDIENT<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;next-ingredient&quot;</span><span class="Delimiter">,</span> NEXT_INGREDIENT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case NEXT_INGREDIENT: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'next-ingredient' didn't expect any ingredients in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'next-ingredient' didn't expect any ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case NEXT_INGREDIENT: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process &lt; SIZE<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>next_ingredient_to_process &lt; SIZE<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">))</span> <span class="Delimiter">{</span> + reagent product = current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> + current_call<span class="Delimiter">().</span>ingredient_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">),</span> + current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>at<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">)</span> + <span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;wrong type for ingredient &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">));</span> + current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>at<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">));</span> assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">// push a new vector</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - ++Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">;</span> + ++current_call<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &lt; <span class="Constant">2</span><span class="Delimiter">)</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;no ingredient to save in &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// todo: will fail noisily if we try to read a compound value</span> + <span class="Comment">// pad the first product with sufficient zeros to match its type</span> + long long int size = size_of<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; size<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario next_ingredient_fail_on_missing)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + f +] +recipe f [ + <span class="Constant">11</span>:number<span class="Special"> &lt;- </span>next-ingredient +] +<span class="traceContains">+error: f: no ingredient to save in 11:number</span> + <span class="Delimiter">:(scenario rewind_ingredients)</span> recipe main [ f <span class="Constant">2</span> @@ -108,10 +146,14 @@ recipe f [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> REWIND_INGREDIENTS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;rewind-ingredients&quot;</span>] = REWIND_INGREDIENTS<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;rewind-ingredients&quot;</span><span class="Delimiter">,</span> REWIND_INGREDIENTS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case REWIND_INGREDIENTS: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case REWIND_INGREDIENTS: <span class="Delimiter">{</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process = <span class="Constant">0</span><span class="Delimiter">;</span> + current_call<span class="Delimiter">().</span>next_ingredient_to_process = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -129,25 +171,28 @@ recipe f [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> INGREDIENT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;ingredient&quot;</span>] = INGREDIENT<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;ingredient&quot;</span><span class="Delimiter">,</span> INGREDIENT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case INGREDIENT: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'ingredient' expects exactly one ingredient, but got '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'ingredient' expects exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</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> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'ingredient' expects a literal ingredient, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_literal<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> &amp;&amp; !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'ingredient' expects a literal ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> - if <span class="Delimiter">(</span>static_cast&lt;long long int&gt;<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> &lt; SIZE<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">))</span> <span class="Delimiter">{</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case INGREDIENT: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>static_cast&lt;long long int&gt;<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> &lt; SIZE<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">))</span> <span class="Delimiter">{</span> + current_call<span class="Delimiter">().</span>next_ingredient_to_process = 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> products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">));</span> + current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>at<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">));</span> assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">// push a new vector</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - ++Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">;</span> + ++current_call<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/036call_reply.cc.html b/html/036call_reply.cc.html index bdc9cb07..45622e07 100644 --- a/html/036call_reply.cc.html +++ b/html/036call_reply.cc.html @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -48,36 +48,58 @@ recipe f [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> REPLY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;reply&quot;</span>] = REPLY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">,</span> REPLY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case REPLY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// continue to process rest of *caller* instruction</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case REPLY: <span class="Delimiter">{</span> <span class="Comment">// Starting Reply</span> const instruction&amp; reply_inst = current_instruction<span class="Delimiter">();</span> <span class="Comment">// save pointer into recipe before pop</span> const string&amp; callee = current_recipe_name<span class="Delimiter">();</span> - --Callstack_depth<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Trace_stream<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">&quot;trace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;reply: decrementing callstack depth from &quot;</span> &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt;&lt; end<span class="Delimiter">();</span> + --Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>pop_front<span class="Delimiter">();</span> <span class="Comment">// just in case 'main' returns a value, drop it for now</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">goto</span> stop_running_current_routine<span class="Delimiter">;</span> const instruction&amp; caller_instruction = current_instruction<span class="Delimiter">();</span> + <span class="Comment">// check types with the caller</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;too few values replied from &quot;</span> &lt;&lt; callee &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>callee<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;reply ingredient &quot;</span> &lt;&lt; reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot; can't be saved in &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + reagent lhs = reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + reagent rhs = caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">);</span> + raise_error &lt;&lt; debug_string<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; vs &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>rhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_reply<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> <span class="Comment">// make reply products available to caller</span> copy<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> ingredients<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>products<span class="Delimiter">,</span> products<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> <span class="Comment">// check that any reply ingredients with /same-as-ingredient connect up</span> <span class="Comment">// the corresponding ingredient and product in the caller.</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">))</span> - raise &lt;&lt; <span class="Constant">&quot;too few values replied from &quot;</span> &lt;&lt; callee &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;result &quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;result &quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">&quot;same-as-ingredient&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - vector&lt;string&gt; tmp = property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">&quot;same-as-ingredient&quot;</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>tmp<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'same-as-ingredient' metadata should take exactly one value in &quot;</span> &lt;&lt; reply_inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + string_tree* tmp = property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">&quot;same-as-ingredient&quot;</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!tmp || tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'same-as-ingredient' metadata should take exactly one value in &quot;</span> &lt;&lt; reply_inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">goto</span> finish_reply<span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int ingredient_index = to_integer<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + long long int ingredient_index = to_integer<span class="Delimiter">(</span>tmp<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> if <span class="Delimiter">(</span>ingredient_index &gt;= SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'same-as-ingredient' metadata overflows ingredients in: &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'same-as-ingredient' metadata overflows ingredients in: &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>!is_dummy<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &amp;&amp; caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>value != caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>value<span class="Delimiter">)</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'same-as-ingredient' product from call to &quot;</span> &lt;&lt; callee &lt;&lt; <span class="Constant">&quot; must be &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot; rather than &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'&quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;' should write to &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot; rather than &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// End Reply</span> @@ -93,53 +115,66 @@ recipe main [ recipe f [ <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>next-ingredient <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> - reply <span class="Constant">12</span>:point/<span class="Special">raw</span> <span class="Comment"># unsafe</span> + reply <span class="Constant">12</span>:point/<span class="Special">raw</span> ] <span class="traceContains">+run: result 0 is [2, 35]</span> <span class="traceContains">+mem: storing 2 in location 3</span> <span class="traceContains">+mem: storing 35 in location 4</span> +<span class="Delimiter">:(scenario reply_type_mismatch)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>f <span class="Constant">2</span> +] +recipe f [ + <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>next-ingredient + <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> + <span class="Constant">14</span>:point<span class="Special"> &lt;- </span>copy <span class="Constant">12</span>:point/<span class="Special">raw</span> + reply <span class="Constant">14</span>:point +] +<span class="traceContains">+error: f: reply ingredient 14:point can't be saved in 3:number</span> + <span class="Comment">//: In mu we'd like to assume that any instruction doesn't modify its</span> <span class="Comment">//: ingredients unless they're also products. The /same-as-ingredient inside</span> <span class="Comment">//: the recipe's 'reply' will help catch accidental misuse of such</span> <span class="Comment">//: 'ingredient-products' (sometimes called in-out parameters in other languages).</span> <span class="Delimiter">:(scenario reply_same_as_ingredient)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>test1 <span class="Constant">1</span>:number <span class="Comment"># call with different ingredient and product</span> ] recipe test1 [ - <span class="Constant">10</span>:address:number<span class="Special"> &lt;- </span>next-ingredient - reply <span class="Constant">10</span>:address:number/same-as-ingredient:<span class="Constant">0</span> + <span class="Constant">10</span>:number<span class="Special"> &lt;- </span>next-ingredient + reply <span class="Constant">10</span>:number/same-as-ingredient:<span class="Constant">0</span> ] -<span class="traceContains">+warn: main: 'same-as-ingredient' product from call to test1 must be 1:number rather than 2:number</span> +<span class="traceContains">+error: main: '2:number &lt;- test1 1:number' should write to 1:number rather than 2:number</span> <span class="Delimiter">:(scenario reply_same_as_ingredient_dummy)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Comment"># % Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> _<span class="Special"> &lt;- </span>test1 <span class="Constant">1</span>:number <span class="Comment"># call with different ingredient and product</span> ] recipe test1 [ - <span class="Constant">10</span>:address:number<span class="Special"> &lt;- </span>next-ingredient - reply <span class="Constant">10</span>:address:number/same-as-ingredient:<span class="Constant">0</span> + <span class="Constant">10</span>:number<span class="Special"> &lt;- </span>next-ingredient + reply <span class="Constant">10</span>:number/same-as-ingredient:<span class="Constant">0</span> ] -$warn: <span class="Constant">0</span> +$error: <span class="Constant">0</span> <span class="Delimiter">:(code)</span> string to_string<span class="Delimiter">(</span>const vector&lt;double&gt;&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">&quot;[]&quot;</span><span class="Delimiter">;</span> ostringstream out<span class="Delimiter">;</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - out &lt;&lt; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + out &lt;&lt; no_scientific<span class="Delimiter">(</span>in<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> out &lt;&lt; <span class="Constant">&quot;[&quot;</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>in<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>i &gt; <span class="Constant">0</span><span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">&quot;, &quot;</span><span class="Delimiter">;</span> - out &lt;&lt; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + out &lt;&lt; no_scientific<span class="Delimiter">(</span>in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> out &lt;&lt; <span class="Constant">&quot;]&quot;</span><span class="Delimiter">;</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> @@ -167,7 +202,7 @@ recipe test1 [ ] <span class="traceContains">+mem: storing 34 in location 1</span> -<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span> +<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr, recipe result)&quot;)</span> <span class="Comment">// rewrite `reply-if a, b, c, ...` to</span> <span class="Comment">// ```</span> <span class="Comment">// jump-unless a, 1:offset</span> @@ -175,7 +210,7 @@ recipe test1 [ <span class="Comment">// ```</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;reply-if&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;jump-unless&quot;</span>]<span class="Delimiter">;</span> + curr<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;jump-unless&quot;</span><span class="Delimiter">);</span> curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;jump-unless&quot;</span><span class="Delimiter">;</span> vector&lt;reagent&gt; results<span class="Delimiter">;</span> copy<span class="Delimiter">(</span>++curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>results<span class="Delimiter">,</span> results<span class="Delimiter">.</span>end<span class="Delimiter">()));</span> @@ -183,12 +218,12 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == < curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;1:offset&quot;</span><span class="Delimiter">));</span> result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> - curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;reply&quot;</span>]<span class="Delimiter">;</span> + curr<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">);</span> curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">;</span> curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>results<span class="Delimiter">);</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;'reply-if' never yields any products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;'reply-if' never yields any products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// rewrite `reply-unless a, b, c, ...` to</span> @@ -198,7 +233,7 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == < <span class="Comment">// ```</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;reply-unless&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;jump-if&quot;</span>]<span class="Delimiter">;</span> + curr<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;jump-if&quot;</span><span class="Delimiter">);</span> curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;jump-if&quot;</span><span class="Delimiter">;</span> vector&lt;reagent&gt; results<span class="Delimiter">;</span> copy<span class="Delimiter">(</span>++curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>results<span class="Delimiter">,</span> results<span class="Delimiter">.</span>end<span class="Delimiter">()));</span> @@ -206,12 +241,12 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == < curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;1:offset&quot;</span><span class="Delimiter">));</span> result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> - curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;reply&quot;</span>]<span class="Delimiter">;</span> + curr<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">);</span> curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">;</span> curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>results<span class="Delimiter">);</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;'reply-unless' never yields any products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;'reply-unless' never yields any products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> diff --git a/html/037recipe.cc.html b/html/037recipe.cc.html index 856e671c..44573495 100644 --- a/html/037recipe.cc.html +++ b/html/037recipe.cc.html @@ -13,13 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } -.Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -35,61 +32,26 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment">//: also like to make the recipe a variable, pass recipes to &quot;higher-order&quot;</span> <span class="Comment">//: recipes, return recipes from recipes and so on.</span> -<span class="Delimiter">:(scenario call_literal_recipe)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>call f:recipe<span class="Delimiter">,</span> <span class="Constant">34</span> -] -recipe f [ - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>next-ingredient - reply <span class="Constant">2</span>:number -] -<span class="traceContains">+mem: storing 34 in location 1</span> - -<span class="Delimiter">:(scenario call_variable)</span> -recipe main [ - <span class="Constant">1</span>:recipe-ordinal<span class="Special"> &lt;- </span>copy f:recipe - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>call <span class="Constant">1</span>:recipe-ordinal<span class="Delimiter">,</span> <span class="Constant">34</span> -] -recipe f [ - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>next-ingredient - reply <span class="Constant">3</span>:number -] -<span class="traceContains">+mem: storing 34 in location 2</span> - <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> <span class="Comment">// 'recipe' is a literal</span> -Type_ordinal[<span class="Constant">&quot;recipe&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;recipe&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// 'recipe-ordinal' is the literal that can store recipe literals</span> -type_ordinal recipe_ordinal = Type_ordinal[<span class="Constant">&quot;recipe-ordinal&quot;</span>] = Next_type_ordinal++<span class="Delimiter">;</span> -Type[recipe_ordinal]<span class="Delimiter">.</span>name = <span class="Constant">&quot;recipe-ordinal&quot;</span><span class="Delimiter">;</span> +type_ordinal recipe_ordinal = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;recipe-ordinal&quot;</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> +get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recipe_ordinal<span class="Delimiter">).</span>name = <span class="Constant">&quot;recipe-ordinal&quot;</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Reagent-parsing Exceptions&quot;)</span> -if <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;recipe&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>Recipe_ordinal[r<span class="Delimiter">.</span>name]<span class="Delimiter">);</span> +if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second &amp;&amp; r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;recipe&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<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="Delimiter">}</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -CALL<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;call&quot;</span>] = CALL<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case CALL: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'call' requires at least one ingredient (the recipe to call)</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Comment">// Begin Call</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'call' should be a recipe, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Comment">// todo: when we start doing type checking this will be a prime point of</span> - <span class="Comment">// attention, so we don't accidentally allow external data to a program to</span> - <span class="Comment">// run as code.</span> - Current_routine<span class="Delimiter">-&gt;</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> - <span class="Identifier">goto</span> call_housekeeping<span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +bool is_mu_recipe<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <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> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;recipe&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;recipe-ordinal&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Comment">// End is_mu_recipe Cases</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> </body> diff --git a/html/038scheduler.cc.html b/html/038scheduler.cc.html index 3a258741..16b3efbb 100644 --- a/html/038scheduler.cc.html +++ b/html/038scheduler.cc.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.SalientComment { color: #00ffff; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } +.SalientComment { color: #00ffff; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -93,7 +93,7 @@ void run<span class="Delimiter">(</span>routine* rr<span class="Delimiter">)</sp skip_to_next_routine<span class="Delimiter">();</span> assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>state == RUNNING<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; current_routine_label<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9990</span><span class="Delimiter">,</span> <span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; current_routine_label<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> run_current_routine<span class="Delimiter">(</span>Scheduling_interval<span class="Delimiter">);</span> <span class="Comment">// Scheduler State Transitions</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>completed<span class="Delimiter">())</span> @@ -129,10 +129,10 @@ void skip_to_next_routine<span class="Delimiter">()</span> <span class="Delimite string current_routine_label<span class="Delimiter">()</span> <span class="Delimiter">{</span> ostringstream result<span class="Delimiter">;</span> - call_stack calls = Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>call_stack::iterator p = calls<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != calls<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const call_stack&amp; calls = Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>call_stack::const_iterator p = calls<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != calls<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>p != calls<span class="Delimiter">.</span>begin<span class="Delimiter">())</span> result &lt;&lt; <span class="Constant">'/'</span><span class="Delimiter">;</span> - result &lt;&lt; Recipe[p<span class="Delimiter">-&gt;</span>running_recipe]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + result &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> p<span class="Delimiter">-&gt;</span>running_recipe<span class="Delimiter">).</span>name<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> @@ -141,22 +141,16 @@ string current_routine_label<span class="Delimiter">()</span> <span class="Delim for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> delete Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> Routines<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Current_routine = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Comment">//: special case for the very first routine</span> <span class="Delimiter">:(replace{} &quot;void run_main(int argc, char* argv[])&quot;)</span> void run_main<span class="Delimiter">(</span>int argc<span class="Delimiter">,</span> char* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - recipe_ordinal r = Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span> + recipe_ordinal r = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">));</span> if <span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// pass in commandline args as ingredients to main</span> - <span class="Comment">// todo: test this</span> - routine* rr = new routine<span class="Delimiter">(</span>r<span class="Delimiter">);</span> - Current_routine = rr<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; argc<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - vector&lt;double&gt; arg<span class="Delimiter">;</span> - arg<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_mu_string<span class="Delimiter">(</span>argv[i]<span class="Delimiter">));</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg<span class="Delimiter">);</span> - <span class="Delimiter">}</span> - run<span class="Delimiter">(</span>rr<span class="Delimiter">);</span> + routine* main_routine = new routine<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + <span class="Comment">// Update main_routine</span> + run<span class="Delimiter">(</span>main_routine<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -184,26 +178,31 @@ parent_index = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> START_RUNNING<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;start-running&quot;</span>] = START_RUNNING<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;start-running&quot;</span><span class="Delimiter">,</span> START_RUNNING<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case START_RUNNING: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;'start-running' requires at least one ingredient: the recipe to start running</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'start-running' requires at least one ingredient: the recipe to start running</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;first ingredient of 'start-running' should be a recipe, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <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 &lt;&lt; <span class="Constant">&quot;'start-running' received non-existent recipe: '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_recipe<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'start-running' should be a recipe, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case START_RUNNING: <span class="Delimiter">{</span> routine* new_routine = new routine<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> new_routine<span class="Delimiter">-&gt;</span>parent_index = Current_routine_index<span class="Delimiter">;</span> <span class="Comment">// populate ingredients</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> new_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + reagent ingredient = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> + new_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + ingredient<span class="Delimiter">.</span>type = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Comment">// release long-lived pointer</span> + <span class="Delimiter">}</span> Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> 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>new_routine<span class="Delimiter">-&gt;</span>id<span class="Delimiter">);</span> @@ -243,7 +242,7 @@ recipe f2 [ <span class="traceContains">+schedule: f1</span> <span class="traceContains">+run: 2:number &lt;- copy 0</span> -<span class="Delimiter">:(scenario start_running_takes_args)</span> +<span class="Delimiter">:(scenario start_running_takes_ingredients)</span> recipe f1 [ start-running f2:recipe<span class="Delimiter">,</span> <span class="Constant">3</span> <span class="Comment"># wait for f2 to run</span> @@ -296,6 +295,30 @@ recipe f1 [ <span class="traceContains">+schedule: f1</span> <span class="traceAbsent">-run: idle</span> +<span class="SalientComment">//:: Errors in a routine cause it to terminate.</span> + +<span class="Delimiter">:(scenario scheduler_terminates_routines_after_errors)</span> +<span class="Special">% Hide_errors = true;</span> +<span class="Special">% Scheduling_interval = 2;</span> +recipe f1 [ + start-running f2:recipe + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> +] +recipe f2 [ + <span class="Comment"># divide by 0 twice</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> + <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> +] +<span class="Comment"># f2 should stop after first divide by 0</span> +<span class="traceContains">+error: f2: divide by zero in '3:number &lt;- divide-with-remainder 4, 0'</span> +<span class="traceAbsent">-error: f2: divide by zero in '4:number &lt;- divide-with-remainder 4, 0'</span> + +<span class="Delimiter">:(after &quot;operator&lt;&lt;(ostream&amp; os, unused end)&quot;)</span> + if <span class="Delimiter">(</span>Trace_stream &amp;&amp; Trace_stream<span class="Delimiter">-&gt;</span>curr_label == <span class="Constant">&quot;error&quot;</span> &amp;&amp; Current_routine<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Current_routine<span class="Delimiter">-&gt;</span>state = COMPLETED<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="SalientComment">//:: Routines are marked completed when their parent completes.</span> <span class="Delimiter">:(scenario scheduler_kills_orphans)</span> @@ -346,17 +369,21 @@ recipe f2 [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> ROUTINE_STATE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;routine-state&quot;</span>] = ROUTINE_STATE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;routine-state&quot;</span><span class="Delimiter">,</span> ROUTINE_STATE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case ROUTINE_STATE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'routine-state' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'routine-state' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case ROUTINE_STATE: <span class="Delimiter">{</span> long long int id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> long long int result = -<span class="Constant">1</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -375,17 +402,21 @@ case ROUTINE_STATE: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> RESTART<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;restart&quot;</span>] = RESTART<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;restart&quot;</span><span class="Delimiter">,</span> RESTART<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case RESTART: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'restart' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'restart' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'restart' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'restart' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case RESTART: <span class="Delimiter">{</span> long long int id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -399,17 +430,21 @@ case RESTART: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> STOP<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;stop&quot;</span>] = STOP<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;stop&quot;</span><span class="Delimiter">,</span> STOP<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case STOP: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'stop' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'stop' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'stop' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'stop' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case STOP: <span class="Delimiter">{</span> long long int id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -423,7 +458,11 @@ case STOP: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _DUMP_ROUTINES<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$dump-routines&quot;</span>] = _DUMP_ROUTINES<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$dump-routines&quot;</span><span class="Delimiter">,</span> _DUMP_ROUTINES<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _DUMP_ROUTINES: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _DUMP_ROUTINES: <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -456,7 +495,7 @@ DISCONTINUED<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Scheduler State Transitions&quot;)</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>limit &gt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>limit &lt;= Scheduling_interval<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;discontinuing routine &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>id &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;discontinuing routine &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>id &lt;&lt; end<span class="Delimiter">();</span> Current_routine<span class="Delimiter">-&gt;</span>state = DISCONTINUED<span class="Delimiter">;</span> Current_routine<span class="Delimiter">-&gt;</span>limit = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -473,21 +512,25 @@ limit = -<span class="Constant">1</span><span class="Delimiter">;</span> <span <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> LIMIT_TIME<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;limit-time&quot;</span>] = LIMIT_TIME<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;limit-time&quot;</span><span class="Delimiter">,</span> LIMIT_TIME<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case LIMIT_TIME: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'limit-time' requires exactly two ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'limit-time' requires exactly two ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'limit-time' should be a number (of instructions to run for), but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'limit-time' should be a number (of instructions to run for), but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case LIMIT_TIME: <span class="Delimiter">{</span> long long int id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/039wait.cc.html b/html/039wait.cc.html index dc19a3b3..057c54b6 100644 --- a/html/039wait.cc.html +++ b/html/039wait.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -66,14 +66,19 @@ waiting_on_location = old_value_of_waiting_location = <span class="Constant">0</ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> WAIT_FOR_LOCATION<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;wait-for-location&quot;</span>] = WAIT_FOR_LOCATION<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;wait-for-location&quot;</span><span class="Delimiter">,</span> WAIT_FOR_LOCATION<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case WAIT_FOR_LOCATION: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case WAIT_FOR_LOCATION: <span class="Delimiter">{</span> - reagent loc = canonize<span class="Delimiter">(</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> + reagent loc = 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> + canonize<span class="Delimiter">(</span>loc<span class="Delimiter">);</span> Current_routine<span class="Delimiter">-&gt;</span>state = WAITING<span class="Delimiter">;</span> Current_routine<span class="Delimiter">-&gt;</span>waiting_on_location = loc<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - Current_routine<span class="Delimiter">-&gt;</span>old_value_of_waiting_location = Memory[loc<span class="Delimiter">.</span>value]<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for location &quot;</span> &lt;&lt; loc<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot; to change from &quot;</span> &lt;&lt; Memory[loc<span class="Delimiter">.</span>value] &lt;&lt; end<span class="Delimiter">();</span> + Current_routine<span class="Delimiter">-&gt;</span>old_value_of_waiting_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">.</span>value<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for location &quot;</span> &lt;&lt; loc<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot; to change from &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">.</span>value<span class="Delimiter">))</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -83,8 +88,8 @@ case WAIT_FOR_LOCATION: <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state != WAITING<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_location &amp;&amp; - Memory[Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_location] != Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>old_value_of_waiting_location<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_location<span class="Delimiter">)</span> != Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>old_value_of_waiting_location<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">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state = RUNNING<span class="Delimiter">;</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_location = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>old_value_of_waiting_location = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -120,24 +125,28 @@ waiting_on_routine = <span class="Constant">0</span><span class="Delimiter">;</s <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> WAIT_FOR_ROUTINE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;wait-for-routine&quot;</span>] = WAIT_FOR_ROUTINE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;wait-for-routine&quot;</span><span class="Delimiter">,</span> WAIT_FOR_ROUTINE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case WAIT_FOR_ROUTINE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'wait-for-routine' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'wait-for-routine' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case WAIT_FOR_ROUTINE: <span class="Delimiter">{</span> if <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> == Current_routine<span class="Delimiter">-&gt;</span>id<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: routine can't wait for itself! &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;routine can't wait for itself! &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-&gt;</span>state = WAITING<span class="Delimiter">;</span> Current_routine<span class="Delimiter">-&gt;</span>waiting_on_routine = 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> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for routine &quot;</span> &lt;&lt; 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> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for routine &quot;</span> &lt;&lt; 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> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -152,7 +161,7 @@ for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</ assert<span class="Delimiter">(</span>id != Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id<span class="Delimiter">);</span> <span class="Comment">// routine can't wait on itself</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)-&gt;</span>id == id &amp;&amp; Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)-&gt;</span>state != RUNNING<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine &quot;</span> &lt;&lt; Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine &quot;</span> &lt;&lt; Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id &lt;&lt; end<span class="Delimiter">();</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state = RUNNING<span class="Delimiter">;</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_routine = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -162,7 +171,11 @@ for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SWITCH<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;switch&quot;</span>] = SWITCH<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;switch&quot;</span><span class="Delimiter">,</span> SWITCH<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SWITCH: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case SWITCH: <span class="Delimiter">{</span> long long int id = some_other_running_routine<span class="Delimiter">();</span> diff --git a/html/040brace.cc.html b/html/040brace.cc.html index eb62a889..6f994e22 100644 --- a/html/040brace.cc.html +++ b/html/040brace.cc.html @@ -13,13 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -60,99 +61,108 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: jump 1:offset</span> -<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: jump 1:offset</span> +<span class="traceContains">+transform: copy ...</span> -<span class="Comment">//: one-time setup</span> -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_braces<span class="Delimiter">);</span> +<span class="Delimiter">:(after &quot;Begin Transforms&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_braces<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(code)</span> void transform_braces<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> const int OPEN = <span class="Constant">0</span><span class="Delimiter">,</span> CLOSE = <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// use signed integer for step index because we'll be doing arithmetic on it</span> list&lt;pair&lt;int<span class="Comment">/*</span><span class="Comment">OPEN/CLOSE</span><span class="Comment">*/</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">step</span><span class="Comment">*/</span>long long int&gt; &gt; braces<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- transform braces for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- transform braces for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">&quot;{&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: push (open, &quot;</span> &lt;&lt; index &lt;&lt; <span class="Constant">&quot;)&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;push (open, &quot;</span> &lt;&lt; index &lt;&lt; <span class="Constant">&quot;)&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> braces<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;int<span class="Delimiter">,</span>long long int&gt;<span class="Delimiter">(</span>OPEN<span class="Delimiter">,</span> index<span class="Delimiter">));</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">&quot;}&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;push (close, &quot;</span> &lt;&lt; index &lt;&lt; <span class="Constant">&quot;)&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;push (close, &quot;</span> &lt;&lt; index &lt;&lt; <span class="Constant">&quot;)&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> braces<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;int<span class="Delimiter">,</span>long long int&gt;<span class="Delimiter">(</span>CLOSE<span class="Delimiter">,</span> index<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> stack&lt;<span class="Comment">/*</span><span class="Comment">step</span><span class="Comment">*/</span>long long int&gt; open_braces<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;recipe &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> - for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">&quot;{&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> open_braces<span class="Delimiter">.</span>push<span class="Delimiter">(</span>index<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">&quot;}&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;missing '{' in &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> open_braces<span class="Delimiter">.</span>pop<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation != Recipe_ordinal[<span class="Constant">&quot;loop&quot;</span>] - &amp;&amp; inst<span class="Delimiter">.</span>operation != Recipe_ordinal[<span class="Constant">&quot;loop-if&quot;</span>] - &amp;&amp; inst<span class="Delimiter">.</span>operation != Recipe_ordinal[<span class="Constant">&quot;loop-unless&quot;</span>] - &amp;&amp; inst<span class="Delimiter">.</span>operation != Recipe_ordinal[<span class="Constant">&quot;break&quot;</span>] - &amp;&amp; inst<span class="Delimiter">.</span>operation != Recipe_ordinal[<span class="Constant">&quot;break-if&quot;</span>] - &amp;&amp; inst<span class="Delimiter">.</span>operation != Recipe_ordinal[<span class="Constant">&quot;break-unless&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; ...&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;loop&quot;</span> + &amp;&amp; inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;loop-if&quot;</span> + &amp;&amp; inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;loop-unless&quot;</span> + &amp;&amp; inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;break&quot;</span> + &amp;&amp; inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;break-if&quot;</span> + &amp;&amp; inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;break-unless&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; inst<span class="Delimiter">.</span>old_name &lt;&lt; <span class="Constant">&quot; ...&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">// check for errors</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos || inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos || inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; expects 1 or 2 ingredients, but got none</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; inst<span class="Delimiter">.</span>old_name &lt;&lt; <span class="Constant">&quot; expects 1 or 2 ingredients, but got none</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// update instruction operation</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> - inst<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;jump-if&quot;</span>]<span class="Delimiter">;</span> - else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> - inst<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;jump-unless&quot;</span>]<span class="Delimiter">;</span> - else - inst<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;jump&quot;</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>name = <span class="Constant">&quot;jump-if&quot;</span><span class="Delimiter">;</span> + inst<span class="Delimiter">.</span>operation = JUMP_IF<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>name = <span class="Constant">&quot;jump-unless&quot;</span><span class="Delimiter">;</span> + inst<span class="Delimiter">.</span>operation = JUMP_UNLESS<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>name = <span class="Constant">&quot;jump&quot;</span><span class="Delimiter">;</span> + inst<span class="Delimiter">.</span>operation = JUMP<span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Comment">// check for explicitly provided targets</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos || inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos || inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// conditional branches check arg 1</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span> &amp;&amp; is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">' '</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// unconditional branches check arg 0</span> if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// if implicit, compute target</span> reagent target<span class="Delimiter">;</span> - target<span class="Delimiter">.</span>types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;offset&quot;</span>]<span class="Delimiter">);</span> + target<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;offset&quot;</span><span class="Delimiter">));</span> + target<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second = new string_tree<span class="Delimiter">(</span><span class="Constant">&quot;offset&quot;</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> if <span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; needs a '{' before</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;loop&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> + raise_error &lt;&lt; inst<span class="Delimiter">.</span>old_name &lt;&lt; <span class="Constant">&quot; needs a '{' before</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;loop&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> target<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">()</span>-index<span class="Delimiter">);</span> else <span class="Comment">// break instruction</span> target<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>matching_brace<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">(),</span> braces<span class="Delimiter">,</span> r<span class="Delimiter">)</span> - index - <span class="Constant">1</span><span class="Delimiter">);</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>target<span class="Delimiter">);</span> <span class="Comment">// log computed target</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-if&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump-if &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; target<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;-unless&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump-unless &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; target<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;jump&quot;</span><span class="Delimiter">)</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>target<span class="Delimiter">.</span>value<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> else - trace<span class="Delimiter">(</span><span class="Constant">&quot;after-brace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;jump &quot;</span> &lt;&lt; target<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">' '</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>target<span class="Delimiter">.</span>value<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;:offset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -165,34 +175,10 @@ long long int matching_brace<span class="Delimiter">(</span>long long int index< stacksize += <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>first ? <span class="Constant">1</span> : -<span class="Constant">1</span><span class="Delimiter">);</span> if <span class="Delimiter">(</span>stacksize == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span> <span class="Delimiter">}</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: unbalanced '{'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> <span class="Comment">// exit current routine</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;unbalanced '{'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> <span class="Comment">// exit current routine</span> <span class="Delimiter">}</span> -<span class="Comment">// temporarily suppress run</span> -void transform<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> - load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> - transform_all<span class="Delimiter">();</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: Make sure these pseudo recipes get consistent numbers in all tests, even</span> -<span class="Comment">//: though they aren't implemented.</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -BREAK<span class="Delimiter">,</span> -BREAK_IF<span class="Delimiter">,</span> -BREAK_UNLESS<span class="Delimiter">,</span> -LOOP<span class="Delimiter">,</span> -LOOP_IF<span class="Delimiter">,</span> -LOOP_UNLESS<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;break&quot;</span>] = BREAK<span class="Delimiter">;</span> -Recipe_ordinal[<span class="Constant">&quot;break-if&quot;</span>] = BREAK_IF<span class="Delimiter">;</span> -Recipe_ordinal[<span class="Constant">&quot;break-unless&quot;</span>] = BREAK_UNLESS<span class="Delimiter">;</span> -Recipe_ordinal[<span class="Constant">&quot;loop&quot;</span>] = LOOP<span class="Delimiter">;</span> -Recipe_ordinal[<span class="Constant">&quot;loop-if&quot;</span>] = LOOP_IF<span class="Delimiter">;</span> -Recipe_ordinal[<span class="Constant">&quot;loop-unless&quot;</span>] = LOOP_UNLESS<span class="Delimiter">;</span> - <span class="Delimiter">:(scenario loop)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> @@ -202,11 +188,11 @@ recipe main [ loop <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump -2:offset</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump -2:offset</span> <span class="Delimiter">:(scenario break_empty_block)</span> recipe main [ @@ -215,9 +201,9 @@ recipe main [ <span class="Identifier">break</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump 0:offset</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump 0:offset</span> <span class="Delimiter">:(scenario break_cascading)</span> recipe main [ @@ -229,10 +215,10 @@ recipe main [ <span class="Identifier">break</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump 0:offset</span> -<span class="traceContains">+after-brace: jump 0:offset</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump 0:offset</span> +<span class="traceContains">+transform: jump 0:offset</span> <span class="Delimiter">:(scenario break_cascading_2)</span> recipe main [ @@ -246,12 +232,12 @@ recipe main [ <span class="Identifier">break</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump 1:offset</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump 0:offset</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump 1:offset</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump 0:offset</span> <span class="Delimiter">:(scenario break_if)</span> recipe main [ @@ -265,12 +251,12 @@ recipe main [ <span class="Identifier">break</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump-if 2, 1:offset</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump 0:offset</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump-if 2, 1:offset</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump 0:offset</span> <span class="Delimiter">:(scenario break_nested)</span> recipe main [ @@ -284,7 +270,7 @@ recipe main [ <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: jump 4:offset</span> +<span class="traceContains">+transform: jump 4:offset</span> <span class="Delimiter">:(scenario break_nested_degenerate)</span> recipe main [ @@ -297,7 +283,7 @@ recipe main [ <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: jump 3:offset</span> +<span class="traceContains">+transform: jump 3:offset</span> <span class="Delimiter">:(scenario break_nested_degenerate_2)</span> recipe main [ @@ -309,17 +295,17 @@ recipe main [ <span class="Delimiter">}</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: jump 2:offset</span> +<span class="traceContains">+transform: jump 2:offset</span> <span class="Delimiter">:(scenario break_label)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Identifier">break</span> +foo:offset <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: jump +foo:offset</span> +<span class="traceContains">+transform: jump +foo:offset</span> <span class="Delimiter">:(scenario break_unless)</span> recipe main [ @@ -330,11 +316,11 @@ recipe main [ <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump-unless 2, 1:offset</span> -<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump-unless 2, 1:offset</span> +<span class="traceContains">+transform: copy ...</span> <span class="Delimiter">:(scenario loop_unless)</span> recipe main [ @@ -345,11 +331,11 @@ recipe main [ <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: jump-unless 2, -1:offset</span> -<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: jump-unless 2, -1:offset</span> +<span class="traceContains">+transform: copy ...</span> <span class="Delimiter">:(scenario loop_nested)</span> recipe main [ @@ -363,8 +349,8 @@ recipe main [ <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: jump-if 4, -5:offset</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: jump-if 4, -5:offset</span> <span class="Delimiter">:(scenario loop_label)</span> recipe main [ @@ -372,9 +358,9 @@ recipe main [ +foo <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] -<span class="traceContains">+after-brace: recipe main</span> -<span class="traceContains">+after-brace: copy ...</span> -<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+transform: --- transform braces for recipe main</span> +<span class="traceContains">+transform: copy ...</span> +<span class="traceContains">+transform: copy ...</span> <span class="Comment">//: test how things actually run</span> <span class="Delimiter">:(scenarios run)</span> @@ -394,21 +380,47 @@ recipe test-factorial [ ] <span class="traceContains">+mem: location 2 is 120</span> -<span class="Delimiter">:(scenario break_outside_braces_warns)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario break_outside_braces_fails)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Identifier">break</span> ] -<span class="traceContains">+warn: break needs a '{' before</span> +<span class="traceContains">+error: break needs a '{' before</span> -<span class="Delimiter">:(scenario break_conditional_without_ingredient_warns)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario break_conditional_without_ingredient_fails)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Delimiter">{</span> <span class="Identifier">break</span>-if <span class="Delimiter">}</span> ] -<span class="traceContains">+warn: break-if expects 1 or 2 ingredients, but got none</span> +<span class="traceContains">+error: break-if expects 1 or 2 ingredients, but got none</span> + +<span class="Comment">//: Make sure these pseudo recipes get consistent numbers in all tests, even</span> +<span class="Comment">//: though they aren't implemented. Allows greater flexibility in ordering</span> +<span class="Comment">//: transforms.</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +BREAK<span class="Delimiter">,</span> +BREAK_IF<span class="Delimiter">,</span> +BREAK_UNLESS<span class="Delimiter">,</span> +LOOP<span class="Delimiter">,</span> +LOOP_IF<span class="Delimiter">,</span> +LOOP_UNLESS<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;break&quot;</span><span class="Delimiter">,</span> BREAK<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;break-if&quot;</span><span class="Delimiter">,</span> BREAK_IF<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;break-unless&quot;</span><span class="Delimiter">,</span> BREAK_UNLESS<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;loop&quot;</span><span class="Delimiter">,</span> LOOP<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;loop-if&quot;</span><span class="Delimiter">,</span> LOOP_IF<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;loop-unless&quot;</span><span class="Delimiter">,</span> LOOP_UNLESS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case BREAK: <span class="Identifier">break</span><span class="Delimiter">;</span> +case BREAK_IF: <span class="Identifier">break</span><span class="Delimiter">;</span> +case BREAK_UNLESS: <span class="Identifier">break</span><span class="Delimiter">;</span> +case LOOP: <span class="Identifier">break</span><span class="Delimiter">;</span> +case LOOP_IF: <span class="Identifier">break</span><span class="Delimiter">;</span> +case LOOP_UNLESS: <span class="Identifier">break</span><span class="Delimiter">;</span> </pre> </body> </html> diff --git a/html/041jump_target.cc.html b/html/041jump_target.cc.html index 8c0ce0cf..53f93910 100644 --- a/html/041jump_target.cc.html +++ b/html/041jump_target.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.traceAbsent { color: #c00000; } .traceContains { color: #008000; } +.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -50,41 +50,41 @@ recipe main [ <span class="traceAbsent">-mem: storing 0 in location 1</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -Type_ordinal[<span class="Constant">&quot;label&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;label&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_labels<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;Transform.push_back(transform_braces)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_labels<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(code)</span> void transform_labels<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> map&lt;string<span class="Delimiter">,</span> long long int&gt; offset<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>label<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; inst<span class="Delimiter">.</span>label<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> - if <span class="Delimiter">(</span>offset<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> == offset<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>offset<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> <span class="Delimiter">{</span> offset[inst<span class="Delimiter">.</span>label] = i<span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: duplicate label '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>label &lt;&lt; <span class="Constant">&quot;'&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;duplicate label '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>label &lt;&lt; <span class="Constant">&quot;'&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Comment">// have all jumps skip some random but noticeable and deterministic amount of code</span> offset[inst<span class="Delimiter">.</span>label] = <span class="Constant">9999</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;jump&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;jump&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> replace_offset<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> offset<span class="Delimiter">,</span> i<span class="Delimiter">,</span> r<span class="Delimiter">);</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;jump-if&quot;</span>] || inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;jump-unless&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;jump-if&quot;</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;jump-unless&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> replace_offset<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">),</span> offset<span class="Delimiter">,</span> i<span class="Delimiter">,</span> r<span class="Delimiter">);</span> <span class="Delimiter">}</span> - if <span class="Delimiter">((</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;loop&quot;</span>] || inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;break&quot;</span>]<span class="Delimiter">)</span> + if <span class="Delimiter">((</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;loop&quot;</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;break&quot;</span><span class="Delimiter">)</span> &amp;&amp; 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> replace_offset<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> offset<span class="Delimiter">,</span> i<span class="Delimiter">,</span> r<span class="Delimiter">);</span> <span class="Delimiter">}</span> - if <span class="Delimiter">((</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;loop-if&quot;</span>] || inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;loop-unless&quot;</span>] - || inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;break-if&quot;</span>] || inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;break-unless&quot;</span>]<span class="Delimiter">)</span> + if <span class="Delimiter">((</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;loop-if&quot;</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;loop-unless&quot;</span> + || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;break-if&quot;</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;break-unless&quot;</span><span class="Delimiter">)</span> &amp;&amp; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> == <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> replace_offset<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">),</span> offset<span class="Delimiter">,</span> i<span class="Delimiter">,</span> r<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -94,19 +94,19 @@ void transform_labels<span class="Delimiter">(</span>const recipe_ordinal r<span <span class="Delimiter">:(code)</span> void replace_offset<span class="Delimiter">(</span>reagent&amp; x<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">const</span><span class="Comment">*/</span> map&lt;string<span class="Delimiter">,</span> long long int&gt;&amp; offset<span class="Delimiter">,</span> const long long int current_offset<span class="Delimiter">,</span> const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: jump target must be offset or label but is &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;jump target must be offset or label but is &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// no jump by default</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> assert<span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">);</span> if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// non-labels will be handled like other number operands</span> if <span class="Delimiter">(</span>!is_jump_target<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: can't jump to label &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;can't jump to label &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// no jump by default</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>offset<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == offset<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: can't find label &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>offset<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;can't find label &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// no jump by default</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -167,18 +167,18 @@ recipe main [ <span class="traceContains">+mem: storing 0 in location 5</span> <span class="traceAbsent">-mem: storing 0 in location 4</span> -<span class="Delimiter">:(scenario recipe_warns_on_duplicate_jump_target)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario recipe_fails_on_duplicate_jump_target)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ +label <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> +label <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] -<span class="traceContains">+warn: main: duplicate label '+label'</span> +<span class="traceContains">+error: main: duplicate label '+label'</span> <span class="Delimiter">:(scenario jump_ignores_nontarget_label)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Comment"># first a few lines of padding to exercise the offset computation</span> <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> @@ -189,7 +189,7 @@ recipe main [ $target <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] -<span class="traceContains">+warn: main: can't jump to label $target</span> +<span class="traceContains">+error: main: can't jump to label $target</span> </pre> </body> </html> diff --git a/html/042name.cc.html b/html/042name.cc.html index 16cf8117..da006079 100644 --- a/html/042name.cc.html +++ b/html/042name.cc.html @@ -13,15 +13,16 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } -.SalientComment { color: #00ffff; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } +.Identifier { color: #804000; } +.cSpecial { color: #008000; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.Identifier { color: #804000; } -.traceContains { color: #008000; } +.CommentedCode { color: #6c6c6c; } +.SalientComment { color: #00ffff; } --> </style> @@ -45,15 +46,16 @@ recipe main [ <span class="traceContains">+mem: storing 0 in location 1</span> <span class="Delimiter">:(scenarios transform)</span> -<span class="Delimiter">:(scenario transform_names_warns)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario transform_names_fails_on_use_before_define)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number<span class="Special"> &lt;- </span>copy y:number ] -<span class="traceContains">+warn: use before set: y in main</span> +<span class="traceContains">+error: main: use before set: y</span> +<span class="Comment"># todo: detect conditional defines</span> -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_names<span class="Delimiter">);</span> +<span class="Delimiter">:(after &quot;Transform.push_back(check_or_set_invalid_types&quot;)</span> <span class="Comment">// there'll be other transforms relating to types; they all need to happen first</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_names<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> map&lt;recipe_ordinal<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> long long int&gt; &gt; Name<span class="Delimiter">;</span> @@ -64,31 +66,33 @@ for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</ <span class="Delimiter">:(code)</span> void transform_names<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- transform names for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- transform names for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> bool names_used = <span class="Constant">false</span><span class="Delimiter">;</span> bool numeric_locations_used = <span class="Constant">false</span><span class="Delimiter">;</span> map&lt;string<span class="Delimiter">,</span> long long int&gt;&amp; names = Name[r]<span class="Delimiter">;</span> <span class="Comment">// store the indices 'used' so far in the map</span> long long int&amp; curr_idx = names[<span class="Constant">&quot;&quot;</span>]<span class="Delimiter">;</span> ++curr_idx<span class="Delimiter">;</span> <span class="Comment">// avoid using index 0, benign skip in some other cases</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - <span class="Comment">// Per-recipe Transforms</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + <span class="Comment">// End transform_names(inst) Special-cases</span> <span class="Comment">// map names to addresses</span> for <span class="Delimiter">(</span>long long int in = <span class="Constant">0</span><span class="Delimiter">;</span> in &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++in<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>is_numeric_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">)))</span> numeric_locations_used = <span class="Constant">true</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>is_named_location<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_used = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>disqualified<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> inst<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>disqualified<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> inst<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="Identifier">continue</span><span class="Delimiter">;</span> if <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 &lt;&lt; <span class="Constant">&quot;use before set: &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; in &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;use before set: &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<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>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="Delimiter">}</span> for <span class="Delimiter">(</span>long long int out = <span class="Constant">0</span><span class="Delimiter">;</span> out &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++out<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>is_numeric_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">)))</span> numeric_locations_used = <span class="Constant">true</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>is_named_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">)))</span> names_used = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>disqualified<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">),</span> inst<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>disqualified<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">),</span> inst<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="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>names<span class="Delimiter">.</span>find<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> == names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;assign &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; &quot;</span> &lt;&lt; curr_idx &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;assign &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; &quot;</span> &lt;&lt; curr_idx &lt;&lt; end<span class="Delimiter">();</span> names[inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">).</span>name] = curr_idx<span class="Delimiter">;</span> curr_idx += size_of<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">));</span> <span class="Delimiter">}</span> @@ -96,12 +100,12 @@ void transform_names<span class="Delimiter">(</span>const recipe_ordinal r<span <span class="Delimiter">}</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>names_used &amp;&amp; numeric_locations_used<span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;mixing variable names and numeric addresses in &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;mixing variable names and numeric addresses</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> -bool disqualified<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">mutable</span><span class="Comment">*/</span> reagent&amp; x<span class="Delimiter">,</span> const instruction&amp; inst<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;missing type in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> +bool disqualified<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">mutable</span><span class="Comment">*/</span> reagent&amp; x<span class="Delimiter">,</span> const instruction&amp; inst<span class="Delimiter">,</span> const string&amp; recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;missing type for &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot; in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> @@ -113,27 +117,28 @@ bool disqualified<span class="Delimiter">(</span><span class="Comment">/*</span> <span class="Delimiter">}</span> bool already_transformed<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">,</span> const map&lt;string<span class="Delimiter">,</span> long long int&gt;&amp; names<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != names<span class="Delimiter">.</span>end<span class="Delimiter">();</span> + <span class="Identifier">return</span> contains_key<span class="Delimiter">(</span>names<span class="Delimiter">,</span> r<span class="Delimiter">.</span>name<span class="Delimiter">);</span> <span class="Delimiter">}</span> long long int lookup_name<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">,</span> const recipe_ordinal default_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> Name[default_recipe][r<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> <span class="Delimiter">}</span> -type_ordinal skip_addresses<span class="Delimiter">(</span>const vector&lt;type_ordinal&gt;&amp; types<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != Type_ordinal[<span class="Constant">&quot;address&quot;</span>]<span class="Delimiter">)</span> <span class="Identifier">return</span> types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +type_ordinal skip_addresses<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> const string&amp; recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(;</span> type<span class="Delimiter">;</span> type = type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">))</span> + <span class="Identifier">return</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> <span class="Delimiter">}</span> - raise &lt;&lt; <span class="Constant">&quot;expected a container&quot;</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;expected a container&quot;</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -int find_element_name<span class="Delimiter">(</span>const type_ordinal t<span class="Delimiter">,</span> const string&amp; name<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const type_info&amp; container = Type[t]<span class="Delimiter">;</span> +int find_element_name<span class="Delimiter">(</span>const type_ordinal t<span class="Delimiter">,</span> const string&amp; name<span class="Delimiter">,</span> const string&amp; recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const type_info&amp; container = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> t<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>container<span class="Delimiter">.</span>element_names<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>container<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == name<span class="Delimiter">)</span> <span class="Identifier">return</span> i<span class="Delimiter">;</span> <span class="Delimiter">}</span> - raise &lt;&lt; <span class="Constant">&quot;unknown element &quot;</span> &lt;&lt; name &lt;&lt; <span class="Constant">&quot; in container &quot;</span> &lt;&lt; Type[t]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;unknown element &quot;</span> &lt;&lt; name &lt;&lt; <span class="Constant">&quot; in container &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> t<span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -151,13 +156,6 @@ bool is_named_location<span class="Delimiter">(</span>const reagent&amp; x<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> -bool is_raw<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int i = <span class="Comment">/*</span><span class="Comment">skip value+type</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>properties<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first == <span class="Constant">&quot;raw&quot;</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="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - bool is_special_name<span class="Delimiter">(</span>const string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>s == <span class="Constant">&quot;_&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>s == <span class="Constant">&quot;0&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> @@ -176,51 +174,51 @@ recipe main [ <span class="Comment">//: an escape hatch to suppress name conversion that we'll use later</span> <span class="Delimiter">:(scenarios run)</span> <span class="Delimiter">:(scenario transform_names_passes_raw)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number/<span class="Special">raw &lt;- </span>copy <span class="Constant">0</span> ] <span class="traceAbsent">-name: assign x 1</span> -<span class="traceContains">+warn: can't write to location 0 in 'x:number/raw &lt;- copy 0'</span> +<span class="traceContains">+error: can't write to location 0 in 'x:number/raw &lt;- copy 0'</span> <span class="Delimiter">:(scenarios transform)</span> -<span class="Delimiter">:(scenario transform_names_warns_when_mixing_names_and_numeric_locations)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario transform_names_fails_when_mixing_names_and_numeric_locations)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number ] -<span class="traceContains">+warn: mixing variable names and numeric addresses in main</span> +<span class="traceContains">+error: main: mixing variable names and numeric addresses</span> -<span class="Delimiter">:(scenario transform_names_warns_when_mixing_names_and_numeric_locations_2)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario transform_names_fails_when_mixing_names_and_numeric_locations_2)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy x:number ] -<span class="traceContains">+warn: mixing variable names and numeric addresses in main</span> +<span class="traceContains">+error: main: mixing variable names and numeric addresses</span> -<span class="Delimiter">:(scenario transform_names_does_not_warn_when_mixing_names_and_raw_locations)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario transform_names_does_not_fail_when_mixing_names_and_raw_locations)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number/<span class="Special">raw</span> ] -<span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span> -$warn: <span class="Constant">0</span> +<span class="traceAbsent">-error: main: mixing variable names and numeric addresses</span> +$error: <span class="Constant">0</span> -<span class="Delimiter">:(scenario transform_names_does_not_warn_when_mixing_names_and_literals)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Delimiter">:(scenario transform_names_does_not_fail_when_mixing_names_and_literals)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> ] -<span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span> -$warn: <span class="Constant">0</span> +<span class="traceAbsent">-error: main: mixing variable names and numeric addresses</span> +$error: <span class="Constant">0</span> <span class="SalientComment">//:: Support element names for containers in 'get' and 'get-address'.</span> <span class="Comment">//: update our running example container for the next test</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -Type[point]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;x&quot;</span><span class="Delimiter">);</span> -Type[point]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;y&quot;</span><span class="Delimiter">);</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;x&quot;</span><span class="Delimiter">);</span> +get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;y&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">:(scenario transform_names_transforms_container_elements)</span> recipe main [ p:address:point<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># unsafe</span> @@ -230,21 +228,20 @@ recipe main [ <span class="traceContains">+name: element y of type point is at offset 1</span> <span class="traceContains">+name: element x of type point is at offset 0</span> -<span class="Delimiter">:(after &quot;Per-recipe Transforms&quot;)</span> +<span class="Delimiter">:(before &quot;End transform_names(inst) Special-cases&quot;)</span> <span class="Comment">// replace element names of containers with offsets</span> -if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;get&quot;</span>] - || inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;get-address&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> +if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;get&quot;</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;get-address&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: exactly 2 ingredients expected in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;exactly 2 ingredients expected in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: expected ingredient 1 of &quot;</span> &lt;&lt; <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;get&quot;</span>] ? <span class="Constant">&quot;'get'&quot;</span> : <span class="Constant">&quot;'get-address'&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to have type 'offset'; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;expected ingredient 1 of &quot;</span> &lt;&lt; <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;get&quot;</span> ? <span class="Constant">&quot;'get'&quot;</span> : <span class="Constant">&quot;'get-address'&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to have type 'offset'; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// since first non-address in base type must be a container, we don't have to canonize</span> - type_ordinal base_type = skip_addresses<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>types<span class="Delimiter">);</span> - inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;element &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; is at offset &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value &lt;&lt; end<span class="Delimiter">();</span> + type_ordinal base_type = skip_addresses<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>type<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;element &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; is at offset &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -252,8 +249,8 @@ if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation <span class="Delimiter">:(scenarios transform)</span> <span class="Delimiter">:(scenario transform_names_handles_containers)</span> recipe main [ - a:point<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - b:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> + a:point<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Special">raw</span> + b:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Special">raw</span> ] <span class="traceContains">+name: assign a 1</span> <span class="traceContains">+name: assign b 3</span> @@ -271,19 +268,19 @@ recipe main [ <span class="traceContains">+name: variant p of type number-or-point has tag 1</span> <span class="traceContains">+mem: storing 13 in location 20</span> -<span class="Delimiter">:(after &quot;Per-recipe Transforms&quot;)</span> +<span class="Delimiter">:(before &quot;End transform_names(inst) Special-cases&quot;)</span> <span class="Comment">// convert variant names of exclusive containers</span> -if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;maybe-convert&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> +if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;maybe-convert&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: exactly 2 ingredients expected in '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;exactly 2 ingredients expected in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> assert<span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// since first non-address in base type must be an exclusive container, we don't have to canonize</span> - type_ordinal base_type = skip_addresses<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>types<span class="Delimiter">);</span> - inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;variant &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; has tag &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value &lt;&lt; end<span class="Delimiter">();</span> + type_ordinal base_type = skip_addresses<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>type<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;variant &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; has tag &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> diff --git a/html/043new.cc.html b/html/043new.cc.html index 82eaa244..35398d9f 100644 --- a/html/043new.cc.html +++ b/html/043new.cc.html @@ -13,9 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } -.SalientComment { color: #00ffff; } .traceContains { color: #008000; } +.SalientComment { color: #00ffff; } +.cSpecial { color: #008000; } .CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -57,81 +57,87 @@ long long int alloc<span class="Delimiter">,</span> alloc_max<span class="Delimi alloc = Memory_allocated_until<span class="Delimiter">;</span> Memory_allocated_until += Initial_memory_per_routine<span class="Delimiter">;</span> alloc_max = Memory_allocated_until<span class="Delimiter">;</span> -trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;routine allocated memory from &quot;</span> &lt;&lt; alloc &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; alloc_max &lt;&lt; end<span class="Delimiter">();</span> - -<span class="SalientComment">//:: First handle 'type' operands.</span> +trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;routine allocated memory from &quot;</span> &lt;&lt; alloc &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; alloc_max &lt;&lt; end<span class="Delimiter">();</span> +<span class="SalientComment">//:: 'new' takes a weird 'type' as its first ingredient; don't error on it</span> <span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -Type_ordinal[<span class="Constant">&quot;type&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="Delimiter">:(after &quot;Per-recipe Transforms&quot;)</span> -<span class="Comment">// replace type names with type_ordinals</span> -if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_ordinal[<span class="Constant">&quot;new&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// End NEW Transform Special-cases</span> - <span class="Comment">// first arg must be of type 'type'</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: 'new' expects one or two ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - if <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>properties<span class="Delimiter">.</span>empty<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>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<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>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != <span class="Constant">&quot;type&quot;</span><span class="Delimiter">)</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: first ingredient of 'new' should be a type, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<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>name<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;: unknown type &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<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>set_value<span class="Delimiter">(</span>Type_ordinal[inst<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="Delimiter">);</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; -&gt; &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> - end_new_transform:<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="SalientComment">//:: Now implement the primitive recipe.</span> -<span class="Comment">//: todo: build 'new' in mu itself</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;type&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> +<span class="SalientComment">//:: typecheck 'new' instructions</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> NEW<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;new&quot;</span>] = NEW<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">,</span> NEW<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case NEW: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'new' requires one or two ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'new' requires one or two ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'new' should be a type, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Comment">// End NEW Check Special-cases</span> + reagent type = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!is_mu_type_literal<span class="Delimiter">(</span>type<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'new' should be a type, but got &quot;</span> &lt;&lt; type<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Comment">// compute the space we need</span> - long long int size = <span class="Constant">0</span><span class="Delimiter">;</span> - long long int array_length = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Delimiter">{</span> - vector&lt;type_ordinal&gt; type<span class="Delimiter">;</span> - type<span class="Delimiter">.</span>push_back<span class="Delimiter">(</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>value<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// array</span> - array_length = 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> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;array size is &quot;</span> &lt;&lt; array_length &lt;&lt; end<span class="Delimiter">();</span> - size = array_length*size_of<span class="Delimiter">(</span>type<span class="Delimiter">)</span> + <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - else <span class="Delimiter">{</span> - <span class="Comment">// scalar</span> - size = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: translate 'new' to 'allocate' instructions that take a size instead of a type</span> +<span class="Delimiter">:(after &quot;Transform.push_back(check_instruction)&quot;)</span> <span class="Comment">// check_instruction will guard against direct 'allocate' instructions below</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_new_to_allocate<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void transform_new_to_allocate<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- convert 'new' to 'allocate' for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- convert 'new' to 'allocate' for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + <span class="Comment">// Convert 'new' To 'allocate'</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = ALLOCATE<span class="Delimiter">;</span> + string_tree* type_name = new string_tree<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>name<span class="Delimiter">);</span> + <span class="Comment">// End Post-processing(type_name) When Converting 'new'</span> + type_tree* type = new_type_tree<span class="Delimiter">(</span>type_name<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>set_value<span class="Delimiter">(</span>size_of<span class="Delimiter">(</span>type<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;size of &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>value &lt;&lt; end<span class="Delimiter">();</span> + delete type<span class="Delimiter">;</span> + delete type_name<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: implement 'allocate' based on size</span> + +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +ALLOCATE<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;allocate&quot;</span><span class="Delimiter">,</span> ALLOCATE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case ALLOCATE: <span class="Delimiter">{</span> + <span class="Comment">// compute the space we need</span> + long long int size = 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> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// array</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;array size is &quot;</span> &lt;&lt; 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> &lt;&lt; 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="CommentedCode">//? Total_alloc += size;</span> <span class="CommentedCode">//? Num_alloc++;</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> const long long int result = Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new alloc: &quot;</span> &lt;&lt; result &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new alloc: &quot;</span> &lt;&lt; result &lt;&lt; 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> - for <span class="Delimiter">(</span>long long int address = result<span class="Delimiter">;</span> address &lt; result+size<span class="Delimiter">;</span> ++address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Memory[address] = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - Memory[result] = array_length<span class="Delimiter">;</span> - <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int address = result<span class="Delimiter">;</span> address &lt; result+size<span class="Delimiter">;</span> ++address<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="Comment">// initialize array length</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<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="Comment">// bump</span> Current_routine<span class="Delimiter">-&gt;</span>alloc += size<span class="Delimiter">;</span> <span class="Comment">// no support for reclaiming memory</span> @@ -139,6 +145,20 @@ case NEW: <span class="Delimiter">{</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="SalientComment">//:: ensure we never call 'allocate' directly; its types are not checked</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case ALLOCATE: <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;never call 'allocate' directly'; always use 'new'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: ensure we never call 'new' without translating it (unless we add special-cases later)</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case NEW: <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;no implementation for 'new'; why wasn't it translated to 'allocate'?</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="CommentedCode">//? :(before &quot;End Globals&quot;)</span> <span class="CommentedCode">//? long long int Total_alloc = 0;</span> <span class="CommentedCode">//? long long int Num_alloc = 0;</span> @@ -163,13 +183,13 @@ void ensure_space<span class="Delimiter">(</span>long long int size<span class=" Current_routine<span class="Delimiter">-&gt;</span>alloc = Memory_allocated_until<span class="Delimiter">;</span> Memory_allocated_until += Initial_memory_per_routine<span class="Delimiter">;</span> Current_routine<span class="Delimiter">-&gt;</span>alloc_max = Memory_allocated_until<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;routine allocated memory from &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>alloc &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>alloc_max &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;routine allocated memory from &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>alloc &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>alloc_max &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario new_initializes)</span> <span class="Special">% Memory_allocated_until = 10;</span> -<span class="Special">% Memory[Memory_allocated_until] = 1;</span> +<span class="Special">% put(Memory, Memory_allocated_until, 1);</span> recipe main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>new number:type <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:number @@ -247,25 +267,31 @@ Free_list<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> ABANDON<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;abandon&quot;</span>] = ABANDON<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;abandon&quot;</span><span class="Delimiter">,</span> ABANDON<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case ABANDON: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'abandon' requires one ingredient, but got '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'abandon' requires one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'abandon' should be an address, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + reagent types = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>types<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!types<span class="Delimiter">.</span>type || types<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'abandon' should be an address, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case ABANDON: <span class="Delimiter">{</span> long long int address = 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> - reagent types = canonize<span class="Delimiter">(</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> - if <span class="Delimiter">(</span>types<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || types<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != Type_ordinal[<span class="Constant">&quot;address&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'abandon' should be an address, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - reagent target_type = lookup_memory<span class="Delimiter">(</span>types<span class="Delimiter">);</span> - abandon<span class="Delimiter">(</span>address<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>target_type<span class="Delimiter">));</span> + reagent types = 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> + canonize<span class="Delimiter">(</span>types<span class="Delimiter">);</span> + <span class="Comment">// lookup_memory without drop_one_lookup {</span> + types<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> types<span class="Delimiter">.</span>value<span class="Delimiter">));</span> + drop_address_from_type<span class="Delimiter">(</span>types<span class="Delimiter">);</span> + <span class="Comment">// }</span> + abandon<span class="Delimiter">(</span>address<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>types<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -276,26 +302,26 @@ void abandon<span class="Delimiter">(</span>long long int address<span class="De <span class="CommentedCode">//? cerr &lt;&lt; &quot;abandon: &quot; &lt;&lt; size &lt;&lt; '\n';</span> <span class="Comment">// clear memory</span> for <span class="Delimiter">(</span>long long int curr = address<span class="Delimiter">;</span> curr &lt; address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> - Memory[curr] = <span class="Constant">0</span><span class="Delimiter">;</span> + put<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="Comment">// append existing free list to address</span> - Memory[address] = Free_list[size]<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">,</span> Free_list[size]<span class="Delimiter">);</span> Free_list[size] = address<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(before &quot;ensure_space(size)&quot; following &quot;case NEW&quot;)</span> +<span class="Delimiter">:(before &quot;ensure_space(size)&quot; following &quot;case ALLOCATE&quot;)</span> if <span class="Delimiter">(</span>Free_list[size]<span class="Delimiter">)</span> <span class="Delimiter">{</span> long long int result = Free_list[size]<span class="Delimiter">;</span> - Free_list[size] = Memory[result]<span class="Delimiter">;</span> + Free_list[size] = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int curr = result+<span class="Constant">1</span><span class="Delimiter">;</span> curr &lt; result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Memory[curr] != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: memory in free list was not zeroed out: &quot;</span> &lt;&lt; curr &lt;&lt; <span class="Constant">'/'</span> &lt;&lt; result &lt;&lt; <span class="Constant">&quot;; somebody wrote to us after free!!!</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;memory in free list was not zeroed out: &quot;</span> &lt;&lt; curr &lt;&lt; <span class="Constant">'/'</span> &lt;&lt; result &lt;&lt; <span class="Constant">&quot;; somebody wrote to us after free!!!</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; 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> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> - Memory[result] = array_length<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<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> else - Memory[result] = <span class="Constant">0</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> 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> @@ -341,23 +367,16 @@ recipe main [ <span class="Comment"># unicode for '«'</span> <span class="traceContains">+mem: storing 171 in location 3</span> -<span class="Delimiter">:(before &quot;End NEW Transform Special-cases&quot;)</span> - if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> - &amp;&amp; !inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>properties<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> - &amp;&amp; !inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> - &amp;&amp; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// skip transform</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>initialized = <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Identifier">goto</span> end_new_transform<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - +<span class="Delimiter">:(before &quot;End NEW Check Special-cases&quot;)</span> +if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before &quot;Convert 'new' To 'allocate'&quot;)</span> +if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;new&quot;</span> &amp;&amp; is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">:(after &quot;case NEW&quot; following &quot;Primitive Recipe Implementations&quot;)</span> -if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</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> - &amp;&amp; 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>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;literal-string&quot;</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>new_mu_string<span class="Delimiter">(</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="Delimiter">));</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> + if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</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> <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>new_mu_string<span class="Delimiter">(</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="Delimiter">));</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> long long int new_mu_string<span class="Delimiter">(</span>const string&amp; contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -368,14 +387,14 @@ long long int new_mu_string<span class="Delimiter">(</span>const string&amp; con ensure_space<span class="Delimiter">(</span>string_length+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// don't forget the extra location for array size</span> <span class="Comment">// initialize string</span> long long int result = Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc++] = string_length<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc++<span class="Delimiter">,</span> string_length<span class="Delimiter">);</span> long long int curr = <span class="Constant">0</span><span class="Delimiter">;</span> const char* raw_contents = contents<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; string_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> uint32_t curr_character<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr &lt; SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> tb_utf8_char_to_unicode<span class="Delimiter">(</span>&amp;curr_character<span class="Delimiter">,</span> &amp;raw_contents[curr]<span class="Delimiter">);</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc] = curr_character<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">,</span> curr_character<span class="Delimiter">);</span> curr += tb_utf8_char_length<span class="Delimiter">(</span>raw_contents[curr]<span class="Delimiter">);</span> ++Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -383,6 +402,17 @@ long long int new_mu_string<span class="Delimiter">(</span>const string&amp; con <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Comment">//: pass in commandline args as ingredients to main</span> +<span class="Comment">//: todo: test this</span> + +<span class="Delimiter">:(after &quot;Update main_routine&quot;)</span> +Current_routine = main_routine<span class="Delimiter">;</span> +for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; argc<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector&lt;double&gt; arg<span class="Delimiter">;</span> + arg<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_mu_string<span class="Delimiter">(</span>argv[i]<span class="Delimiter">));</span> + current_call<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + <span class="Comment">//: stash recognizes strings</span> <span class="Delimiter">:(scenario stash_string)</span> @@ -398,6 +428,13 @@ if <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>r <span class="Identifier">return</span> read_mu_string<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario unicode_string)</span> +recipe main [ + x:address:array:character<span class="Special"> &lt;- </span>new [♠] + stash [foo:]<span class="Delimiter">,</span> x:address:array:character +] +<span class="traceContains">+app: foo: ♠</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> @@ -423,22 +460,30 @@ long long int unicode_length<span class="Delimiter">(</span>const string&amp; s< <span class="Delimiter">}</span> bool is_mu_string<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">)</span> == <span class="Constant">3</span> - &amp;&amp; x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">&quot;address&quot;</span>] - &amp;&amp; x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">&quot;array&quot;</span>] - &amp;&amp; x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">&quot;character&quot;</span>]<span class="Delimiter">;</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>type + &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">)</span> + &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right + &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> + &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right + &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;character&quot;</span><span class="Delimiter">)</span> + &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right == <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> string read_mu_string<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - long long int size = Memory[address]<span class="Delimiter">;</span> + long long int size = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">);</span> if <span class="Delimiter">(</span>size == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span> ostringstream tmp<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int curr = address+<span class="Constant">1</span><span class="Delimiter">;</span> curr &lt;= address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// todo: unicode</span> - tmp &lt;&lt; <span class="Delimiter">(</span>char<span class="Delimiter">)(</span>int<span class="Delimiter">)</span>Memory[curr]<span class="Delimiter">;</span> + tmp &lt;&lt; to_unicode<span class="Delimiter">(</span>static_cast&lt;uint32_t&gt;<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)));</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> tmp<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> + +bool is_mu_type_literal<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? if (!r.properties.empty())</span> +<span class="CommentedCode">//? dump_property(r.properties.at(0).second, cerr);</span> + <span class="Identifier">return</span> is_literal<span class="Delimiter">(</span>r<span class="Delimiter">)</span> &amp;&amp; !r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second &amp;&amp; r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;type&quot;</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/044space.cc.html b/html/044space.cc.html index 7c46d504..0bd414cb 100644 --- a/html/044space.cc.html +++ b/html/044space.cc.html @@ -13,9 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } .SalientComment { color: #00ffff; } -.traceContains { color: #008000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -42,7 +42,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># then location 0 is really location 11, location 1 is really location 12, and so on.</span> recipe main [ <span class="Constant">10</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># pretend array; in practice we'll use new</span> - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span> + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>/<span class="Special">raw</span> <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+mem: storing 23 in location 12</span> @@ -54,14 +54,15 @@ recipe main [ <span class="Comment"># pretend array</span> <span class="Constant">1000</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># actual start of this recipe</span> - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">1000</span> - <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span> + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">1000</span>/<span class="Special">raw</span> + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>/<span class="Special">raw</span> <span class="Constant">8</span>:number/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:number ] <span class="traceContains">+mem: storing 34 in location 8</span> <span class="SalientComment">//:: first disable name conversion for 'default-space'</span> <span class="Delimiter">:(scenario convert_names_passes_default_space)</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ default-space:number<span class="Delimiter">,</span> x:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span> ] @@ -80,24 +81,19 @@ long long int default_space<span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End call Constructor&quot;)</span> default_space = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="Delimiter">:(replace &quot;reagent r = x&quot; following &quot;reagent canonize(reagent x)&quot;)</span> -reagent r = absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End canonize(x) Special-cases&quot;)</span> + absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Delimiter">:(code)</span> -reagent absolutize<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;default-space&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> +void absolutize<span class="Delimiter">(</span>reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;default-space&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: reagent not initialized: &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">return</span> x<span class="Delimiter">;</span> + raise_error &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: reagent not initialized: &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> - reagent r = x<span class="Delimiter">;</span> - r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">(</span>r<span class="Delimiter">.</span>value<span class="Delimiter">,</span> space_base<span class="Delimiter">(</span>r<span class="Delimiter">)));</span> - r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> - assert<span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>r<span class="Delimiter">));</span> - <span class="Identifier">return</span> r<span class="Delimiter">;</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">,</span> space_base<span class="Delimiter">(</span>x<span class="Delimiter">)));</span> + x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">));</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(before &quot;return result&quot; following &quot;reagent lookup_memory(reagent x)&quot;)</span> -result<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> <span class="SalientComment">//:: fix 'get'</span> @@ -109,14 +105,14 @@ recipe main [ <span class="Comment"># pretend array</span> <span class="Constant">1000</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># actual start of this recipe</span> - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">1000</span> - <span class="Constant">1</span>:address:point<span class="Special"> &lt;- </span>copy <span class="Constant">12</span> + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">1000</span>/<span class="Special">raw</span> + <span class="Constant">1</span>:address:point<span class="Special"> &lt;- </span>copy <span class="Constant">12</span>/<span class="Special">raw</span> <span class="Constant">9</span>:number/<span class="Special">raw &lt;- </span>get *<span class="Constant">1</span>:address:point<span class="Delimiter">,</span> <span class="Constant">1</span>:offset ] <span class="traceContains">+mem: storing 35 in location 9</span> <span class="Delimiter">:(after &quot;reagent tmp&quot; following &quot;case GET:&quot;)</span> -tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> +tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> <span class="SalientComment">//:: fix 'index'</span> @@ -129,14 +125,14 @@ recipe main [ <span class="Comment"># pretend array</span> <span class="Constant">1000</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># actual start of this recipe</span> - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">1000</span> - <span class="Constant">1</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">12</span> + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">1000</span>/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">12</span>/<span class="Special">raw</span> <span class="Constant">9</span>:number/<span class="Special">raw &lt;- </span>index *<span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">1</span> ] <span class="traceContains">+mem: storing 35 in location 9</span> <span class="Delimiter">:(after &quot;reagent tmp&quot; following &quot;case INDEX:&quot;)</span> -tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> +tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> <span class="SalientComment">//:: convenience operation to automatically deduce the amount of space to</span> <span class="SalientComment">//:: allocate in a default space with names</span> @@ -156,7 +152,7 @@ if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <spa <span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span> if <span class="Delimiter">(</span>s == <span class="Constant">&quot;number-of-locals&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span> +<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr, recipe result)&quot;)</span> <span class="Comment">// rewrite `new-default-space` to</span> <span class="Comment">// `default-space:address:array:location &lt;- new location:type, number-of-locals:literal`</span> <span class="Comment">// where N is Name[recipe][&quot;&quot;]</span> @@ -166,14 +162,14 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == < <span class="Delimiter">:(after &quot;vector&lt;double&gt; read_memory(reagent x)&quot;)</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;number-of-locals&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> vector&lt;double&gt; result<span class="Delimiter">;</span> - result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Name[Recipe_ordinal[current_recipe_name<span class="Delimiter">()</span>]][<span class="Constant">&quot;&quot;</span>]<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Name[get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> current_recipe_name<span class="Delimiter">())</span>][<span class="Constant">&quot;&quot;</span>]<span class="Delimiter">);</span> if <span class="Delimiter">(</span>result<span class="Delimiter">.</span>back<span class="Delimiter">()</span> == <span class="Constant">0</span><span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;no space allocated for default-space in recipe &quot;</span> &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;; are you using names</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;no space allocated for default-space in recipe &quot;</span> &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;; are you using names?</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(after &quot;void write_memory(reagent x, vector&lt;double&gt; data)&quot;)</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;number-of-locals&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: can't write to special name 'number-of-locals'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;can't write to special name 'number-of-locals'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -201,7 +197,7 @@ try_reclaim_locals<span class="Delimiter">();</span> <span class="Comment">//: now 'local-scope' is identical to 'new-default-space' except that we'll</span> <span class="Comment">//: reclaim the default-space when the routine exits</span> -<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span> +<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr, recipe result)&quot;)</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;local-scope&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> rewrite_default_space_instruction<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -209,22 +205,22 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == < <span class="Delimiter">:(code)</span> void try_reclaim_locals<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Comment">// only reclaim routines starting with 'local-scope'</span> - const recipe_ordinal r = Recipe_ordinal[current_recipe_name<span class="Delimiter">()</span>]<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - const instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name != <span class="Constant">&quot;local-scope&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - abandon<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">,</span> + const recipe_ordinal r = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> current_recipe_name<span class="Delimiter">());</span> + if <span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name != <span class="Constant">&quot;local-scope&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + abandon<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>default_space<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">array length</span><span class="Comment">*/</span><span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">number-of-locals</span><span class="Comment">*/</span>Name[r][<span class="Constant">&quot;&quot;</span>]<span class="Delimiter">);</span> <span class="Delimiter">}</span> void rewrite_default_space_instruction<span class="Delimiter">(</span>instruction&amp; curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;new&quot;</span>]<span class="Delimiter">;</span> if <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;new-default-space can't take any ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; curr<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; can't take any ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;new&quot;</span><span class="Delimiter">;</span> curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;location:type&quot;</span><span class="Delimiter">));</span> curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;number-of-locals:literal&quot;</span><span class="Delimiter">));</span> if <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;new-default-space can't take any results</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;new-default-space can't take any results</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<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">&quot;default-space:address:array:location&quot;</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> @@ -232,37 +228,46 @@ void rewrite_default_space_instruction<span class="Delimiter">(</span>instructio <span class="Delimiter">:(code)</span> long long int space_base<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">;</span> + <span class="Comment">// temporary stub; will be replaced in a later layer</span> + <span class="Identifier">return</span> current_call<span class="Delimiter">().</span>default_space<span class="Delimiter">;</span> <span class="Delimiter">}</span> long long int address<span class="Delimiter">(</span>long long int offset<span class="Delimiter">,</span> long long int base<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>base == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> offset<span class="Delimiter">;</span> <span class="Comment">// raw</span> - if <span class="Delimiter">(</span>offset &gt;= static_cast&lt;long long int&gt;<span class="Delimiter">(</span>Memory[base]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>offset &gt;= static_cast&lt;long long int&gt;<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base<span class="Delimiter">)))</span> <span class="Delimiter">{</span> <span class="Comment">// todo: test</span> - raise &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; offset &lt;&lt; <span class="Constant">&quot; is out of bounds &quot;</span> &lt;&lt; Memory[base] &lt;&lt; <span class="Constant">&quot; at &quot;</span> &lt;&lt; base &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; offset &lt;&lt; <span class="Constant">&quot; is out of bounds &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot; at &quot;</span> &lt;&lt; base &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> base+<span class="Constant">1</span> + offset<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(after &quot;void write_memory(reagent x, vector&lt;double&gt; data)&quot;)</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;default-space&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>data<span class="Delimiter">))</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'default-space' should be of type address:array:location, but tried to write &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space = data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>data<span class="Delimiter">)</span> + || !x<span class="Delimiter">.</span>type + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">)</span> + || !x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> + || !x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;location&quot;</span><span class="Delimiter">)</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'default-space' should be of type address:array:location, but tried to write &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + current_call<span class="Delimiter">().</span>default_space = data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario get_default_space)</span> recipe main [ - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span> - <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>copy default-space:address:array:location + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:location/<span class="Special">raw &lt;- </span>copy default-space:address:array:location ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="Delimiter">:(after &quot;vector&lt;double&gt; read_memory(reagent x)&quot;)</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;default-space&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> vector&lt;double&gt; result<span class="Delimiter">;</span> - result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> diff --git a/html/045space_surround.cc.html b/html/045space_surround.cc.html index 6ceb3696..da74d215 100644 --- a/html/045space_surround.cc.html +++ b/html/045space_surround.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -42,11 +42,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } recipe main [ <span class="Constant">10</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># pretend array</span> <span class="Constant">20</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># pretend array</span> - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span> - <span class="Constant">0</span>:address:array:location/names:dummy<span class="Special"> &lt;- </span>copy <span class="Constant">20</span> <span class="Comment"># later layers will explain the /names: property</span> + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>/<span class="Special">raw</span> + <span class="Constant">0</span>:address:array:location/names:dummy<span class="Special"> &lt;- </span>copy <span class="Constant">20</span>/<span class="Special">raw</span> <span class="Comment"># later layers will explain the /names: property</span> <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">32</span> <span class="Constant">1</span>:number/space:<span class="Constant">1</span><span class="Special"> &lt;- </span>copy <span class="Constant">33</span> ] +recipe dummy [ +] <span class="Comment"># chain space</span> <span class="traceContains">+mem: storing 20 in location 11</span> <span class="Comment"># store to default-space</span> @@ -60,23 +62,23 @@ recipe main [ <span class="Delimiter">:(replace{} &quot;long long int space_base(const reagent&amp; x)&quot;)</span> long long int space_base<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> space_base<span class="Delimiter">(</span>x<span class="Delimiter">,</span> space_index<span class="Delimiter">(</span>x<span class="Delimiter">),</span> Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> + <span class="Identifier">return</span> space_base<span class="Delimiter">(</span>x<span class="Delimiter">,</span> space_index<span class="Delimiter">(</span>x<span class="Delimiter">),</span> current_call<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Delimiter">}</span> long long int space_base<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">,</span> long long int space_index<span class="Delimiter">,</span> long long int base<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>space_index == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> base<span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int result = space_base<span class="Delimiter">(</span>x<span class="Delimiter">,</span> space_index-<span class="Constant">1</span><span class="Delimiter">,</span> Memory[base+<span class="Constant">1</span>]<span class="Delimiter">);</span> + long long int result = space_base<span class="Delimiter">(</span>x<span class="Delimiter">,</span> space_index-<span class="Constant">1</span><span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base+<span class="Constant">1</span><span class="Delimiter">));</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> long long int space_index<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Comment">/*</span><span class="Comment">skip name:type</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first == <span class="Constant">&quot;space&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: /space metadata should take exactly one value in &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">return</span> to_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second || x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;/space metadata should take exactly one value in &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> to_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> diff --git a/html/046closure_name.cc.html b/html/046closure_name.cc.html index 4587a5aa..13c7ddd2 100644 --- a/html/046closure_name.cc.html +++ b/html/046closure_name.cc.html @@ -13,13 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } +.Identifier { color: #804000; } .cSpecial { color: #008000; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.Identifier { color: #804000; } -.traceContains { color: #008000; } +.CommentedCode { color: #6c6c6c; } --> </style> @@ -59,47 +60,58 @@ recipe increment-counter [ reply y:number/space:<span class="Constant">1</span> ] -<span class="traceContains">+name: recipe increment-counter is surrounded by new-counter</span> +<span class="traceContains">+name: lexically surrounding space for recipe increment-counter comes from new-counter</span> <span class="traceContains">+mem: storing 5 in location 3</span> <span class="Comment">//: To make this work, compute the recipe that provides names for the</span> -<span class="Comment">//: surrounding space of each recipe. This must happen before transform_names.</span> +<span class="Comment">//: surrounding space of each recipe.</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> map&lt;recipe_ordinal<span class="Delimiter">,</span> recipe_ordinal&gt; Surrounding_space<span class="Delimiter">;</span> -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>collect_surrounding_spaces<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;Transform.push_back(transform_names)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>collect_surrounding_spaces<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(code)</span> void collect_surrounding_spaces<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction&amp; inst = Recipe[r]<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">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- collect surrounding spaces for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- collect surrounding spaces for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>name != <span class="Constant">&quot;0&quot;</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>types<span class="Delimiter">)</span> != <span class="Constant">3</span> - || inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != Type_ordinal[<span class="Constant">&quot;address&quot;</span>] - || inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)</span> != Type_ordinal[<span class="Constant">&quot;array&quot;</span>] - || inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)</span> != Type_ordinal[<span class="Constant">&quot;location&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;slot 0 should always have type address:array:location, but is &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + type_tree* type = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!type + || type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">)</span> + || !type<span class="Delimiter">-&gt;</span>right + || type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> + || !type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right + || type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;location&quot;</span><span class="Delimiter">)</span> + || type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;slot 0 should always have type address:array:location, but is &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string_tree* s = property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> <span class="Constant">&quot;names&quot;</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;slot 0 requires a /names property in recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - vector&lt;string&gt; s = property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> <span class="Constant">&quot;names&quot;</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>s<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;slot 0 requires a /names property in recipe &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>s<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> raise_error &lt;&lt; <span class="Constant">&quot;slot 0 should have a single value in /names, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + const string&amp; surrounding_recipe_name = s<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Surrounding_space<span class="Delimiter">,</span> r<span class="Delimiter">)</span> + &amp;&amp; Surrounding_space[r] != get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> surrounding_recipe_name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; can have only one 'surrounding' recipe but has &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Surrounding_space[r]<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; and &quot;</span> &lt;&lt; surrounding_recipe_name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>s<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> raise &lt;&lt; <span class="Constant">&quot;slot 0 should have a single value in /names, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - string surrounding_recipe_name = s<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>Surrounding_space<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">)</span> != Surrounding_space<span class="Delimiter">.</span>end<span class="Delimiter">()</span> - &amp;&amp; Surrounding_space[r] != Recipe_ordinal[surrounding_recipe_name]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;recipe &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; can have only one 'surrounding' recipe but has &quot;</span> &lt;&lt; Recipe[Surrounding_space[r]]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; and &quot;</span> &lt;&lt; surrounding_recipe_name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;lexically surrounding space for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; comes from &quot;</span> &lt;&lt; surrounding_recipe_name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;lexically surrounding space for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; &quot; comes from &quot; &lt;&lt; surrounding_recipe_name &lt;&lt; '\n';</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> surrounding_recipe_name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;can't find recipe providing surrounding space for &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; surrounding_recipe_name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;recipe &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; is surrounded by &quot;</span> &lt;&lt; surrounding_recipe_name &lt;&lt; end<span class="Delimiter">();</span> - Surrounding_space[r] = Recipe_ordinal[surrounding_recipe_name]<span class="Delimiter">;</span> + Surrounding_space[r] = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> surrounding_recipe_name<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -110,12 +122,12 @@ void collect_surrounding_spaces<span class="Delimiter">(</span>const recipe_ordi <span class="Delimiter">:(replace{} &quot;long long int lookup_name(const reagent&amp; r, const recipe_ordinal default_recipe)&quot;)</span> long long int lookup_name<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">,</span> const recipe_ordinal default_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">&quot;space&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Name[default_recipe]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise &lt;&lt; <span class="Constant">&quot;name not found: &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Name[default_recipe]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise_error &lt;&lt; <span class="Constant">&quot;name not found: &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> Name[default_recipe][x<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> <span class="Delimiter">}</span> - vector&lt;string&gt; p = property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">&quot;space&quot;</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>p<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> raise &lt;&lt; <span class="Constant">&quot;/space property should have exactly one (non-negative integer) value</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - long long int n = to_integer<span class="Delimiter">(</span>p<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + string_tree* p = property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">&quot;space&quot;</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!p || p<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> raise_error &lt;&lt; <span class="Constant">&quot;/space property should have exactly one (non-negative integer) value</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + long long int n = to_integer<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>n &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> recipe_ordinal surrounding_recipe = lookup_surrounding_recipe<span class="Delimiter">(</span>default_recipe<span class="Delimiter">,</span> n<span class="Delimiter">);</span> set&lt;recipe_ordinal&gt; done<span class="Delimiter">;</span> @@ -127,12 +139,12 @@ long long int lookup_name<span class="Delimiter">(</span>const reagent&amp; x<sp <span class="Comment">// recursively call transform_names on it.</span> long long int lookup_name<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">,</span> const recipe_ordinal r<span class="Delimiter">,</span> set&lt;recipe_ordinal&gt;&amp; done<span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt;&amp; path<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Name[r]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> Name[r][x<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>done<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">)</span> != done<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;can't compute address of &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; because &quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>done<span class="Delimiter">,</span> r<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't compute address of &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; because &quot;</span> &lt;&lt; end<span class="Delimiter">();</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>path<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; path<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i-<span class="Constant">1</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; requires computing names of &quot;</span> &lt;&lt; path<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; path<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i-<span class="Constant">1</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; requires computing names of &quot;</span> &lt;&lt; path<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> - raise &lt;&lt; path<span class="Delimiter">.</span>at<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>path<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; requires computing names of &quot;</span> &lt;&lt; r &lt;&lt; <span class="Constant">&quot;..ad infinitum</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; path<span class="Delimiter">.</span>at<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>path<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; requires computing names of &quot;</span> &lt;&lt; r &lt;&lt; <span class="Constant">&quot;..ad infinitum</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> done<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>r<span class="Delimiter">);</span> @@ -144,26 +156,26 @@ long long int lookup_name<span class="Delimiter">(</span>const reagent&amp; x<sp recipe_ordinal lookup_surrounding_recipe<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">,</span> long long int n<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>n == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> r<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Surrounding_space<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">)</span> == Surrounding_space<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;don't know surrounding recipe of &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Surrounding_space<span class="Delimiter">,</span> r<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;don't know surrounding recipe of &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> assert<span class="Delimiter">(</span>Surrounding_space[r]<span class="Delimiter">);</span> <span class="Identifier">return</span> lookup_surrounding_recipe<span class="Delimiter">(</span>Surrounding_space[r]<span class="Delimiter">,</span> n-<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> -<span class="Comment">//: weaken use-before-set warnings just a tad</span> +<span class="Comment">//: weaken use-before-set detection just a tad</span> <span class="Delimiter">:(replace{} &quot;bool already_transformed(const reagent&amp; r, const map&lt;string, long long int&gt;&amp; names)&quot;)</span> bool already_transformed<span class="Delimiter">(</span>const reagent&amp; r<span class="Delimiter">,</span> const map&lt;string<span class="Delimiter">,</span> long long int&gt;&amp; names<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">&quot;space&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - vector&lt;string&gt; p = property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">&quot;space&quot;</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>p<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;/space property should have exactly one (non-negative integer) value in &quot;</span> &lt;&lt; r<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + string_tree* p = property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">&quot;space&quot;</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!p || p<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;/space property should have exactly one (non-negative integer) value in &quot;</span> &lt;&lt; r<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>p<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != <span class="Constant">&quot;0&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>value != <span class="Constant">&quot;0&quot;</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="Identifier">return</span> names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != names<span class="Delimiter">.</span>end<span class="Delimiter">();</span> + <span class="Identifier">return</span> contains_key<span class="Delimiter">(</span>names<span class="Delimiter">,</span> r<span class="Delimiter">.</span>name<span class="Delimiter">);</span> <span class="Delimiter">}</span> </pre> </body> diff --git a/html/047global.cc.html b/html/047global.cc.html index c90a4500..da8d790f 100644 --- a/html/047global.cc.html +++ b/html/047global.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -42,8 +42,8 @@ recipe main [ <span class="Constant">10</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Constant">20</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> <span class="Comment"># actual start of this recipe</span> - global-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">20</span> - default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span> + global-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">20</span>/<span class="Special">raw</span> + default-space:address:array:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>/<span class="Special">raw</span> <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> <span class="Constant">1</span>:number/space:global<span class="Special"> &lt;- </span>copy <span class="Constant">24</span> ] @@ -64,10 +64,18 @@ long long int global_space<span class="Delimiter">;</span> global_space = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">:(after &quot;void write_memory(reagent x, vector&lt;double&gt; data)&quot;)</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;global-space&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>data<span class="Delimiter">))</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'global-space' should be of type address:array:location, but tried to write &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>data<span class="Delimiter">)</span> + || !x<span class="Delimiter">.</span>type + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;address&quot;</span><span class="Delimiter">)</span> + || !x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> + || !x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;location&quot;</span><span class="Delimiter">)</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'global-space' should be of type address:array:location, but tried to write &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>global_space<span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;routine already has a global-space; you can't over-write your globals&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;routine already has a global-space; you can't over-write your globals&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> Current_routine<span class="Delimiter">-&gt;</span>global_space = data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -76,7 +84,7 @@ global_space = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">:(after &quot;long long int space_base(const reagent&amp; x)&quot;)</span> if <span class="Delimiter">(</span>is_global<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>global_space<span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;routine has no global space</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;routine has no global space</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span> Current_routine<span class="Delimiter">-&gt;</span>global_space<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -84,14 +92,14 @@ global_space = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">//: don't want to make them too comfortable to use.</span> <span class="Delimiter">:(scenario global_space_with_names)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ global-space:address:array:location<span class="Special"> &lt;- </span>new location:type<span class="Delimiter">,</span> <span class="Constant">10</span> x:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span> <span class="Constant">1</span>:number/space:global<span class="Special"> &lt;- </span>copy <span class="Constant">24</span> ] -<span class="Comment"># don't warn that we're mixing numeric addresses and names</span> -$warn: <span class="Constant">0</span> +<span class="Comment"># don't complain about mixing numeric addresses and names</span> +$error: <span class="Constant">0</span> <span class="Delimiter">:(after &quot;bool is_numeric_location(const reagent&amp; x)&quot;)</span> if <span class="Delimiter">(</span>is_global<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> @@ -102,7 +110,7 @@ $warn: <span class="Constant">0</span> bool is_global<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Comment">/*</span><span class="Comment">skip name:type</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first == <span class="Constant">&quot;space&quot;</span><span class="Delimiter">)</span> - <span class="Identifier">return</span> !x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;global&quot;</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second &amp;&amp; x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;global&quot;</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> diff --git a/html/048check_type_by_name.cc.html b/html/048check_type_by_name.cc.html new file mode 100644 index 00000000..d091ba31 --- /dev/null +++ b/html/048check_type_by_name.cc.html @@ -0,0 +1,137 @@ +<!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 - 048check_type_by_name.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Identifier { color: #804000; } +.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.CommentedCode { color: #6c6c6c; } +.Todo { color: #000000; background-color: #ffff00; padding-bottom: 1px; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Some simple sanity checks for types, and also attempts to guess them where</span> +<span class="Comment">//: they aren't provided.</span> +<span class="Comment">//:</span> +<span class="Comment">//: You still have to provide the full type the first time you mention a</span> +<span class="Comment">//: variable in a recipe. You have to explicitly name :offset and :variant</span> +<span class="Comment">//: every single time. You can't use the same name with multiple types in a</span> +<span class="Comment">//: single recipe.</span> + +<span class="Delimiter">:(scenario transform_fails_on_reusing_name_with_different_type)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + x:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> +] +<span class="traceContains">+error: main: x used with multiple types</span> + +<span class="Delimiter">:(before &quot;Transform.push_back(check_or_set_invalid_types)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_types_by_name<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void check_types_by_name<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- deduce types for recipe &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- deduce types for recipe &quot; &lt;&lt; get(Recipe, r).name &lt;&lt; '\n';</span> + map&lt;string<span class="Delimiter">,</span> type_tree*&gt; type<span class="Delimiter">;</span> + map&lt;string<span class="Delimiter">,</span> string_tree*&gt; type_name<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int in = <span class="Constant">0</span><span class="Delimiter">;</span> in &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + deduce_missing_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> 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> + check_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> 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> r<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int out = <span class="Constant">0</span><span class="Delimiter">;</span> out &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++out<span class="Delimiter">)</span> <span class="Delimiter">{</span> + deduce_missing_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> 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> + check_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> 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> r<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void deduce_missing_type<span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> type_tree*&gt;&amp; type<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> string_tree*&gt;&amp; type_name<span class="Delimiter">,</span> reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <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> + x<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span>*type[x<span class="Delimiter">.</span>name]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; &lt;= &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>!x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second = new string_tree<span class="Delimiter">(</span>*type_name[x<span class="Delimiter">.</span>name]<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void check_type<span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> type_tree*&gt;&amp; type<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> string_tree*&gt;&amp; type_name<span class="Delimiter">,</span> const reagent&amp; x<span class="Delimiter">,</span> const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// </span><span class="Todo">TODO</span><span class="Comment">: delete this</span> + <span class="Comment">// if you use raw locations you're probably doing something unsafe</span> + if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// will throw a more precise error elsewhere</span> + if <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="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + type[x<span class="Delimiter">.</span>name] = x<span class="Delimiter">.</span>type<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + type_name[x<span class="Delimiter">.</span>name] = x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>type[x<span class="Delimiter">.</span>name]<span class="Delimiter">,</span> x<span class="Delimiter">.</span>type<span class="Delimiter">))</span> + raise_error &lt;&lt; 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> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; used with multiple types</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario transform_fills_in_missing_types)</span> +recipe main [ + x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + y:number<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> +] + +<span class="Delimiter">:(scenario transform_fills_in_missing_types_in_product)</span> +recipe main [ + x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + x<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> +] + +<span class="Delimiter">:(scenario transform_fills_in_missing_types_in_product_and_ingredient)</span> +recipe main [ + x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + x<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+mem: storing 2 in location 1</span> + +<span class="Delimiter">:(scenario transform_fails_on_missing_types_in_first_mention)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + x<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + x:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> +] +<span class="traceContains">+error: main: missing type for x in 'x &lt;- copy 1'</span> + +<span class="Delimiter">:(scenario typo_in_address_type_fails)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + y:address:charcter<span class="Special"> &lt;- </span>new character:type + *y<span class="Special"> &lt;- </span>copy <span class="Constant">67</span> +] +<span class="traceContains">+error: main: unknown type in 'y:address:charcter &lt;- new character:type'</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/048typecheck.cc.html b/html/048typecheck.cc.html deleted file mode 100644 index f39bc4bf..00000000 --- a/html/048typecheck.cc.html +++ /dev/null @@ -1,128 +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 - 048typecheck.cc</title> -<meta name="Generator" content="Vim/7.4"> -<meta name="plugin-version" content="vim7.4_v1"> -<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-family: monospace; color: #eeeeee; background-color: #080808; } -* { font-size: 1.05em; } -.cSpecial { color: #008000; } -.Constant { color: #00a0a0; } -.Comment { color: #9090ff; } -.Delimiter { color: #a04060; } -.Special { color: #ff6060; } -.Identifier { color: #804000; } -.traceContains { color: #008000; } ---> -</style> - -<script type='text/javascript'> -<!-- - ---> -</script> -</head> -<body> -<pre id='vimCodeElement'> -<span class="Comment">//: Some simple sanity checks for types, and also attempts to guess them where</span> -<span class="Comment">//: they aren't provided.</span> -<span class="Comment">//:</span> -<span class="Comment">//: You still have to provide the full type the first time you mention a</span> -<span class="Comment">//: variable in a recipe. You have to explicitly name :offset and :variant</span> -<span class="Comment">//: every single time. You can't use the same name with multiple types in a</span> -<span class="Comment">//: single recipe.</span> - -<span class="Delimiter">:(scenario transform_types_warns_on_reusing_name_with_different_type)</span> -<span class="Special">% Hide_warnings = true;</span> -recipe main [ - x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> - x:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> -] -<span class="traceContains">+warn: x used with multiple types in main</span> - -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_types<span class="Delimiter">);</span> - -<span class="Delimiter">:(code)</span> -void transform_types<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - map&lt;string<span class="Delimiter">,</span> vector&lt;type_ordinal&gt; &gt; metadata<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - for <span class="Delimiter">(</span>long long int in = <span class="Constant">0</span><span class="Delimiter">;</span> in &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++in<span class="Delimiter">)</span> <span class="Delimiter">{</span> - deduce_missing_type<span class="Delimiter">(</span>metadata<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">));</span> - check_metadata<span class="Delimiter">(</span>metadata<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="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int out = <span class="Constant">0</span><span class="Delimiter">;</span> out &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++out<span class="Delimiter">)</span> <span class="Delimiter">{</span> - deduce_missing_type<span class="Delimiter">(</span>metadata<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">));</span> - check_metadata<span class="Delimiter">(</span>metadata<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="Delimiter">}</span> - <span class="Delimiter">}</span> -<span class="Delimiter">}</span> - -void check_metadata<span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> vector&lt;type_ordinal&gt; &gt;&amp; metadata<span class="Delimiter">,</span> const reagent&amp; x<span class="Delimiter">,</span> const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Comment">// if you use raw locations you're probably doing something unsafe</span> - if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// will throw a more precise warning elsewhere</span> - if <span class="Delimiter">(</span>metadata<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == metadata<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - metadata[x<span class="Delimiter">.</span>name] = x<span class="Delimiter">.</span>types<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>metadata[x<span class="Delimiter">.</span>name] != x<span class="Delimiter">.</span>types<span class="Delimiter">)</span> - raise &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; used with multiple types in &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario transform_types_fills_in_missing_types)</span> -recipe main [ - x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> - y:number<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> -] - -<span class="Delimiter">:(code)</span> -void deduce_missing_type<span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> vector&lt;type_ordinal&gt; &gt;&amp; metadata<span class="Delimiter">,</span> reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>metadata<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == metadata<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - copy<span class="Delimiter">(</span>metadata[x<span class="Delimiter">.</span>name]<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> metadata[x<span class="Delimiter">.</span>name]<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">,</span> x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> - assert<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>metadata[x<span class="Delimiter">.</span>name]<span class="Delimiter">.</span>size<span class="Delimiter">());</span> - x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> vector&lt;string&gt; &gt;<span class="Delimiter">(</span><span class="Constant">&quot;as-before&quot;</span><span class="Delimiter">,</span> vector&lt;string&gt;<span class="Delimiter">()));</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario transform_types_fills_in_missing_types_in_product)</span> -recipe main [ - x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> - x<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> -] - -<span class="Delimiter">:(scenario transform_types_fills_in_missing_types_in_product_and_ingredient)</span> -recipe main [ - x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> - x<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> -] -<span class="traceContains">+mem: storing 2 in location 1</span> - -<span class="Delimiter">:(scenario transform_warns_on_missing_types_in_first_mention)</span> -<span class="Special">% Hide_warnings = true;</span> -recipe main [ - x<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> - x:number<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> -] -<span class="traceContains">+warn: missing type in 'x &lt;- copy 1'</span> - -<span class="Delimiter">:(scenario typo_in_address_type_warns)</span> -<span class="Special">% Hide_warnings = true;</span> -recipe main [ - y:address:charcter<span class="Special"> &lt;- </span>new character:type - *y<span class="Special"> &lt;- </span>copy <span class="Constant">67</span> -] -<span class="traceContains">+warn: unknown type: charcter</span> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html index e6184407..c586b575 100644 --- a/html/050scenario.cc.html +++ b/html/050scenario.cc.html @@ -13,10 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } -.SalientComment { color: #00ffff; } .traceContains { color: #008000; } .CommentedCode { color: #6c6c6c; } +.SalientComment { color: #00ffff; } +.cSpecial { color: #008000; } .traceAbsent { color: #c00000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -110,8 +110,8 @@ else if <span class="Delimiter">(</span>command == <span class="Constant">&quot; scenario parse_scenario<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> scenario result<span class="Delimiter">;</span> result<span class="Delimiter">.</span>name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>Scenario_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != Scenario_names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;duplicate scenario name: &quot;</span> &lt;&lt; result<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Scenario_names<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">))</span> + raise_error &lt;&lt; <span class="Constant">&quot;duplicate scenario name: &quot;</span> &lt;&lt; result<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> Scenario_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">);</span> @@ -224,7 +224,11 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> RUN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;run&quot;</span>] = RUN<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">,</span> RUN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case RUN: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case RUN: <span class="Delimiter">{</span> ostringstream tmp<span class="Delimiter">;</span> @@ -232,6 +236,11 @@ case RUN: <span class="Delimiter">{</span> vector&lt;recipe_ordinal&gt; tmp_recipe = load<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<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> + if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ++Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;trace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;run: incrementing callstack depth to &quot;</span> &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt;&lt; end<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt; <span class="Constant">9000</span><span class="Delimiter">);</span> <span class="Comment">// 9998-101 plus cushion</span> + <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-&gt;</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> @@ -256,7 +265,7 @@ recipe main [ <span class="traceContains">+mem: storing 13 in location 1</span> <span class="traceContains">+mem: storing 13 in location 2</span> -<span class="Comment">//: 'memory-should-contain' raises warnings if specific locations aren't as expected</span> +<span class="Comment">//: 'memory-should-contain' raises errors if specific locations aren't as expected</span> <span class="Comment">//: Also includes some special support for checking strings.</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> @@ -266,19 +275,23 @@ Scenario_testing_scenario = <span class="Constant">false</span><span class="Deli <span class="Delimiter">:(scenario memory_check)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ memory-should-contain [ <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">13</span> ] ] <span class="traceContains">+run: checking location 1</span> -<span class="traceContains">+warn: expected location 1 to contain 13 but saw 0</span> +<span class="traceContains">+error: expected location 1 to contain 13 but saw 0</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MEMORY_SHOULD_CONTAIN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;memory-should-contain&quot;</span>] = MEMORY_SHOULD_CONTAIN<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;memory-should-contain&quot;</span><span class="Delimiter">,</span> MEMORY_SHOULD_CONTAIN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MEMORY_SHOULD_CONTAIN: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MEMORY_SHOULD_CONTAIN: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -299,22 +312,22 @@ void check_memory<span class="Delimiter">(</span>const string&amp; s<span class= check_type<span class="Delimiter">(</span>lhs<span class="Delimiter">,</span> in<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - int address = to_integer<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + long long int address = to_integer<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string _assign<span class="Delimiter">;</span> in &gt;&gt; _assign<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>_assign == <span class="Constant">&quot;&lt;-&quot;</span><span class="Delimiter">);</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - int value = <span class="Constant">0</span><span class="Delimiter">;</span> in &gt;&gt; value<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>locations_checked<span class="Delimiter">.</span>find<span class="Delimiter">(</span>address<span class="Delimiter">)</span> != locations_checked<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;duplicate expectation for location &quot;</span> &lt;&lt; address &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking location &quot;</span> &lt;&lt; address &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Memory[address] != value<span class="Delimiter">)</span> <span class="Delimiter">{</span> + double value = <span class="Constant">0</span><span class="Delimiter">;</span> in &gt;&gt; value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>locations_checked<span class="Delimiter">,</span> address<span class="Delimiter">))</span> + raise_error &lt;&lt; <span class="Constant">&quot;duplicate expectation for location &quot;</span> &lt;&lt; address &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking location &quot;</span> &lt;&lt; address &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">)</span> != value<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// genuine test in a mu file</span> - raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; value &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; Memory[address] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>value<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// just testing scenario support</span> - raise &lt;&lt; <span class="Constant">&quot;expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; value &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; Memory[address] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>value<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -328,7 +341,7 @@ void check_memory<span class="Delimiter">(</span>const string&amp; s<span class= void check_type<span class="Delimiter">(</span>const string&amp; lhs<span class="Delimiter">,</span> istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> reagent x<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;string&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;string&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>to_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">));</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string _assign = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> @@ -342,16 +355,16 @@ void check_type<span class="Delimiter">(</span>const string&amp; lhs<span class= check_string<span class="Delimiter">(</span>address<span class="Delimiter">,</span> literal<span class="Delimiter">);</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - raise &lt;&lt; <span class="Constant">&quot;don't know how to check memory for &quot;</span> &lt;&lt; lhs &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;don't know how to check memory for &quot;</span> &lt;&lt; lhs &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> void check_string<span class="Delimiter">(</span>long long int address<span class="Delimiter">,</span> const string&amp; literal<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking string length at &quot;</span> &lt;&lt; address &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Memory[address] != SIZE<span class="Delimiter">(</span>literal<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">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking string length at &quot;</span> &lt;&lt; address &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">))</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; Memory[address] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> else - raise &lt;&lt; <span class="Constant">&quot;expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; Memory[address] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;expected location &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> ++Num_failures<span class="Delimiter">;</span> @@ -360,15 +373,15 @@ void check_string<span class="Delimiter">(</span>long long int address<span clas <span class="Delimiter">}</span> ++address<span class="Delimiter">;</span> <span class="Comment">// now skip length</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking location &quot;</span> &lt;&lt; address+i &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Memory[address+i] != literal<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">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking location &quot;</span> &lt;&lt; address+i &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+i<span class="Delimiter">)</span> != literal<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// genuine test in a mu file</span> - raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location &quot;</span> &lt;&lt; <span class="Delimiter">(</span>address+i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; literal<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; Memory[address+i] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location &quot;</span> &lt;&lt; <span class="Delimiter">(</span>address+i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; literal<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+i<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// just testing scenario support</span> - raise &lt;&lt; <span class="Constant">&quot;expected location &quot;</span> &lt;&lt; <span class="Delimiter">(</span>address+i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; literal<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; Memory[address+i] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;expected location &quot;</span> &lt;&lt; <span class="Delimiter">(</span>address+i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to contain &quot;</span> &lt;&lt; literal<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+i<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -381,18 +394,18 @@ void check_string<span class="Delimiter">(</span>long long int address<span clas <span class="Delimiter">:(scenario memory_check_multiple)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ memory-should-contain [ <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">0</span> ] ] -<span class="traceContains">+warn: duplicate expectation for location 1</span> +<span class="traceContains">+error: duplicate expectation for location 1</span> <span class="Delimiter">:(scenario memory_check_string_length)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">97</span> <span class="Comment"># 'a'</span> @@ -402,7 +415,7 @@ recipe main [ <span class="Constant">1</span>:string<span class="Special"> &lt;- </span>[ab] ] ] -<span class="traceContains">+warn: expected location 1 to contain length 2 of string [ab] but saw 3</span> +<span class="traceContains">+error: expected location 1 to contain length 2 of string [ab] but saw 3</span> <span class="Delimiter">:(scenario memory_check_string)</span> recipe main [ @@ -425,21 +438,25 @@ recipe main [ <span class="Comment">// that the lines are present *and* in the specified sequence. (There can be</span> <span class="Comment">// other lines in between.)</span> -<span class="Delimiter">:(scenario trace_check_warns_on_failure)</span> +<span class="Delimiter">:(scenario trace_check_fails)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ trace-should-contain [ a: b a: d ] ] -<span class="traceContains">+warn: missing [b] in trace with label a</span> +<span class="traceContains">+error: missing [b] in trace with label a</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> TRACE_SHOULD_CONTAIN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;trace-should-contain&quot;</span>] = TRACE_SHOULD_CONTAIN<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;trace-should-contain&quot;</span><span class="Delimiter">,</span> TRACE_SHOULD_CONTAIN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case TRACE_SHOULD_CONTAIN: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case TRACE_SHOULD_CONTAIN: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -448,7 +465,7 @@ case TRACE_SHOULD_CONTAIN: <span class="Delimiter">{</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -<span class="Comment">// simplified version of check_trace_contents() that emits warnings rather</span> +<span class="Comment">// simplified version of check_trace_contents() that emits errors rather</span> <span class="Comment">// than just printing to stderr</span> bool check_trace<span class="Delimiter">(</span>const string&amp; expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> Trace_stream<span class="Delimiter">-&gt;</span>newline<span class="Delimiter">();</span> @@ -465,8 +482,8 @@ bool check_trace<span class="Delimiter">(</span>const string&amp; expected<span <span class="Delimiter">}</span> <span class="Delimiter">}</span> - raise &lt;&lt; <span class="Constant">&quot;missing [&quot;</span> &lt;&lt; expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>contents &lt;&lt; <span class="Constant">&quot;] &quot;</span> - &lt;&lt; <span class="Constant">&quot;in trace with label &quot;</span> &lt;&lt; expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;missing [&quot;</span> &lt;&lt; expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>contents &lt;&lt; <span class="Constant">&quot;] &quot;</span> + &lt;&lt; <span class="Constant">&quot;in trace with label &quot;</span> &lt;&lt; expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<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> @@ -483,9 +500,9 @@ vector&lt;trace_line&gt; parse_trace<span class="Delimiter">(</span>const string <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(scenario trace_check_warns_on_failure_in_later_line)</span> +<span class="Delimiter">:(scenario trace_check_fails_in_nonfirst_line)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ run [ trace <span class="Constant">1</span><span class="Delimiter">,</span> [a]<span class="Delimiter">,</span> [b] @@ -495,11 +512,11 @@ recipe main [ a: d ] ] -<span class="traceContains">+warn: missing [d] in trace with label a</span> +<span class="traceContains">+error: missing [d] in trace with label a</span> <span class="Delimiter">:(scenario trace_check_passes_silently)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ run [ trace <span class="Constant">1</span><span class="Delimiter">,</span> [a]<span class="Delimiter">,</span> [b] @@ -508,16 +525,16 @@ recipe main [ a: b ] ] -<span class="traceAbsent">-warn: missing [b] in trace with label a</span> -$warn: <span class="Constant">0</span> +<span class="traceAbsent">-error: missing [b] in trace with label a</span> +$error: <span class="Constant">0</span> <span class="Comment">//: 'trace-should-not-contain' is like the '-' lines in our scenarios so far</span> <span class="Comment">//: Each trace line is separately checked for absense. Order is *not*</span> <span class="Comment">//: important, so you can't say things like &quot;B should not exist after A.&quot;</span> -<span class="Delimiter">:(scenario trace_negative_check_warns_on_failure)</span> +<span class="Delimiter">:(scenario trace_negative_check_fails)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ run [ trace <span class="Constant">1</span><span class="Delimiter">,</span> [a]<span class="Delimiter">,</span> [b] @@ -526,12 +543,16 @@ recipe main [ a: b ] ] -<span class="traceContains">+warn: unexpected [b] in trace with label a</span> +<span class="traceContains">+error: unexpected [b] in trace with label a</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> TRACE_SHOULD_NOT_CONTAIN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;trace-should-not-contain&quot;</span>] = TRACE_SHOULD_NOT_CONTAIN<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;trace-should-not-contain&quot;</span><span class="Delimiter">,</span> TRACE_SHOULD_NOT_CONTAIN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case TRACE_SHOULD_NOT_CONTAIN: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case TRACE_SHOULD_NOT_CONTAIN: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -540,14 +561,14 @@ case TRACE_SHOULD_NOT_CONTAIN: <span class="Delimiter">{</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -<span class="Comment">// simplified version of check_trace_contents() that emits warnings rather</span> +<span class="Comment">// simplified version of check_trace_contents() that emits errors rather</span> <span class="Comment">// than just printing to stderr</span> bool check_trace_missing<span class="Delimiter">(</span>const string&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> Trace_stream<span class="Delimiter">-&gt;</span>newline<span class="Delimiter">();</span> vector&lt;trace_line&gt; lines = parse_trace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>lines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span>lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>label<span class="Delimiter">,</span> lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>contents<span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;unexpected [&quot;</span> &lt;&lt; lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>contents &lt;&lt; <span class="Constant">&quot;] in trace with label &quot;</span> &lt;&lt; lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;unexpected [&quot;</span> &lt;&lt; lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>contents &lt;&lt; <span class="Constant">&quot;] in trace with label &quot;</span> &lt;&lt; lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<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> @@ -557,18 +578,18 @@ bool check_trace_missing<span class="Delimiter">(</span>const string&amp; in<spa <span class="Delimiter">:(scenario trace_negative_check_passes_silently)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ trace-should-not-contain [ a: b ] ] -<span class="traceAbsent">-warn: unexpected [b] in trace with label a</span> -$warn: <span class="Constant">0</span> +<span class="traceAbsent">-error: unexpected [b] in trace with label a</span> +$error: <span class="Constant">0</span> -<span class="Delimiter">:(scenario trace_negative_check_warns_on_any_unexpected_line)</span> +<span class="Delimiter">:(scenario trace_negative_check_fails_on_any_unexpected_line)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ run [ trace <span class="Constant">1</span><span class="Delimiter">,</span> [a]<span class="Delimiter">,</span> [d] @@ -578,7 +599,7 @@ recipe main [ a: d ] ] -<span class="traceContains">+warn: unexpected [d] in trace with label a</span> +<span class="traceContains">+error: unexpected [d] in trace with label a</span> <span class="Delimiter">:(scenario trace_count_check)</span> recipe main [ @@ -591,35 +612,39 @@ recipe main [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CHECK_TRACE_COUNT_FOR_LABEL<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;check-trace-count-for-label&quot;</span>] = CHECK_TRACE_COUNT_FOR_LABEL<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;check-trace-count-for-label&quot;</span><span class="Delimiter">,</span> CHECK_TRACE_COUNT_FOR_LABEL<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case CHECK_TRACE_COUNT_FOR_LABEL: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'check-trace-for-label' requires exactly two ingredients, but got '&quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'check-trace-for-label' requires exactly two ingredients, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'check-trace-for-label' should be a number (count), but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'check-trace-for-label' should be a number (count), but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int expected_count = 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> - if <span class="Delimiter">(</span>!is_literal_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'check-trace-for-label' should be a literal string (label), but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'check-trace-for-label' should be a literal string (label), but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case CHECK_TRACE_COUNT_FOR_LABEL: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + long long int expected_count = 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> string label = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">;</span> long long int count = trace_count<span class="Delimiter">(</span>label<span class="Delimiter">);</span> if <span class="Delimiter">(</span>count != expected_count<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// genuine test in a mu file</span> - raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: expected &quot;</span> &lt;&lt; expected_count &lt;&lt; <span class="Constant">&quot; lines in trace with label &quot;</span> &lt;&lt; label &lt;&lt; <span class="Constant">&quot; in trace: &quot;</span><span class="Delimiter">;</span> + raise_error &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;expected &quot;</span> &lt;&lt; expected_count &lt;&lt; <span class="Constant">&quot; lines in trace with label &quot;</span> &lt;&lt; label &lt;&lt; <span class="Constant">&quot; in trace: &quot;</span><span class="Delimiter">;</span> DUMP<span class="Delimiter">(</span>label<span class="Delimiter">);</span> - raise<span class="Delimiter">;</span> + raise_error<span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// just testing scenario support</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: expected &quot;</span> &lt;&lt; expected_count &lt;&lt; <span class="Constant">&quot; lines in trace with label &quot;</span> &lt;&lt; label &lt;&lt; <span class="Constant">&quot; in trace</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;expected &quot;</span> &lt;&lt; expected_count &lt;&lt; <span class="Constant">&quot; lines in trace with label &quot;</span> &lt;&lt; label &lt;&lt; <span class="Constant">&quot; in trace</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -631,14 +656,14 @@ case CHECK_TRACE_COUNT_FOR_LABEL: <span class="Delimiter">{</span> <span class="Delimiter">:(scenario trace_count_check_2)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ run [ trace <span class="Constant">1</span><span class="Delimiter">,</span> [a]<span class="Delimiter">,</span> [foo] ] check-trace-count-for-label <span class="Constant">2</span><span class="Delimiter">,</span> [a] ] -<span class="traceContains">+warn: main: expected 2 lines in trace with label a in trace</span> +<span class="traceContains">+error: main: expected 2 lines in trace with label a in trace</span> <span class="Comment">//: Minor detail: ignore 'system' calls in scenarios, since anything we do</span> <span class="Comment">//: with them is by definition impossible to test through mu.</span> diff --git a/html/052tangle.cc.html b/html/052tangle.cc.html index 95fc502f..4fc37210 100644 --- a/html/052tangle.cc.html +++ b/html/052tangle.cc.html @@ -13,6 +13,7 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } @@ -20,7 +21,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .Special { color: #ff6060; } .Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -69,27 +69,29 @@ Fragments_used<span class="Delimiter">.</span>clear<span class="Delimiter">();</ <span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span> else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;before&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - recipe tmp = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + recipe tmp<span class="Delimiter">;</span> + slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> if <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> else - raise &lt;&lt; <span class="Constant">&quot;can't tangle before label &quot;</span> &lt;&lt; label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't tangle before label &quot;</span> &lt;&lt; label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;after&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - recipe tmp = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + recipe tmp<span class="Delimiter">;</span> + slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> if <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> else - raise &lt;&lt; <span class="Constant">&quot;can't tangle after label &quot;</span> &lt;&lt; label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't tangle after label &quot;</span> &lt;&lt; label &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Comment">//: after all recipes are loaded, insert fragments at appropriate labels.</span> -<span class="Delimiter">:(after &quot;int main&quot;)</span> - Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>insert_fragments<span class="Delimiter">);</span> +<span class="Delimiter">:(after &quot;Begin Transforms&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>insert_fragments<span class="Delimiter">);</span> <span class="Comment">// NOT idempotent</span> -<span class="Comment">//; We might need to perform multiple passes, in case inserted fragments</span> +<span class="Comment">//: We might need to perform multiple passes, in case inserted fragments</span> <span class="Comment">//: include more labels that need further insertions. Track which labels we've</span> <span class="Comment">//: already processed using an extra field.</span> <span class="Delimiter">:(before &quot;End instruction Fields&quot;)</span> @@ -105,8 +107,8 @@ void insert_fragments<span class="Delimiter">(</span>const recipe_ordinal r<span made_progress = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// create a new vector because insertions invalidate iterators</span> vector&lt;instruction&gt; result<span class="Delimiter">;</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>is_label || !is_waypoint<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> || inst<span class="Delimiter">.</span>tangle_done<span class="Delimiter">)</span> <span class="Delimiter">{</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> @@ -115,16 +117,16 @@ void insert_fragments<span class="Delimiter">(</span>const recipe_ordinal r<span made_progress = <span class="Constant">true</span><span class="Delimiter">;</span> Fragments_used<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">);</span> ostringstream prefix<span class="Delimiter">;</span> - prefix &lt;&lt; <span class="Constant">'+'</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; pass &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; i<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Before_fragments<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != Before_fragments<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + prefix &lt;&lt; <span class="Constant">'+'</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; pass &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; i<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Before_fragments<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> <span class="Delimiter">{</span> append_fragment<span class="Delimiter">(</span>result<span class="Delimiter">,</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">,</span> prefix<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>After_fragments<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != After_fragments<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>After_fragments<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> <span class="Delimiter">{</span> append_fragment<span class="Delimiter">(</span>result<span class="Delimiter">,</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">,</span> prefix<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>result<span class="Delimiter">);</span> ++pass<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -145,7 +147,7 @@ void append_fragment<span class="Delimiter">(</span>vector&lt;instruction&gt;&am for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>patch<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> instruction inst = patch<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>jump_targets<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != jump_targets<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>jump_targets<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> inst<span class="Delimiter">.</span>label = prefix+inst<span class="Delimiter">.</span>label<span class="Delimiter">;</span> base<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> @@ -153,7 +155,7 @@ void append_fragment<span class="Delimiter">(</span>vector&lt;instruction&gt;&am for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> reagent&amp; x = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;label&quot;</span> &amp;&amp; jump_targets<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != jump_targets<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;label&quot;</span> &amp;&amp; contains_key<span class="Delimiter">(</span>jump_targets<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> x<span class="Delimiter">.</span>name = prefix+x<span class="Delimiter">.</span>name<span class="Delimiter">;</span> <span class="Delimiter">}</span> base<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> @@ -164,22 +166,22 @@ bool is_waypoint<span class="Delimiter">(</span>string label<span class="Delimit <span class="Identifier">return</span> *label<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> == <span class="Constant">'&lt;'</span> &amp;&amp; *label<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> == <span class="Constant">'&gt;'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Comment">//: warn about unapplied fragments</span> +<span class="Comment">//: complain about unapplied fragments</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> bool Transform_check_insert_fragments_Ran = <span class="Constant">false</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span> -Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_insert_fragments<span class="Delimiter">);</span> <span class="Comment">// final transform</span> +<span class="Delimiter">:(after &quot;Transform.push_back(insert_fragments)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_insert_fragments<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(code)</span> void check_insert_fragments<span class="Delimiter">(</span>unused recipe_ordinal<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Transform_check_insert_fragments_Ran<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> Transform_check_insert_fragments_Ran = <span class="Constant">true</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> recipe&gt;::iterator p = Before_fragments<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Before_fragments<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Fragments_used<span class="Delimiter">.</span>find<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">)</span> == Fragments_used<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;could not locate insert before &quot;</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>first &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Fragments_used<span class="Delimiter">,</span> p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">))</span> + raise_error &lt;&lt; <span class="Constant">&quot;could not locate insert before &quot;</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>first &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> for <span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> recipe&gt;::iterator p = After_fragments<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != After_fragments<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Fragments_used<span class="Delimiter">.</span>find<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">)</span> == Fragments_used<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - raise &lt;&lt; <span class="Constant">&quot;could not locate insert after &quot;</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>first &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Fragments_used<span class="Delimiter">,</span> p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">))</span> + raise_error &lt;&lt; <span class="Constant">&quot;could not locate insert after &quot;</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>first &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -204,7 +206,7 @@ after &lt;label1&gt; [ $mem: <span class="Constant">4</span> <span class="Delimiter">:(scenario tangle_ignores_jump_target)</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> +label1 @@ -213,7 +215,7 @@ recipe main [ before +label1 [ <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] -<span class="traceContains">+warn: can't tangle before label +label1</span> +<span class="traceContains">+error: can't tangle before label +label1</span> <span class="traceContains">+mem: storing 0 in location 1</span> <span class="traceContains">+mem: storing 0 in location 4</span> <span class="Comment"># label1</span> diff --git a/html/053continuation.cc.html b/html/053continuation.cc.html deleted file mode 100644 index 7e3623fb..00000000 --- a/html/053continuation.cc.html +++ /dev/null @@ -1,278 +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 - 053continuation.cc</title> -<meta name="Generator" content="Vim/7.4"> -<meta name="plugin-version" content="vim7.4_v1"> -<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-family: monospace; color: #eeeeee; background-color: #080808; } -* { font-size: 1.05em; } -.cSpecial { color: #008000; } -.SalientComment { color: #00ffff; } -.traceAbsent { color: #c00000; } -.traceContains { color: #008000; } -.Constant { color: #00a0a0; } -.Comment { color: #9090ff; } -.Delimiter { color: #a04060; } -.Special { color: #ff6060; } -.Identifier { color: #804000; } ---> -</style> - -<script type='text/javascript'> -<!-- - ---> -</script> -</head> -<body> -<pre id='vimCodeElement'> -<span class="Comment">//: Continuations are a powerful primitive for constructing advanced kinds of</span> -<span class="Comment">//: control *policies* like back-tracking. They're usually provided using a</span> -<span class="Comment">//: primitive called 'call-cc': <a href="http://en.wikipedia.org/wiki/Call-with-current-continuation)">http://en.wikipedia.org/wiki/Call-with-current-continuation)</a></span> -<span class="Comment">//: But in mu 'call-cc' is constructed out of a combination of two primitives:</span> -<span class="Comment">//: 'current-continuation', which returns a continuation, and</span> -<span class="Comment">//: 'continue-from', which takes a continuation to switch to.</span> - -<span class="Comment">//: todo: implement continuations in mu's memory</span> -<span class="Delimiter">:(before &quot;End Globals&quot;)</span> -map&lt;long long int<span class="Delimiter">,</span> call_stack&gt; Continuation<span class="Delimiter">;</span> -long long int Next_continuation_id = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Setup&quot;)</span> -Continuation<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> -Next_continuation_id = <span class="Constant">0</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span> -type_ordinal continuation = Type_ordinal[<span class="Constant">&quot;continuation&quot;</span>] = Next_type_ordinal++<span class="Delimiter">;</span> -Type[continuation]<span class="Delimiter">.</span>name = <span class="Constant">&quot;continuation&quot;</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -CURRENT_CONTINUATION<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;current-continuation&quot;</span>] = CURRENT_CONTINUATION<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case CURRENT_CONTINUATION: <span class="Delimiter">{</span> - <span class="Comment">// copy the current call stack</span> - Continuation[Next_continuation_id] = Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">;</span> <span class="Comment">// deep copy because calls have no pointers</span> - <span class="Comment">// make sure calling the copy doesn't spawn the same continuation again</span> - ++Continuation[Next_continuation_id]<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_step_index<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>Next_continuation_id<span class="Delimiter">);</span> - ++Next_continuation_id<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span><span class="Constant">&quot;current-continuation&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new continuation &quot;</span> &lt;&lt; Next_continuation_id &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -CONTINUE_FROM<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;continue-from&quot;</span>] = CONTINUE_FROM<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case CONTINUE_FROM: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'continue-from' should be a continuation id generated by 'current-continuation', but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - long long int c = 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> - Current_routine<span class="Delimiter">-&gt;</span>calls = Continuation[c]<span class="Delimiter">;</span> <span class="Comment">// deep copy; calls have no pointers</span> - <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// skip rest of this instruction</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario continuation)</span> -<span class="Comment"># simulate a loop using continuations</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - <span class="Constant">2</span>:continuation<span class="Special"> &lt;- </span>current-continuation - <span class="Delimiter">{</span> - <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>greater-or-equal <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span> - <span class="Identifier">break</span>-if <span class="Constant">3</span>:boolean - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">1</span> - <span class="Identifier">continue</span>-from <span class="Constant">2</span>:continuation <span class="Comment"># loop</span> - <span class="Delimiter">}</span> -] -<span class="traceContains">+mem: storing 1 in location 1</span> -<span class="traceContains">+mem: storing 2 in location 1</span> -<span class="traceContains">+mem: storing 3 in location 1</span> -<span class="traceAbsent">-mem: storing 4 in location 1</span> -<span class="Comment"># ensure every iteration doesn't copy the stack over and over</span> -$current-continuation: <span class="Constant">1</span> - -<span class="Delimiter">:(scenario continuation_inside_caller)</span> -recipe main [ - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - <span class="Constant">2</span>:continuation<span class="Special"> &lt;- </span>loop-body - <span class="Delimiter">{</span> - <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>greater-or-equal <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span> - <span class="Identifier">break</span>-if <span class="Constant">3</span>:boolean - <span class="Identifier">continue</span>-from <span class="Constant">2</span>:continuation <span class="Comment"># loop</span> - <span class="Delimiter">}</span> -] - -recipe loop-body [ - <span class="Constant">4</span>:continuation<span class="Special"> &lt;- </span>current-continuation - <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">1</span> -] -<span class="traceContains">+mem: storing 1 in location 1</span> -<span class="traceContains">+mem: storing 2 in location 1</span> -<span class="traceContains">+mem: storing 3 in location 1</span> -<span class="traceAbsent">-mem: storing 4 in location 1</span> - -<span class="SalientComment">//:: A variant of continuations is the 'delimited' continuation that can be called like any other recipe.</span> -<span class="Comment">//:</span> -<span class="Comment">//: In mu, this is constructed out of two primitives:</span> -<span class="Comment">//:</span> -<span class="Comment">//: * 'create-delimited-continuation' lays down a mark on the call</span> -<span class="Comment">//: stack and calls the provided function (it is sometimes called 'prompt')</span> -<span class="Comment">//: * 'reply-current-continuation' copies the top of the stack until the</span> -<span class="Comment">//: mark, and returns it as the response of create-delimited-continuation</span> -<span class="Comment">//: (which might be a distant ancestor on the call stack; intervening calls</span> -<span class="Comment">//: don't return)</span> -<span class="Comment">//:</span> -<span class="Comment">//: The resulting slice of the stack can now be called just like a regular</span> -<span class="Comment">//: function.</span> - -<span class="Delimiter">:(scenario delimited_continuation)</span> -recipe main [ - <span class="Constant">1</span>:continuation<span class="Special"> &lt;- </span>create-delimited-continuation f:recipe <span class="Constant">12</span> <span class="Comment"># 12 is an argument to f</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">5</span> - <span class="Delimiter">{</span> - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>call <span class="Constant">1</span>:continuation<span class="Delimiter">,</span> <span class="Constant">2</span>:number <span class="Comment"># 2 is an argument to g, the 'top' of the continuation</span> - <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>greater-or-equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">8</span> - <span class="Identifier">break</span>-if <span class="Constant">3</span>:boolean - loop - <span class="Delimiter">}</span> -] - -recipe f [ - <span class="Constant">11</span>:number<span class="Special"> &lt;- </span>next-ingredient - <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>g <span class="Constant">11</span>:number - reply <span class="Constant">12</span>:number -] - -recipe g [ - <span class="Constant">21</span>:number<span class="Special"> &lt;- </span>next-ingredient - rewind-ingredients - reply-delimited-continuation - <span class="Comment"># calls of the continuation start from here</span> - <span class="Constant">22</span>:number<span class="Special"> &lt;- </span>next-ingredient - <span class="Constant">23</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">22</span>:number<span class="Delimiter">,</span> <span class="Constant">1</span> - reply <span class="Constant">23</span>:number -] -<span class="Comment"># first call of 'g' executes the part before reply-delimited-continuation</span> -<span class="traceContains">+mem: storing 12 in location 21</span> -<span class="traceContains">+run: 2:number &lt;- copy 5</span> -<span class="traceContains">+mem: storing 5 in location 2</span> -<span class="Comment"># calls of the continuation execute the part after reply-delimited-continuation</span> -<span class="traceContains">+run: 2:number &lt;- call 1:continuation, 2:number</span> -<span class="traceContains">+mem: storing 5 in location 22</span> -<span class="traceContains">+mem: storing 6 in location 2</span> -<span class="traceContains">+run: 2:number &lt;- call 1:continuation, 2:number</span> -<span class="traceContains">+mem: storing 6 in location 22</span> -<span class="traceContains">+mem: storing 7 in location 2</span> -<span class="traceContains">+run: 2:number &lt;- call 1:continuation, 2:number</span> -<span class="traceContains">+mem: storing 7 in location 22</span> -<span class="traceContains">+mem: storing 8 in location 2</span> -<span class="Comment"># first call of 'g' does not execute the part after reply-delimited-continuation</span> -<span class="traceAbsent">-mem: storing 12 in location 22</span> -<span class="Comment"># calls of the continuation don't execute the part before reply-delimited-continuation</span> -<span class="traceAbsent">-mem: storing 5 in location 21</span> -<span class="traceAbsent">-mem: storing 6 in location 21</span> -<span class="traceAbsent">-mem: storing 7 in location 21</span> -<span class="Comment"># termination</span> -<span class="traceAbsent">-mem: storing 9 in location 2</span> - -<span class="Comment">//: 'create-delimited-continuation' is like 'call' except it adds a 'reset' mark to</span> -<span class="Comment">//: the call stack</span> - -<span class="Delimiter">:(before &quot;End call Fields&quot;)</span> -bool is_reset<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End call Constructor&quot;)</span> -is_reset = <span class="Constant">false</span><span class="Delimiter">;</span> - -<span class="Comment">//: like call, but mark the current call as a 'reset' call before pushing the next one on it</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -CREATE_DELIMITED_CONTINUATION<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;create-delimited-continuation&quot;</span>] = CREATE_DELIMITED_CONTINUATION<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case CREATE_DELIMITED_CONTINUATION: <span class="Delimiter">{</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>is_reset = <span class="Constant">true</span><span class="Delimiter">;</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>Recipe_ordinal[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="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> - <span class="Identifier">goto</span> call_housekeeping<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: save the slice of current call stack until the 'create-delimited-continuation'</span> -<span class="Comment">//: call, and return it as the result.</span> -<span class="Comment">//: todo: implement delimited continuations in mu's memory</span> -<span class="Delimiter">:(before &quot;End Globals&quot;)</span> -map&lt;long long int<span class="Delimiter">,</span> call_stack&gt; Delimited_continuation<span class="Delimiter">;</span> -long long int Next_delimited_continuation_id = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Setup&quot;)</span> -Delimited_continuation<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> -Next_delimited_continuation_id = <span class="Constant">0</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -REPLY_DELIMITED_CONTINUATION<span class="Delimiter">,</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;reply-delimited-continuation&quot;</span>] = REPLY_DELIMITED_CONTINUATION<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case REPLY_DELIMITED_CONTINUATION: <span class="Delimiter">{</span> - <span class="Comment">// first clear any existing ingredients, to isolate the creation of the</span> - <span class="Comment">// continuation from its calls</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>next_ingredient_to_process = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Comment">// copy the current call stack until the most recent 'reset' call</span> - call_stack::iterator find_reset<span class="Delimiter">(</span>call_stack&amp; c<span class="Delimiter">);</span> <span class="Comment">// manual prototype containing '::'</span> - call_stack::iterator reset = find_reset<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>reset == Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: couldn't find a 'reset' call to jump out to</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - Delimited_continuation[Next_delimited_continuation_id] = call_stack<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> reset<span class="Delimiter">);</span> - while <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> != reset<span class="Delimiter">)</span> <span class="Delimiter">{</span> - --Callstack_depth<span class="Delimiter">;</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>pop_front<span class="Delimiter">();</span> - <span class="Delimiter">}</span> - <span class="Comment">// return it as the result of the 'reset' call</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>Next_delimited_continuation_id<span class="Delimiter">);</span> - ++Next_delimited_continuation_id<span class="Delimiter">;</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// continue to process rest of 'reset' call</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(code)</span> -call_stack::iterator find_reset<span class="Delimiter">(</span>call_stack&amp; c<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>call_stack::iterator p = c<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != c<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> - if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>is_reset<span class="Delimiter">)</span> <span class="Identifier">return</span> p<span class="Delimiter">;</span> - <span class="Identifier">return</span> c<span class="Delimiter">.</span>end<span class="Delimiter">();</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: overload 'call' for continuations</span> -<span class="Delimiter">:(after &quot;Begin Call&quot;)</span> - if <span class="Delimiter">(</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>properties<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> - &amp;&amp; !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>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> - &amp;&amp; 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>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;continuation&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// copy multiple calls on to current call stack</span> - assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> - if <span class="Delimiter">(</span>Delimited_continuation<span class="Delimiter">.</span>find<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> == Delimited_continuation<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: no such delimited continuation &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Delimiter">}</span> - const call_stack&amp; new_calls = Delimited_continuation[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> - for <span class="Delimiter">(</span>call_stack::const_reverse_iterator p = new_calls<span class="Delimiter">.</span>rbegin<span class="Delimiter">();</span> p != new_calls<span class="Delimiter">.</span>rend<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>*p<span class="Delimiter">);</span> - ++current_step_index<span class="Delimiter">();</span> <span class="Comment">// skip past the reply-delimited-continuation</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> - <span class="Identifier">goto</span> call_housekeeping<span class="Delimiter">;</span> - <span class="Delimiter">}</span> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/054dilated_reagent.cc.html b/html/054dilated_reagent.cc.html new file mode 100644 index 00000000..84086d82 --- /dev/null +++ b/html/054dilated_reagent.cc.html @@ -0,0 +1,140 @@ +<!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 - 054dilated_reagent.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.cSpecial { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.Identifier { color: #804000; } +.Constant { color: #00a0a0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: An alternative syntax for reagents that permits whitespace in properties,</span> +<span class="Comment">//: grouped by brackets.</span> + +<span class="Delimiter">:(scenarios load)</span> +<span class="Delimiter">:(scenario dilated_reagent)</span> +recipe main [ + <span class="Delimiter">{</span><span class="Constant">1</span>: number<span class="Delimiter">,</span> foo: bar<span class="Delimiter">}</span><span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;, &quot;foo&quot;: &quot;bar&quot;}</span> + +<span class="Comment">//: First augment next_word to group balanced brackets together.</span> + +<span class="Delimiter">:(before &quot;End next_word Special-cases&quot;)</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'('</span><span class="Delimiter">)</span> + <span class="Identifier">return</span> slurp_balanced_bracket<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Comment">// treat curlies mostly like parens, but don't mess up labels</span> + if <span class="Delimiter">(</span>start_of_dilated_reagent<span class="Delimiter">(</span>in<span class="Delimiter">))</span> + <span class="Identifier">return</span> slurp_balanced_bracket<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +<span class="Comment">// A curly is considered a label if it's the last thing on a line. Dilated</span> +<span class="Comment">// reagents should remain all on one line.</span> +<span class="Comment">//</span> +<span class="Comment">// Side-effect: This might delete some whitespace after an initial '{'.</span> +bool start_of_dilated_reagent<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'{'</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Comment">// slurp '{'</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + char next = in<span class="Delimiter">.</span>peek<span class="Delimiter">();</span> + in<span class="Delimiter">.</span>putback<span class="Delimiter">(</span><span class="Constant">'{'</span><span class="Delimiter">);</span> + <span class="Identifier">return</span> next != <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">// Assume the first letter is an open bracket, and read everything until the</span> +<span class="Comment">// matching close bracket.</span> +<span class="Comment">// We balance {} () and []. And we skip one character after '\'.</span> +string slurp_balanced_bracket<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ostringstream result<span class="Delimiter">;</span> + char c<span class="Delimiter">;</span> + list&lt;char&gt; open_brackets<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>in &gt;&gt; c<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>c == <span class="cSpecial">'\\'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// always silently skip the next character</span> + result &lt;&lt; c<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!<span class="Delimiter">(</span>in &gt;&gt; c<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + result &lt;&lt; c<span class="Delimiter">;</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>c == <span class="Constant">'('</span><span class="Delimiter">)</span> open_brackets<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>c<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>c == <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>open_brackets<span class="Delimiter">.</span>back<span class="Delimiter">()</span> == <span class="Constant">'('</span><span class="Delimiter">);</span> + open_brackets<span class="Delimiter">.</span>pop_back<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>c == <span class="Constant">'['</span><span class="Delimiter">)</span> open_brackets<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>c<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>c == <span class="Constant">']'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>open_brackets<span class="Delimiter">.</span>back<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">);</span> + open_brackets<span class="Delimiter">.</span>pop_back<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>c == <span class="Constant">'{'</span><span class="Delimiter">)</span> open_brackets<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>c<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>c == <span class="Constant">'}'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>open_brackets<span class="Delimiter">.</span>back<span class="Delimiter">()</span> == <span class="Constant">'{'</span><span class="Delimiter">);</span> + open_brackets<span class="Delimiter">.</span>pop_back<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + result &lt;&lt; c<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>open_brackets<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after &quot;Parsing reagent(string s)&quot;)</span> +if <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>properties<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + istringstream in<span class="Delimiter">(</span>s<span class="Delimiter">);</span> + in &gt;&gt; std::noskipws<span class="Delimiter">;</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Comment">// skip '{'</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + string key = slurp_key<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>key<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>key == <span class="Constant">&quot;}&quot;</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + string_tree* value = new string_tree<span class="Delimiter">(</span>next_word<span class="Delimiter">(</span>in<span class="Delimiter">));</span> + <span class="Comment">// End Parsing Reagent Property(value)</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span>key<span class="Delimiter">,</span> value<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Comment">// structures for the first row of properties</span> + name = properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>first<span class="Delimiter">;</span> + string type_name = properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// this type can't be an integer literal</span> + put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">));</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +string slurp_key<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string result = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + while <span class="Delimiter">(</span>!result<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; *result<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> == <span class="Constant">':'</span><span class="Delimiter">)</span> + strip_last<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + while <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> || in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">':'</span><span class="Delimiter">)</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/055parse_tree.cc.html b/html/055parse_tree.cc.html new file mode 100644 index 00000000..7d9e158f --- /dev/null +++ b/html/055parse_tree.cc.html @@ -0,0 +1,117 @@ +<!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 - 055parse_tree.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.Identifier { color: #804000; } +.Constant { color: #00a0a0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">// So far instructions can only contain linear lists of properties. Now we add</span> +<span class="Comment">// support for more complex trees of properties in dilated reagents. This will</span> +<span class="Comment">// come in handy later for expressing complex types, like &quot;a dictionary from</span> +<span class="Comment">// (address to array of charaters) to (list of numbers)&quot;.</span> + +<span class="Delimiter">:(scenario dilated_reagent_with_nested_brackets)</span> +recipe main [ + <span class="Delimiter">{</span><span class="Constant">1</span>: number<span class="Delimiter">,</span> foo: <span class="Delimiter">(</span>bar <span class="Delimiter">(</span>baz quux<span class="Delimiter">))}</span><span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+parse: product: {&quot;1&quot;: &quot;number&quot;, &quot;foo&quot;: &lt;&quot;bar&quot; : &lt;&lt;&quot;baz&quot; : &lt;&quot;quux&quot; : &lt;&gt;&gt;&gt; : &lt;&gt;&gt;&gt;}</span> + +<span class="Delimiter">:(before &quot;End Parsing Reagent Property(value)&quot;)</span> +value = parse_string_tree<span class="Delimiter">(</span>value<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +string_tree* parse_string_tree<span class="Delimiter">(</span>string_tree* s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!s<span class="Delimiter">-&gt;</span>left &amp;&amp; !s<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>s<span class="Delimiter">-&gt;</span>value<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="Identifier">return</span> s<span class="Delimiter">;</span> + string_tree* result = parse_string_tree<span class="Delimiter">(</span>s<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> + delete s<span class="Delimiter">;</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +string_tree* parse_string_tree<span class="Delimiter">(</span>const string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + istringstream in<span class="Delimiter">(</span>s<span class="Delimiter">);</span> + in &gt;&gt; std::noskipws<span class="Delimiter">;</span> + <span class="Identifier">return</span> parse_string_tree<span class="Delimiter">(</span>in<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +string_tree* parse_string_tree<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'('</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string_tree* result = new string_tree<span class="Delimiter">(</span>next_word<span class="Delimiter">(</span>in<span class="Delimiter">));</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Comment">// skip '('</span> + string_tree* result = <span class="Constant">NULL</span><span class="Delimiter">;</span> + string_tree** curr = &amp;result<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span> + *curr = new string_tree<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_ignored_characters<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'('</span><span class="Delimiter">)</span> + <span class="Delimiter">(</span>*curr<span class="Delimiter">)-&gt;</span>left = parse_string_tree<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + else + <span class="Delimiter">(</span>*curr<span class="Delimiter">)-&gt;</span>value = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + curr = &amp;<span class="Delimiter">(</span>*curr<span class="Delimiter">)-&gt;</span>right<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Comment">// skip ')'</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario dilated_reagent_with_type_tree)</span> +<span class="Special">% Hide_errors = true; // 'map' isn't defined yet</span> +recipe main [ + <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>foo <span class="Delimiter">(</span>address array character<span class="Delimiter">)</span> <span class="Delimiter">(</span>bar number<span class="Delimiter">))}</span><span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="Comment"># just to avoid errors</span> +container foo [ +] +container bar [ +] +<span class="traceContains">+parse: product: {&quot;1&quot;: &lt;&quot;foo&quot; : &lt;&lt;&quot;address&quot; : &lt;&quot;array&quot; : &lt;&quot;character&quot; : &lt;&gt;&gt;&gt;&gt; : &lt;&lt;&quot;bar&quot; : &lt;&quot;number&quot; : &lt;&gt;&gt;&gt; : &lt;&gt;&gt;&gt;&gt;}</span> + +<span class="Comment">//: an exception is 'new', which takes a type tree as its ingredient *value*</span> + +<span class="Delimiter">:(scenario dilated_reagent_with_new)</span> +recipe main [ + x:address:number<span class="Special"> &lt;- </span>new <span class="Delimiter">{(</span>foo bar<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> +] +<span class="Comment"># type isn't defined so size is meaningless, but at least we parse the type correctly</span> +<span class="traceContains">+new: size of &lt;&quot;foo&quot; : &lt;&quot;bar&quot; : &lt;&gt;&gt;&gt; is 1</span> + +<span class="Delimiter">:(before &quot;End Post-processing(type_name) When Converting 'new'&quot;)</span> +type_name = parse_string_tree<span class="Delimiter">(</span>type_name<span class="Delimiter">);</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/056recipe_header.cc.html b/html/056recipe_header.cc.html new file mode 100644 index 00000000..5000a703 --- /dev/null +++ b/html/056recipe_header.cc.html @@ -0,0 +1,395 @@ +<!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 - 056recipe_header.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.SalientComment { color: #00ffff; } +.cSpecial { color: #008000; } +.traceAbsent { color: #c00000; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.Identifier { color: #804000; } +.Constant { color: #00a0a0; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Advanced notation for the common/easy case where a recipe takes some fixed</span> +<span class="Comment">//: number of ingredients and yields some fixed number of products.</span> + +<span class="Delimiter">:(scenario recipe_with_header)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + z:number<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> y + reply z +] +<span class="traceContains">+mem: storing 8 in location 1</span> + +<span class="Comment">//: When loading recipes save any header.</span> + +<span class="Delimiter">:(before &quot;End recipe Fields&quot;)</span> +bool has_header<span class="Delimiter">;</span> +vector&lt;reagent&gt; ingredients<span class="Delimiter">;</span> +vector&lt;reagent&gt; products<span class="Delimiter">;</span> +<span class="Delimiter">:(before &quot;End recipe Constructor&quot;)</span> +has_header = <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before &quot;End recipe Refinements&quot;)</span> +skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> +if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;recipe has a header; parsing&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + load_recipe_header<span class="Delimiter">(</span>in<span class="Delimiter">,</span> result<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void load_recipe_header<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> recipe&amp; result<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>has_header = <span class="Constant">true</span><span class="Delimiter">;</span> + while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string s = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>s == <span class="Constant">&quot;-&gt;&quot;</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + result<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>s<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;header ingredient: &quot;</span> &lt;&lt; result<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>back<span class="Delimiter">().</span>original_string &lt;&lt; end<span class="Delimiter">();</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string s = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>s<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;header product: &quot;</span> &lt;&lt; result<span class="Delimiter">.</span>products<span class="Delimiter">.</span>back<span class="Delimiter">().</span>original_string &lt;&lt; end<span class="Delimiter">();</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Load Recipe Header(result)</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario recipe_handles_stray_comma)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number<span class="Delimiter">,</span> [ + local-scope + load-ingredients + z:number<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> y + reply z +] +<span class="traceContains">+mem: storing 8 in location 1</span> + +<span class="Delimiter">:(scenario recipe_handles_stray_comma_2)</span> +recipe main [ + foo +] +recipe foo<span class="Delimiter">,</span> [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">2</span> +] +recipe bar [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">3</span> +] +<span class="traceContains">+mem: storing 4 in location 1</span> + +<span class="Delimiter">:(after &quot;Begin debug_string(recipe x)&quot;)</span> +out &lt;&lt; <span class="Constant">&quot;ingredients:</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span> +for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + out &lt;&lt; <span class="Constant">&quot; &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> +out &lt;&lt; <span class="Constant">&quot;products:</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span> +for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>x<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + out &lt;&lt; <span class="Constant">&quot; &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + +<span class="Comment">//: If a recipe never mentions any ingredients or products, assume it has a header.</span> + +<span class="Delimiter">:(scenario recipe_without_ingredients_or_products_has_header)</span> +recipe test [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+parse: recipe test has a header</span> + +<span class="Delimiter">:(before &quot;End recipe Body(result)&quot;)</span> +if <span class="Delimiter">(</span>!result<span class="Delimiter">.</span>has_header<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>has_header = <span class="Constant">true</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>result<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">((</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;reply&quot;</span> &amp;&amp; !inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;next-ingredient&quot;</span> + || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;ingredient&quot;</span> + || inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;rewind-ingredients&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>has_header = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +if <span class="Delimiter">(</span>result<span class="Delimiter">.</span>has_header<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">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;recipe &quot;</span> &lt;&lt; result<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; has a header&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Rewrite 'load-ingredients' to instructions to create all reagents in the header.</span> + +<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr, recipe result)&quot;)</span> +if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;load-ingredients&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>result<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + curr<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;next-ingredient&quot;</span><span class="Delimiter">);</span> + curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;next-ingredient&quot;</span><span class="Delimiter">;</span> + curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> + curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Check types going in and out of all recipes with headers.</span> + +<span class="Delimiter">:(scenarios transform)</span> +<span class="Delimiter">:(scenario recipe_headers_are_checked)</span> +<span class="Special">% Hide_errors = true;</span> +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + z:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Special">raw</span> + reply z +] +<span class="traceContains">+error: add2: replied with the wrong type at 'reply z'</span> + +<span class="Delimiter">:(after &quot;Transform.push_back(check_types_by_name)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_reply_instructions_against_header<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void check_reply_instructions_against_header<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const recipe&amp; caller_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<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">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- checking reply instructions against header for &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- checking reply instructions against header for &quot; &lt;&lt; caller_recipe.name &lt;&lt; '\n';</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name != <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;tried to reply the wrong number of products in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<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> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;replied with the wrong type at '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario recipe_headers_check_for_duplicate_names)</span> +<span class="Special">% Hide_errors = true;</span> +recipe add2 x:number<span class="Delimiter">,</span> x:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + reply z +] +<span class="traceContains">+error: add2: x can't repeat in the ingredients</span> + +<span class="Delimiter">:(before &quot;End recipe Fields&quot;)</span> +map&lt;string<span class="Delimiter">,</span> int&gt; ingredient_index<span class="Delimiter">;</span> + +<span class="Delimiter">:(after &quot;Transform.push_back(insert_fragments)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_and_update_header_reagents<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void check_and_update_header_reagents<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe&amp; caller_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<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">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- checking reply instructions against header for &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredient_index<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">))</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; can't repeat in the ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredient_index<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">,</span> i<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Deduce types from the header if possible.</span> + +<span class="Delimiter">:(scenarios run)</span> +<span class="Delimiter">:(scenario deduce_instruction_types_from_recipe_header)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + z<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> y <span class="Comment"># no type for z</span> + reply z +] +<span class="traceContains">+mem: storing 8 in location 1</span> + +<span class="Delimiter">:(before &quot;Transform.push_back(check_reply_instructions_against_header)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>deduce_types_from_header<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void deduce_types_from_header<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe&amp; caller_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<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">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- deduce types from header for &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr &lt;&lt; &quot;--- deduce types from header for &quot; &lt;&lt; caller_recipe.name &lt;&lt; '\n';</span> + map&lt;string<span class="Delimiter">,</span> const type_tree*&gt; header_type<span class="Delimiter">;</span> + map&lt;string<span class="Delimiter">,</span> const string_tree*&gt; header_type_name<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + put<span class="Delimiter">(</span>header_type<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>header_type_name<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type of &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + put<span class="Delimiter">(</span>header_type<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>header_type_name<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type of &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = caller_recipe<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">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;instruction: &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>header_type<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">)</span> == header_type<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;unknown variable &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type = new type_tree<span class="Delimiter">(</span>*get<span class="Delimiter">(</span>header_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second = new string_tree<span class="Delimiter">(</span>*get<span class="Delimiter">(</span>header_type_name<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type of &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; product: &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>header_type<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">)</span> == header_type<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;unknown variable &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type = new type_tree<span class="Delimiter">(</span>*get<span class="Delimiter">(</span>header_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second = new string_tree<span class="Delimiter">(</span>*get<span class="Delimiter">(</span>header_type_name<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type of &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: One final convenience: no need to say what to return if the information is</span> +<span class="Comment">//: in the header.</span> + +<span class="Delimiter">:(scenario reply_based_on_header)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + z<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> y + reply +] +<span class="traceContains">+mem: storing 8 in location 1</span> + +<span class="Delimiter">:(after &quot;Transform.push_back(check_and_update_header_reagents)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>fill_in_reply_ingredients<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void fill_in_reply_ingredients<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe&amp; caller_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!caller_recipe<span class="Delimiter">.</span>has_header<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- fill in reply ingredients from header for recipe &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;reply&quot;</span> &amp;&amp; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + add_header_products<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// fall through reply</span> + if <span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">).</span>name != <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction inst<span class="Delimiter">;</span> + inst<span class="Delimiter">.</span>name = <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">;</span> + add_header_products<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">);</span> + caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void add_header_products<span class="Delimiter">(</span>instruction&amp; inst<span class="Delimiter">,</span> const recipe&amp; caller_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;reply&quot;</span><span class="Delimiter">);</span> + <span class="Comment">// collect any products with the same names as ingredients</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// if the ingredient is missing, add it from the header</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> == i<span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Comment">// if it's missing /same_as_ingredient, try to fill it in</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredient_index<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &amp;&amp; !has_property<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="Constant">&quot;same_as_ingredient&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + ostringstream same_as_ingredient<span class="Delimiter">;</span> + same_as_ingredient &lt;&lt; get<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>ingredient_index<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;same-as-ingredient&quot;</span><span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span>same_as_ingredient<span class="Delimiter">.</span>str<span class="Delimiter">())));</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario explicit_reply_ignores_header)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-&gt;</span> y:number<span class="Delimiter">,</span> z:number [ + local-scope + load-ingredients + y<span class="Special"> &lt;- </span>add a<span class="Delimiter">,</span> b + z<span class="Special"> &lt;- </span>subtract a<span class="Delimiter">,</span> b + reply a<span class="Delimiter">,</span> z +] +<span class="traceContains">+mem: storing 3 in location 1</span> +<span class="traceContains">+mem: storing -2 in location 2</span> + +<span class="Delimiter">:(scenario reply_on_fallthrough_based_on_header)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + z<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> y +] +<span class="traceContains">+transform: instruction: reply z:number</span> +<span class="traceContains">+mem: storing 8 in location 1</span> + +<span class="Delimiter">:(scenario reply_on_fallthrough_already_exists)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>add2 <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> z:number [ + local-scope + load-ingredients + z<span class="Special"> &lt;- </span>add x<span class="Delimiter">,</span> y <span class="Comment"># no type for z</span> + reply z +] +<span class="traceContains">+transform: instruction: reply z</span> +<span class="traceAbsent">-transform: instruction: reply z:number</span> +<span class="traceContains">+mem: storing 8 in location 1</span> + +<span class="Delimiter">:(scenario recipe_headers_perform_same_ingredient_check)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>add2 <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +recipe add2 x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-&gt;</span> x:number [ + local-scope + load-ingredients +] +<span class="traceContains">+error: main: '3:number &lt;- add2 1:number, 2:number' should write to 1:number rather than 3:number</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/057static_dispatch.cc.html b/html/057static_dispatch.cc.html new file mode 100644 index 00000000..ec362d4a --- /dev/null +++ b/html/057static_dispatch.cc.html @@ -0,0 +1,223 @@ +<!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 - 057static_dispatch.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.Identifier { color: #804000; } +.Constant { color: #00a0a0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Transform to maintain multiple variants of a recipe depending on the</span> +<span class="Comment">//: number and types of the ingredients and products. Allows us to use nice</span> +<span class="Comment">//: names like 'print' or 'length' in many mutually extensible ways.</span> + +<span class="Delimiter">:(scenario static_dispatch)</span> +recipe main [ + <span class="Constant">7</span>:number/<span class="Special">raw &lt;- </span>test <span class="Constant">3</span> +] +recipe test a:number <span class="Delimiter">-&gt;</span> z:number [ + z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> +] +recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-&gt;</span> z:number [ + z<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 1 in location 7</span> + +<span class="Comment">//: When loading recipes, accumulate variants if headers don't collide, and</span> +<span class="Comment">//: raise a warning if headers collide.</span> + +<span class="Delimiter">:(before &quot;End Globals&quot;)</span> +map&lt;string<span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt; &gt; Recipe_variants<span class="Delimiter">;</span> +<span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span> +put<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> <span class="Constant">&quot;main&quot;</span><span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt;<span class="Delimiter">());</span> <span class="Comment">// since we manually added main to Recipe_ordinal</span> +<span class="Delimiter">:(before &quot;End Setup&quot;)</span> +for <span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt; &gt;::iterator p = Recipe_variants<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe_variants<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &gt;= Reserved_for_tests<span class="Delimiter">)</span> + p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// just leave a ghost</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before &quot;End Load Recipe Header(result)&quot;)</span> +if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + const recipe_ordinal r = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + if <span class="Delimiter">((</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>has_header<span class="Delimiter">)</span> + &amp;&amp; !header_already_exists<span class="Delimiter">(</span>result<span class="Delimiter">))</span> <span class="Delimiter">{</span> + string new_name = next_unused_recipe_name<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> + get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">));</span> + result<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +else <span class="Delimiter">{</span> + <span class="Comment">// save first variant</span> + put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> + get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +bool header_already_exists<span class="Delimiter">(</span>const recipe&amp; rr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const vector&lt;recipe_ordinal&gt;&amp; variants = get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> rr<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">()</span> + &amp;&amp; all_reagents_match<span class="Delimiter">(</span>rr<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool all_reagents_match<span class="Delimiter">(</span>const recipe&amp; r1<span class="Delimiter">,</span> const recipe&amp; r2<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>r2<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>r2<span class="Delimiter">.</span>products<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!exact_match<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> r2<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!exact_match<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> r2<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool exact_match<span class="Delimiter">(</span>type_tree* a<span class="Delimiter">,</span> type_tree* b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>a == b<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> a<span class="Delimiter">-&gt;</span>value == b<span class="Delimiter">-&gt;</span>value + &amp;&amp; exact_match<span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> b<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> + &amp;&amp; exact_match<span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> b<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +string next_unused_recipe_name<span class="Delimiter">(</span>const string&amp; recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">2</span><span class="Delimiter">;</span> <span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ostringstream out<span class="Delimiter">;</span> + out &lt;&lt; recipe_name &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; i<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>out<span class="Delimiter">.</span>str<span class="Delimiter">())</span> == Recipe_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Once all the recipes are loaded, transform their bodies to replace each</span> +<span class="Comment">//: call with the most suitable variant.</span> + +<span class="Delimiter">:(scenario static_dispatch_picks_most_similar_variant)</span> +recipe main [ + <span class="Constant">7</span>:number/<span class="Special">raw &lt;- </span>test <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">5</span> +] +recipe test a:number <span class="Delimiter">-&gt;</span> z:number [ + z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> +] +recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-&gt;</span> z:number [ + z<span class="Special"> &lt;- </span>copy <span class="Constant">2</span> +] +<span class="traceContains">+mem: storing 2 in location 7</span> + +<span class="Comment">//: after insert_fragments (tangle) and before computing operation ids</span> +<span class="Comment">//: after filling in all missing types (because we'll be introducing 'blank' types in this transform in a later layer, for shape-shifting recipes)</span> +<span class="Delimiter">:(after &quot;Transform.push_back(deduce_types_from_header)&quot;)</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>resolve_ambiguous_calls<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void resolve_ambiguous_calls<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe&amp; caller_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!caller_recipe<span class="Delimiter">.</span>has_header<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- resolve ambiguous calls for recipe &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">).</span>empty<span class="Delimiter">());</span> + replace_best_variant<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void replace_best_variant<span class="Delimiter">(</span>instruction&amp; inst<span class="Delimiter">,</span> const recipe&amp; caller_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;instruction &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + vector&lt;recipe_ordinal&gt;&amp; variants = get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + long long int best_score = variant_score<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">));</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int current_score = variant_score<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking variant &quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; current_score &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>current_score &gt; best_score<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>name = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">;</span> + best_score = current_score<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Instruction Dispatch(inst, best_score)</span> +<span class="Delimiter">}</span> + +long long int variant_score<span class="Delimiter">(</span>const instruction&amp; inst<span class="Delimiter">,</span> recipe_ordinal variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>variant == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// ghost from a previous test</span> + const vector&lt;reagent&gt;&amp; header_ingredients = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt; SIZE<span class="Delimiter">(</span>header_ingredients<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;too few ingredients&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>header_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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;mismatch: ingredient &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;too few products&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + const vector&lt;reagent&gt;&amp; header_products = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>header_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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;mismatch: product &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Comment">// the greater the number of unused ingredients, the lower the score</span> + <span class="Identifier">return</span> <span class="Constant">100</span> - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<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> + - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span>-SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">));</span> <span class="Comment">// ok to go negative</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario static_dispatch_disabled_on_headerless_definition)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe test a:number <span class="Delimiter">-&gt;</span> z:number [ + z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> +] +recipe test [ + reply <span class="Constant">34</span> +] +<span class="traceContains">+warn: redefining recipe test</span> + +<span class="Delimiter">:(scenario static_dispatch_disabled_on_headerless_definition_2)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe test [ + reply <span class="Constant">34</span> +] +recipe test a:number <span class="Delimiter">-&gt;</span> z:number [ + z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> +] +<span class="traceContains">+warn: redefining recipe test</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/058shape_shifting_container.cc.html b/html/058shape_shifting_container.cc.html new file mode 100644 index 00000000..4425953a --- /dev/null +++ b/html/058shape_shifting_container.cc.html @@ -0,0 +1,294 @@ +<!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 - 058shape_shifting_container.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Special { color: #ff6060; } +.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.SalientComment { color: #00ffff; } +.Identifier { color: #804000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="SalientComment">//:: Container definitions can contain type parameters.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Extremely hacky initial implementation:</span> +<span class="Comment">//:</span> +<span class="Comment">//: a) We still don't support the full complexity of type trees inside</span> +<span class="Comment">//: container definitions. So for example you can't have a container element</span> +<span class="Comment">//: with this type:</span> +<span class="Comment">//: (map (array address character) (list number))</span> +<span class="Comment">//:</span> +<span class="Comment">//: b) We also can't include type parameters anywhere except at the top of the</span> +<span class="Comment">//: type of a container element.</span> + +<span class="Delimiter">:(scenario size_of_shape_shifting_container)</span> +container foo:_t [ + x:_t + y:number +] +recipe main [ + <span class="Constant">1</span>:foo:number<span class="Special"> &lt;- </span>merge <span class="Constant">12</span><span class="Delimiter">,</span> <span class="Constant">13</span> + <span class="Constant">3</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> +] +<span class="traceContains">+mem: storing 12 in location 1</span> +<span class="traceContains">+mem: storing 13 in location 2</span> +<span class="traceContains">+mem: storing 14 in location 3</span> +<span class="traceContains">+mem: storing 15 in location 4</span> +<span class="traceContains">+mem: storing 16 in location 5</span> + +<span class="Delimiter">:(before &quot;End Globals&quot;)</span> +<span class="Comment">// We'll use large type ordinals to mean &quot;the following type of the variable&quot;.</span> +const int START_TYPE_INGREDIENTS = <span class="Constant">2000</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before &quot;End Test Run Initialization&quot;)</span> +assert<span class="Delimiter">(</span>Next_type_ordinal &lt; START_TYPE_INGREDIENTS<span class="Delimiter">);</span> + +<span class="Delimiter">:(before &quot;End type_info Fields&quot;)</span> +map&lt;string<span class="Delimiter">,</span> type_ordinal&gt; type_ingredient_names<span class="Delimiter">;</span> + +<span class="Comment">//: Suppress unknown type checks in shape-shifting containers.</span> + +<span class="Delimiter">:(before &quot;Check Container Field Types(info)&quot;)</span> +if <span class="Delimiter">(</span>!info<span class="Delimiter">.</span>type_ingredient_names<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before &quot;End container Name Refinements&quot;)</span> +if <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="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;container has type ingredients; parsing&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + read_type_ingredients<span class="Delimiter">(</span>name<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void read_type_ingredients<span class="Delimiter">(</span>string&amp; name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string save_name = name<span class="Delimiter">;</span> + istringstream in<span class="Delimiter">(</span>save_name<span class="Delimiter">);</span> + name = slurp_until<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> + put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> + type_info&amp; 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> + long long int next_type_ordinal = START_TYPE_INGREDIENTS<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + string curr = slurp_until<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>info<span class="Delimiter">.</span>type_ingredient_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>curr<span class="Delimiter">)</span> != info<span class="Delimiter">.</span>type_ingredient_names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;can't repeat type ingredient names in a single container definition</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + put<span class="Delimiter">(</span>info<span class="Delimiter">.</span>type_ingredient_names<span class="Delimiter">,</span> curr<span class="Delimiter">,</span> next_type_ordinal++<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before &quot;End insert_container Special Uses(type_name)&quot;)</span> +<span class="Comment">// check for use of type ingredients</span> +if <span class="Delimiter">(</span>type_name<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> + *curr_type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>info<span class="Delimiter">.</span>type_ingredient_names<span class="Delimiter">,</span> type_name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; type: &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>info<span class="Delimiter">.</span>type_ingredient_names<span class="Delimiter">,</span> type_name<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before &quot;End Container Type Checks&quot;)</span> +if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value &gt;= START_TYPE_INGREDIENTS + &amp;&amp; <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value - START_TYPE_INGREDIENTS<span class="Delimiter">)</span> &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>type_ingredient_names<span class="Delimiter">))</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before &quot;End size_of(type) Container Cases&quot;)</span> +if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>value &gt;= START_TYPE_INGREDIENTS<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">&quot;type&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking size of type ingredient</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + long long int size = size_of_type_ingredient<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!size<span class="Delimiter">)</span> + raise_error &lt;&lt; <span class="Constant">&quot;illegal type '&quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + result += size<span class="Delimiter">;</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +<span class="Comment">// shape-shifting version of size_of</span> +long long int size_of_type_ingredient<span class="Delimiter">(</span>const type_tree* element_template<span class="Delimiter">,</span> const type_tree* rest_of_use<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int type_ingredient_index = element_template<span class="Delimiter">-&gt;</span>value - START_TYPE_INGREDIENTS<span class="Delimiter">;</span> + const type_tree* curr = rest_of_use<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!curr<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + while <span class="Delimiter">(</span>type_ingredient_index &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + --type_ingredient_index<span class="Delimiter">;</span> + curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!curr<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>!curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">);</span> <span class="Comment">// unimplemented</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> curr<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// temporarily while we're still ironing out kinks; eventually replace with a raise_error</span> + DUMP<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + cerr &lt;&lt; <span class="Constant">&quot;missing type &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>curr<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> curr<span class="Delimiter">-&gt;</span>value<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;type&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type deduced to be &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> curr<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;$&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + type_tree tmp<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> + tmp<span class="Delimiter">.</span>right = new type_tree<span class="Delimiter">(</span>*curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>&amp;tmp<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario get_on_shape_shifting_container)</span> +container foo:_t [ + x:_t + y:number +] +recipe main [ + <span class="Constant">1</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:foo:point<span class="Delimiter">,</span> y:offset +] +<span class="traceContains">+mem: storing 16 in location 2</span> + +<span class="Delimiter">:(before &quot;End GET field Cases&quot;)</span> +const type_tree* type = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value &gt;= START_TYPE_INGREDIENTS<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int size = size_of_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!size<span class="Delimiter">)</span> + raise_error &lt;&lt; <span class="Constant">&quot;illegal field type '&quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + src += size<span class="Delimiter">;</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario get_on_shape_shifting_container_2)</span> +container foo:_t [ + x:_t + y:number +] +recipe main [ + <span class="Constant">1</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> + <span class="Constant">2</span>:point<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:foo:point<span class="Delimiter">,</span> x:offset +] +<span class="traceContains">+mem: storing 14 in location 2</span> +<span class="traceContains">+mem: storing 15 in location 3</span> + +<span class="Delimiter">:(scenario get_on_shape_shifting_container_3)</span> +container foo:_t [ + x:_t + y:number +] +recipe main [ + <span class="Constant">1</span>:foo:address:point<span class="Special"> &lt;- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">48</span> <span class="Comment"># unsafe</span> + <span class="Constant">2</span>:address:point<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:foo:address:point<span class="Delimiter">,</span> x:offset +] +<span class="traceContains">+mem: storing 34 in location 2</span> + +<span class="Delimiter">:(before &quot;End element_type Special-cases&quot;)</span> +if <span class="Delimiter">(</span>contains_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> + raise_error &lt;&lt; <span class="Constant">&quot;illegal type '&quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + replace_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +bool contains_type_ingredient<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> contains_type_ingredient<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool contains_type_ingredient<span class="Delimiter">(</span>const type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value &gt;= START_TYPE_INGREDIENTS<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> contains_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> || contains_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void replace_type_ingredient<span class="Delimiter">(</span>type_tree* element_type<span class="Delimiter">,</span> const type_tree* callsite_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!callsite_type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error but it's already been raised above</span> + if <span class="Delimiter">(</span>!element_type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>element_type<span class="Delimiter">-&gt;</span>value &gt;= START_TYPE_INGREDIENTS<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!has_nth_type<span class="Delimiter">(</span>callsite_type<span class="Delimiter">,</span> element_type<span class="Delimiter">-&gt;</span>value-START_TYPE_INGREDIENTS<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;illegal type '&quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>callsite_type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + const type_tree* replacement = nth_type<span class="Delimiter">(</span>callsite_type<span class="Delimiter">,</span> element_type<span class="Delimiter">-&gt;</span>value-START_TYPE_INGREDIENTS<span class="Delimiter">);</span> + element_type<span class="Delimiter">-&gt;</span>value = replacement<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + element_type<span class="Delimiter">-&gt;</span>left = replacement<span class="Delimiter">-&gt;</span>left ? new type_tree<span class="Delimiter">(</span>*replacement<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span> + element_type<span class="Delimiter">-&gt;</span>right = replacement<span class="Delimiter">-&gt;</span>right ? new type_tree<span class="Delimiter">(</span>*replacement<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + replace_type_ingredient<span class="Delimiter">(</span>element_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> callsite_type<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +const type_tree* nth_type<span class="Delimiter">(</span>const type_tree* base<span class="Delimiter">,</span> long long int n<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>n &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>n == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> base<span class="Delimiter">;</span> + <span class="Identifier">return</span> nth_type<span class="Delimiter">(</span>base<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> n-<span class="Constant">1</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool has_nth_type<span class="Delimiter">(</span>const type_tree* base<span class="Delimiter">,</span> long long int n<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>n &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> + if <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> + if <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">-&gt;</span>right<span class="Delimiter">,</span> n-<span class="Constant">1</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario get_on_shape_shifting_container_error)</span> +<span class="Special">% Hide_errors = true;</span> +container foo:_t [ + x:_t + y:number +] +recipe main [ + <span class="Constant">10</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> + <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>get <span class="Constant">10</span>:foo<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+error: illegal type 'foo' seems to be missing a type ingredient or three</span> + +<span class="Comment">//: get-address similarly</span> + +<span class="Delimiter">:(scenario get_address_on_shape_shifting_container)</span> +container foo:_t [ + x:_t + y:number +] +recipe main [ + <span class="Constant">10</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> + <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>get-address <span class="Constant">10</span>:foo:point<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+mem: storing 12 in location 1</span> + +<span class="Delimiter">:(before &quot;End GET_ADDRESS field Cases&quot;)</span> +const type_tree* type = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +if <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value &gt;= START_TYPE_INGREDIENTS<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int size = size_of_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!size<span class="Delimiter">)</span> + raise_error &lt;&lt; <span class="Constant">&quot;illegal type '&quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + result += size<span class="Delimiter">;</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario get_on_shape_shifting_container_inside_shape_shifting_container)</span> +container foo:_t [ + x:_t + y:number +] +container bar [ + x:foo:point + y:number +] +recipe main [ + <span class="Constant">1</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span><span class="Delimiter">,</span> <span class="Constant">17</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:bar<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+mem: storing 17 in location 2</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/059shape_shifting_recipe.cc.html b/html/059shape_shifting_recipe.cc.html new file mode 100644 index 00000000..2df37fa3 --- /dev/null +++ b/html/059shape_shifting_recipe.cc.html @@ -0,0 +1,482 @@ +<!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 - 059shape_shifting_recipe.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Special { color: #ff6060; } +.cSpecial { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.SalientComment { color: #00ffff; } +.Identifier { color: #804000; } +.Constant { color: #00a0a0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="SalientComment">//:: Like container definitions, recipes too can contain type parameters.</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe)</span> +recipe main [ + <span class="Constant">10</span>:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span> + <span class="Constant">11</span>:point<span class="Special"> &lt;- </span>foo <span class="Constant">10</span>:point +] +<span class="Comment"># non-matching variant</span> +recipe foo a:number <span class="Delimiter">-&gt;</span> result:number [ + local-scope + load-ingredients + result<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="Comment"># matching shape-shifting variant</span> +recipe foo a:_t <span class="Delimiter">-&gt;</span> result:_t [ + local-scope + load-ingredients + result<span class="Special"> &lt;- </span>copy a +] +<span class="traceContains">+mem: storing 14 in location 11</span> +<span class="traceContains">+mem: storing 15 in location 12</span> + +<span class="Comment">//: Before anything else, disable transforms for shape-shifting recipes.</span> + +<span class="Delimiter">:(before &quot;End Transform Checks&quot;)</span> +if <span class="Delimiter">(</span>any_type_ingredient_in_header<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">recipe_ordinal</span><span class="Comment">*/</span>p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + +<span class="Comment">//: We'll be creating recipes without loading them from anywhere by</span> +<span class="Comment">//: *specializing* existing recipes, so make sure we don't clear any of those</span> +<span class="Comment">//: when we start running tests.</span> +<span class="Delimiter">:(before &quot;End Loading .mu Files&quot;)</span> +recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + +<span class="Delimiter">:(before &quot;End Instruction Dispatch(inst, best_score)&quot;)</span> +if <span class="Delimiter">(</span>best_score == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;no variant found; searching for variant with suitable type ingredients&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + recipe_ordinal exemplar = pick_matching_shape_shifting_variant<span class="Delimiter">(</span>variants<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> best_score<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>exemplar<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;found variant to specialize: &quot;</span> &lt;&lt; exemplar &lt;&lt; <span class="Constant">' '</span> &lt;&lt; get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">).</span>name &lt;&lt; end<span class="Delimiter">();</span> + variants<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_variant<span class="Delimiter">(</span>exemplar<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">));</span> + inst<span class="Delimiter">.</span>name = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>back<span class="Delimiter">()).</span>name<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new specialization: &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +recipe_ordinal pick_matching_shape_shifting_variant<span class="Delimiter">(</span>vector&lt;recipe_ordinal&gt;&amp; variants<span class="Delimiter">,</span> const instruction&amp; inst<span class="Delimiter">,</span> long long int&amp; best_score<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe_ordinal result = <span class="Constant">0</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// ghost from a previous test</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking shape-shifting variant &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span> + long long int current_score = shape_shifting_variant_score<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;final score: &quot;</span> &lt;&lt; current_score &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>current_score &gt; best_score<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;matches&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + result = variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + best_score = current_score<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +long long int shape_shifting_variant_score<span class="Delimiter">(</span>const instruction&amp; inst<span class="Delimiter">,</span> recipe_ordinal variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!any_type_ingredient_in_header<span class="Delimiter">(</span>variant<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;no type ingredients&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + const vector&lt;reagent&gt;&amp; header_ingredients = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &lt; SIZE<span class="Delimiter">(</span>header_ingredients<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;too few ingredients&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!non_type_ingredients_match<span class="Delimiter">(</span>header_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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;mismatch: ingredient &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;too few products&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + const vector&lt;reagent&gt;&amp; header_products = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!non_type_ingredients_match<span class="Delimiter">(</span>header_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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;mismatch: product &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Comment">// the greater the number of unused ingredients, the lower the score</span> + <span class="Identifier">return</span> <span class="Constant">100</span> - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<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> + - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span>-SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">));</span> <span class="Comment">// ok to go negative</span> +<span class="Delimiter">}</span> + +bool any_type_ingredient_in_header<span class="Delimiter">(</span>recipe_ordinal variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>contains_type_ingredient_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>contains_type_ingredient_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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> + +bool non_type_ingredients_match<span class="Delimiter">(</span>const reagent&amp; lhs<span class="Delimiter">,</span> const reagent&amp; rhs<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>contains_type_ingredient_name<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">,</span> rhs<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool contains_type_ingredient_name<span class="Delimiter">(</span>const reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> contains_type_ingredient_name<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool contains_type_ingredient_name<span class="Delimiter">(</span>const string_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_type_ingredient_name<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> contains_type_ingredient_name<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> || contains_type_ingredient_name<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_type_ingredient_name<span class="Delimiter">(</span>const string&amp; type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> !type<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; type<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> + +recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exemplar<span class="Delimiter">,</span> const instruction&amp; inst<span class="Delimiter">,</span> const recipe&amp; caller_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string new_name = next_unused_recipe_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;switching &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; new_name &lt;&lt; end<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">));</span> + recipe_ordinal new_recipe_ordinal = put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> + <span class="Comment">// make a copy</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">));</span> + recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_recipe_ordinal<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">));</span> + recipe&amp; new_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">);</span> + new_recipe<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> + <span class="Comment">// Since the exemplar never ran any transforms, we have to redo some of the</span> + <span class="Comment">// work of the check_types_by_name transform while supporting type-ingredients.</span> + compute_type_names<span class="Delimiter">(</span>new_recipe<span class="Delimiter">);</span> + <span class="Comment">// that gives enough information to replace type-ingredients with concrete types</span> + <span class="Delimiter">{</span> + map&lt;string<span class="Delimiter">,</span> const string_tree*&gt; mappings<span class="Delimiter">;</span> + bool error = <span class="Constant">false</span><span class="Delimiter">;</span> + compute_type_ingredient_mappings<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">),</span> inst<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> &amp;error<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!error<span class="Delimiter">)</span> replace_type_ingredients<span class="Delimiter">(</span>new_recipe<span class="Delimiter">,</span> mappings<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;::iterator p = mappings<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != mappings<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> + delete p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>error<span class="Delimiter">)</span> <span class="Identifier">return</span> exemplar<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">);</span> + <span class="Comment">// finally, perform all transforms on the new specialization</span> + for <span class="Delimiter">(</span>long long int t = <span class="Constant">0</span><span class="Delimiter">;</span> t &lt; SIZE<span class="Delimiter">(</span>Transform<span class="Delimiter">);</span> ++t<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Delimiter">(</span>*Transform<span class="Delimiter">.</span>at<span class="Delimiter">(</span>t<span class="Delimiter">))(</span>new_recipe_ordinal<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + new_recipe<span class="Delimiter">.</span>transformed_until = SIZE<span class="Delimiter">(</span>Transform<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> new_recipe_ordinal<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +void compute_type_names<span class="Delimiter">(</span>recipe&amp; variant<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;compute type names: &quot;</span> &lt;&lt; variant<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> + map&lt;string<span class="Delimiter">,</span> string_tree*&gt; type_names<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; 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> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; 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> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; 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&amp; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; instruction: &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int in = <span class="Constant">0</span><span class="Delimiter">;</span> in &lt; 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> + for <span class="Delimiter">(</span>long long int out = <span class="Constant">0</span><span class="Delimiter">;</span> out &lt; 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> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void save_or_deduce_type_name<span class="Delimiter">(</span>reagent&amp; x<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> string_tree*&gt;&amp; type_name<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; checking &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second &amp;&amp; contains_key<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second = new string_tree<span class="Delimiter">(</span>*get<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; deducing type to &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;unknown type for &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;offset&quot;</span> || x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;variant&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// special-case for container-access instructions</span> + put<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">,</span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type of &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; is &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +void compute_type_ingredient_mappings<span class="Delimiter">(</span>const recipe&amp; exemplar<span class="Delimiter">,</span> const instruction&amp; inst<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;&amp; mappings<span class="Delimiter">,</span> const recipe&amp; caller_recipe<span class="Delimiter">,</span> bool* error<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const reagent&amp; exemplar_reagent = exemplar<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + reagent ingredient = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>ingredient<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> + accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_reagent<span class="Delimiter">,</span> ingredient<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const reagent&amp; exemplar_reagent = exemplar<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + reagent product = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_reagent<span class="Delimiter">,</span> product<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void accumulate_type_ingredients<span class="Delimiter">(</span>const reagent&amp; exemplar_reagent<span class="Delimiter">,</span> reagent&amp; refinement<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;&amp; mappings<span class="Delimiter">,</span> const recipe&amp; exemplar<span class="Delimiter">,</span> const instruction&amp; call_instruction<span class="Delimiter">,</span> const recipe&amp; caller_recipe<span class="Delimiter">,</span> bool* error<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>refinement<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_reagent<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> refinement<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> exemplar_reagent<span class="Delimiter">,</span> call_instruction<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void accumulate_type_ingredients<span class="Delimiter">(</span>const string_tree* exemplar_type<span class="Delimiter">,</span> const string_tree* refinement_type<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;&amp; mappings<span class="Delimiter">,</span> const recipe&amp; exemplar<span class="Delimiter">,</span> const reagent&amp; exemplar_reagent<span class="Delimiter">,</span> const instruction&amp; call_instruction<span class="Delimiter">,</span> const recipe&amp; caller_recipe<span class="Delimiter">,</span> bool* error<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!exemplar_type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!refinement_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;missing type ingredient in &quot;</span> &lt;&lt; exemplar_reagent<span class="Delimiter">.</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!exemplar_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; exemplar_type<span class="Delimiter">-&gt;</span>value<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>!refinement_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + if <span class="Delimiter">(</span>exemplar_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;type_ingredients in non-last position not currently supported</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-&gt;</span>value<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;adding mapping from &quot;</span> &lt;&lt; exemplar_type<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>refinement_type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span>*refinement_type<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!deeply_equal<span class="Delimiter">(</span>get<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">),</span> refinement_type<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;no call found for '&quot;</span> &lt;&lt; call_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + *error = <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> refinement_type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> exemplar_reagent<span class="Delimiter">,</span> call_instruction<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> refinement_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> exemplar_reagent<span class="Delimiter">,</span> call_instruction<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void replace_type_ingredients<span class="Delimiter">(</span>recipe&amp; new_recipe<span class="Delimiter">,</span> const map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;&amp; mappings<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// update its header</span> + if <span class="Delimiter">(</span>mappings<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">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;replacing in recipe header ingredients&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + replace_type_ingredients<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> mappings<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;replacing in recipe header products&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + replace_type_ingredients<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> mappings<span class="Delimiter">);</span> + <span class="Comment">// update its body</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction&amp; inst = new_recipe<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;replacing in instruction '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> + replace_type_ingredients<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> mappings<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> + replace_type_ingredients<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> mappings<span class="Delimiter">);</span> + <span class="Comment">// special-case for new: replace type ingredient in first ingredient *value*</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;new&quot;</span> &amp;&amp; inst<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="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> + string_tree* type_name = parse_string_tree<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>name<span class="Delimiter">);</span> + replace_type_ingredients<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> mappings<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>name = type_name<span class="Delimiter">-&gt;</span>to_string<span class="Delimiter">();</span> + delete type_name<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void replace_type_ingredients<span class="Delimiter">(</span>reagent&amp; x<span class="Delimiter">,</span> const map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;&amp; mappings<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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;replacing in ingredient &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>original_string &lt;&lt; end<span class="Delimiter">();</span> + <span class="Comment">// replace properties</span> + assert<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + replace_type_ingredients<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> mappings<span class="Delimiter">);</span> + <span class="Comment">// refresh types from properties</span> + delete x<span class="Delimiter">.</span>type<span class="Delimiter">;</span> + x<span class="Delimiter">.</span>type = new_type_tree<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; after: &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +void replace_type_ingredients<span class="Delimiter">(</span>string_tree* type<span class="Delimiter">,</span> const map&lt;string<span class="Delimiter">,</span> const string_tree*&gt;&amp; mappings<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_type_ingredient_name<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> &amp;&amp; contains_key<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Delimiter">{</span> + const string_tree* replacement = get<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; type<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; debug_string<span class="Delimiter">(</span>replacement<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> + type<span class="Delimiter">-&gt;</span>value = replacement<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>replacement<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> type<span class="Delimiter">-&gt;</span>left = new string_tree<span class="Delimiter">(</span>*replacement<span class="Delimiter">-&gt;</span>left<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>replacement<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> type<span class="Delimiter">-&gt;</span>right = new string_tree<span class="Delimiter">(</span>*replacement<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + replace_type_ingredients<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> mappings<span class="Delimiter">);</span> + replace_type_ingredients<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> mappings<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void ensure_all_concrete_types<span class="Delimiter">(</span>const recipe&amp; new_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = new_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> + ensure_all_concrete_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> + ensure_all_concrete_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void ensure_all_concrete_types<span class="Delimiter">(</span>const type_tree* x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;null type</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">-&gt;</span>value == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise &lt;&lt; <span class="Constant">&quot;unknown type</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_2)</span> +recipe main [ + <span class="Constant">10</span>:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span> + <span class="Constant">11</span>:point<span class="Special"> &lt;- </span>foo <span class="Constant">10</span>:point +] +<span class="Comment"># non-matching shape-shifting variant</span> +recipe foo a:_t<span class="Delimiter">,</span> b:_t <span class="Delimiter">-&gt;</span> result:number [ + local-scope + load-ingredients + result<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +] +<span class="Comment"># matching shape-shifting variant</span> +recipe foo a:_t <span class="Delimiter">-&gt;</span> result:_t [ + local-scope + load-ingredients + result<span class="Special"> &lt;- </span>copy a +] +<span class="traceContains">+mem: storing 14 in location 11</span> +<span class="traceContains">+mem: storing 15 in location 12</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_nonroot)</span> +recipe main [ + <span class="Constant">10</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> + <span class="Constant">20</span>:point/<span class="Special">raw &lt;- </span>bar <span class="Constant">10</span>:foo:point +] +<span class="Comment"># shape-shifting recipe with type ingredient following some other type</span> +recipe bar a:foo:_t <span class="Delimiter">-&gt;</span> result:_t [ + local-scope + load-ingredients + result<span class="Special"> &lt;- </span>get a<span class="Delimiter">,</span> x:offset +] +container foo:_t [ + x:_t + y:number +] +<span class="traceContains">+mem: storing 14 in location 20</span> +<span class="traceContains">+mem: storing 15 in location 21</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_type_deduction_ignores_offsets)</span> +recipe main [ + <span class="Constant">10</span>:foo:point<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> + <span class="Constant">20</span>:point/<span class="Special">raw &lt;- </span>bar <span class="Constant">10</span>:foo:point +] +recipe bar a:foo:_t <span class="Delimiter">-&gt;</span> result:_t [ + local-scope + load-ingredients + x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> + result<span class="Special"> &lt;- </span>get a<span class="Delimiter">,</span> x:offset <span class="Comment"># shouldn't collide with other variable</span> +] +container foo:_t [ + x:_t + y:number +] +<span class="traceContains">+mem: storing 14 in location 20</span> +<span class="traceContains">+mem: storing 15 in location 21</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient)</span> +recipe main [ + <span class="Constant">1</span>:address:foo:point<span class="Special"> &lt;- </span>bar <span class="Constant">3</span> + <span class="Constant">11</span>:foo:point<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:foo:point +] +container foo:_t [ + x:_t + y:number +] +recipe bar x:number <span class="Delimiter">-&gt;</span> result:address:foo:_t [ + local-scope + load-ingredients + <span class="Comment"># new refers to _t in its ingredient *value*</span> + result<span class="Special"> &lt;- </span>new <span class="Delimiter">{(</span>foo _t<span class="Delimiter">)</span> : type<span class="Delimiter">}</span> +] +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="traceContains">+mem: storing 0 in location 12</span> +<span class="traceContains">+mem: storing 0 in location 13</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient_2)</span> +recipe main [ + <span class="Constant">1</span>:address:foo:point<span class="Special"> &lt;- </span>bar <span class="Constant">3</span> + <span class="Constant">11</span>:foo:point<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:foo:point +] +recipe bar x:number <span class="Delimiter">-&gt;</span> result:address:foo:_t [ + local-scope + load-ingredients + <span class="Comment"># new refers to _t in its ingredient *value*</span> + result<span class="Special"> &lt;- </span>new <span class="Delimiter">{(</span>foo _t<span class="Delimiter">)</span> : type<span class="Delimiter">}</span> +] +<span class="Comment"># container defined after use</span> +container foo:_t [ + x:_t + y:number +] +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="traceContains">+mem: storing 0 in location 12</span> +<span class="traceContains">+mem: storing 0 in location 13</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_supports_compound_types)</span> +recipe main [ + <span class="Constant">1</span>:address:point<span class="Special"> &lt;- </span>new point:type + <span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>get-address *<span class="Constant">1</span>:address:point<span class="Delimiter">,</span> y:offset + *<span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:address:point<span class="Special"> &lt;- </span>bar <span class="Constant">1</span>:address:point <span class="Comment"># specialize _t to address:point</span> + <span class="Constant">4</span>:point<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:point +] +recipe bar a:_t <span class="Delimiter">-&gt;</span> result:_t [ + local-scope + load-ingredients + result<span class="Special"> &lt;- </span>copy a +] +<span class="traceContains">+mem: storing 34 in location 5</span> + +<span class="Delimiter">:(scenario shape_shifting_recipe_error)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + a:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span> + b:address:number<span class="Special"> &lt;- </span>foo a +] +recipe foo a:_t <span class="Delimiter">-&gt;</span> b:_t [ + load-ingredients + b<span class="Special"> &lt;- </span>copy a +] +<span class="traceContains">+error: main: no call found for 'b:address:number &lt;- foo a'</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/060string.mu.html b/html/060string.mu.html index a5cf9f7a..ae7a3e01 100644 --- a/html/060string.mu.html +++ b/html/060string.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -447,7 +447,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> oldc:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> newc:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - from:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + from:number, _<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># default to 0</span> len:number<span class="Special"> &lt;- </span>length *s i:number<span class="Special"> &lt;- </span>find-next s, oldc, from done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len @@ -625,62 +625,60 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># most common case first</span> result:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span> - <span class="muControl">jump-if</span> result <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">9/tab</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">13/carriage-return</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result <span class="Comment"># remaining uncommon cases in sorted order</span> <span class="Comment"># <a href="http://unicode.org">http://unicode.org</a> code-points in unicode-set Z and Pattern_White_Space</span> result<span class="Special"> &lt;- </span>equal c, <span class="Constant">11/ctrl-k</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">12/ctrl-l</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">133/ctrl-0085</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">160/no-break-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">5760/ogham-space-mark</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8192/en-quad</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8193/em-quad</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8194/en-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8195/em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8196/three-per-em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8197/four-per-em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8198/six-per-em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8199/figure-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8200/punctuation-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8201/thin-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8202/hair-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8206/left-to-right</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8207/right-to-left</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8232/line-separator</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8233/paragraph-separator</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8239/narrow-no-break-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8287/medium-mathematical-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + <span class="muControl">reply-if</span> result, result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">12288/ideographic-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> -<span class="Constant"> +reply</span> <span class="muControl">reply</span> result ] diff --git a/html/061channel.mu.html b/html/061channel.mu.html index a52d34f3..47a11e0f 100644 --- a/html/061channel.mu.html +++ b/html/061channel.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } +.muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .muData { color: #ffff00; } .SalientComment { color: #00ffff; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -47,7 +47,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } run [ <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span> <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - <span class="Constant">2</span>:number, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel + <span class="Constant">2</span>:character, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">34</span> @@ -63,7 +63,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span> <span class="Comment"># including) index first-empty. The reader always modifies it at first-full,</span> <span class="Comment"># while the writer always modifies it at first-empty.</span> - data:address:array:location + data:address:array:character ] <span class="Comment"># result:address:channel &lt;- new-channel capacity:number</span> @@ -80,16 +80,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># result.data = new location[ingredient+1]</span> capacity:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> capacity<span class="Special"> &lt;- </span>add capacity, <span class="Constant">1</span> <span class="Comment"># unused slot for 'full?' below</span> - dest:address:address:array:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span> - *dest<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, capacity + dest:address:address:array:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span> + *dest<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, capacity <span class="muControl">reply</span> result ] -<span class="Comment"># chan &lt;- write chan:address:channel, val:location</span> +<span class="Comment"># chan &lt;- write chan:address:channel, val:character</span> <span class="muRecipe">recipe</span> write [ <span class="Constant">local-scope</span> chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - val:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + val:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="Comment"># block if chan is full</span> full:boolean<span class="Special"> &lt;- </span>channel-full? chan @@ -98,9 +98,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } wait-for-location *full-address <span class="Delimiter">}</span> <span class="Comment"># store val</span> - circular-buffer:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span> + circular-buffer:address:array:character<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span> free:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-free:offset</span> - dest:address:location<span class="Special"> &lt;- </span>index-address *circular-buffer, *free + dest:address:character<span class="Special"> &lt;- </span>index-address *circular-buffer, *free *dest<span class="Special"> &lt;- </span>copy val <span class="Comment"># mark its slot as filled</span> *free<span class="Special"> &lt;- </span>add *free, <span class="Constant">1</span> @@ -114,7 +114,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span> ] -<span class="Comment"># result:location, chan &lt;- read chan:address:channel</span> +<span class="Comment"># result:character, chan &lt;- read chan:address:channel</span> <span class="muRecipe">recipe</span> read [ <span class="Constant">local-scope</span> chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> @@ -127,8 +127,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> <span class="Comment"># read result</span> full:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-full:offset</span> - circular-buffer:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span> - result:location<span class="Special"> &lt;- </span>index *circular-buffer, *full + circular-buffer:address:array:character<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span> + result:character<span class="Special"> &lt;- </span>index *circular-buffer, *full <span class="Comment"># mark its slot as empty</span> *full<span class="Special"> &lt;- </span>add *full, <span class="Constant">1</span> <span class="Delimiter">{</span> @@ -254,7 +254,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> channel-capacity [ <span class="Constant">local-scope</span> chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - q:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span> + q:address:array:character<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span> result:number<span class="Special"> &lt;- </span>length *q <span class="muControl">reply</span> result ] diff --git a/html/062array.mu.html b/html/062array.mu.html index b65da102..4f800098 100644 --- a/html/062array.mu.html +++ b/html/062array.mu.html @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } +.muScenario { color: #00af00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -33,8 +33,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="muScenario">scenario</span> array-from-args [ run [ - <span class="Constant">1</span>:address:array:location<span class="Special"> &lt;- </span>new-array <span class="Constant">0</span>, <span class="Constant">1</span>, <span class="Constant">2</span> - <span class="Constant">2</span>:array:location<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:array:location + <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new-array <span class="Constant">0</span>, <span class="Constant">1</span>, <span class="Constant">2</span> + <span class="Constant">2</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:array:character ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">3</span> <span class="Comment"># array length</span> @@ -50,21 +50,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } capacity:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while read curr-value</span> - curr-value:location, exists?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + curr-value:character, exists?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="muControl">break-unless</span> exists? capacity<span class="Special"> &lt;- </span>add capacity, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - result:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, capacity + result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, capacity rewind-ingredients i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while read curr-value</span> done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, capacity <span class="muControl">break-if</span> done? - curr-value:location, exists?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + curr-value:character, exists?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> assert exists?, <span class="Constant">[error in rewinding ingredients to new-array]</span> - tmp:address:location<span class="Special"> &lt;- </span>index-address *result, i + tmp:address:character<span class="Special"> &lt;- </span>index-address *result, i *tmp<span class="Special"> &lt;- </span>copy curr-value i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> diff --git a/html/063list.mu.html b/html/063list.mu.html index a4c4e02e..a3122c41 100644 --- a/html/063list.mu.html +++ b/html/063list.mu.html @@ -13,13 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } -.muControl { color: #c0a020; } +.Delimiter { color: #a04060; } --> </style> @@ -33,55 +34,58 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <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"># Try to make all objects in a single list of the same type, it'll help avoid bugs.</span> -<span class="Comment"># If you want to store multiple types in a single list, use an exclusive-container.</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 [ - value:location - next:address:list +<span class="muData">container</span> list:_elem [ + value:_elem + next:address:list:_elem ] -<span class="Comment"># result:address:list &lt;- push x:location, in:address:list</span> -<span class="muRecipe">recipe</span> push [ +<span class="muRecipe">recipe</span> push x:_elem, in:address:list:_elem<span class="muRecipe"> -&gt; </span>result:address:list:_elem [ <span class="Constant">local-scope</span> - x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - result:address:list<span class="Special"> &lt;- </span>new <span class="Constant">list:type</span> - val:address:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">value:offset</span> + <span class="Constant">load-ingredients</span> + result<span class="Special"> &lt;- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> + val:address:_elem<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">value:offset</span> *val<span class="Special"> &lt;- </span>copy x - next:address:address:list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">next:offset</span> + next:address:address:list:_elem<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">next:offset</span> *next<span class="Special"> &lt;- </span>copy in <span class="muControl">reply</span> result ] -<span class="Comment"># result:location &lt;- first in:address:list</span> -<span class="muRecipe">recipe</span> first [ +<span class="muRecipe">recipe</span> first in:address:list:_elem<span class="muRecipe"> -&gt; </span>result:_elem [ <span class="Constant">local-scope</span> - in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - result:location<span class="Special"> &lt;- </span>get *in, <span class="Constant">value:offset</span> - <span class="muControl">reply</span> result + <span class="Constant">load-ingredients</span> + result<span class="Special"> &lt;- </span>get *in, <span class="Constant">value:offset</span> ] <span class="Comment"># result:address:list &lt;- rest in:address:list</span> -<span class="muRecipe">recipe</span> rest [ +<span class="muRecipe">recipe</span> rest in:address:list:_elem<span class="muRecipe"> -&gt; </span>result:address:list:_elem [ <span class="Constant">local-scope</span> - in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - result:address:list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> - <span class="muControl">reply</span> result + <span class="Constant">load-ingredients</span> + result<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> +] + +<span class="muRecipe">recipe</span> force-specialization-list-number [ + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>push <span class="Constant">2</span>:number, <span class="Constant">1</span>:address:list:number + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list:number ] +<span class="Comment"># todo: automatically specialize code in scenarios</span> <span class="muScenario">scenario</span> list-handling [ run [ - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>push <span class="Constant">3</span>, <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:list - <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span> + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>push <span class="Constant">2</span>:number, <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:list:number + <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list:number + <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list:number + <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list:number ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># empty to empty, dust to dust..</span> diff --git a/html/064random.cc.html b/html/064random.cc.html index e8a75626..bd176af3 100644 --- a/html/064random.cc.html +++ b/html/064random.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .PreProc { color: #c000c0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -35,7 +35,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> RANDOM<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;random&quot;</span>] = RANDOM<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;random&quot;</span><span class="Delimiter">,</span> RANDOM<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case RANDOM: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case RANDOM: <span class="Delimiter">{</span> <span class="Comment">// todo: limited range of numbers, might be imperfectly random</span> @@ -48,7 +52,11 @@ case RANDOM: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MAKE_RANDOM_NONDETERMINISTIC<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;make-random-nondeterministic&quot;</span>] = MAKE_RANDOM_NONDETERMINISTIC<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;make-random-nondeterministic&quot;</span><span class="Delimiter">,</span> MAKE_RANDOM_NONDETERMINISTIC<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MAKE_RANDOM_NONDETERMINISTIC: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MAKE_RANDOM_NONDETERMINISTIC: <span class="Delimiter">{</span> srand<span class="Delimiter">(</span>time<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">));</span> @@ -58,17 +66,21 @@ case MAKE_RANDOM_NONDETERMINISTIC: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> ROUND<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;round&quot;</span>] = ROUND<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;round&quot;</span><span class="Delimiter">,</span> ROUND<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case ROUND: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'round' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'round' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'round' should be a number, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'round' should be a number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case ROUND: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>rint<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> diff --git a/html/065duplex_list.mu.html b/html/065duplex_list.mu.html index bf7634a0..4a9437ce 100644 --- a/html/065duplex_list.mu.html +++ b/html/065duplex_list.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -34,52 +34,44 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># A doubly linked list permits bidirectional traversal.</span> -<span class="muData">container</span> duplex-list [ - value:location - next:address:duplex-list - prev:address:duplex-list +<span class="muData">container</span> duplex-list:_elem [ + value:_elem + next:address:duplex-list:_elem + prev:address:duplex-list:_elem ] -<span class="Comment"># result:address:duplex-list &lt;- push-duplex x:location, in:address:duplex-list</span> -<span class="muRecipe">recipe</span> push-duplex [ +<span class="muRecipe">recipe</span> push-duplex x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>result:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - result:address:duplex-list<span class="Special"> &lt;- </span>new <span class="Constant">duplex-list:type</span> - val:address:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">value:offset</span> + <span class="Constant">load-ingredients</span> + result<span class="Special"> &lt;- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> + val:address:_elem<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">value:offset</span> *val<span class="Special"> &lt;- </span>copy x - next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">next:offset</span> + next:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">next:offset</span> *next<span class="Special"> &lt;- </span>copy in - <span class="muControl">reply-unless</span> in, result - prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">prev:offset</span> + <span class="muControl">reply-unless</span> in + prev:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">prev:offset</span> *prev<span class="Special"> &lt;- </span>copy result - <span class="muControl">reply</span> result ] -<span class="Comment"># result:location &lt;- first-duplex in:address:duplex-list</span> -<span class="muRecipe">recipe</span> first-duplex [ +<span class="muRecipe">recipe</span> first-duplex in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>result:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> - result:location<span class="Special"> &lt;- </span>get *in, <span class="Constant">value:offset</span> - <span class="muControl">reply</span> result + result<span class="Special"> &lt;- </span>get *in, <span class="Constant">value:offset</span> ] -<span class="Comment"># result:address:duplex-list &lt;- next-duplex in:address:duplex-list</span> -<span class="muRecipe">recipe</span> next-duplex [ +<span class="muRecipe">recipe</span> next-duplex in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>result:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> - result:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> - <span class="muControl">reply</span> result + result<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> ] -<span class="Comment"># result:address:duplex-list &lt;- prev-duplex in:address:duplex-list</span> -<span class="muRecipe">recipe</span> prev-duplex [ +<span class="muRecipe">recipe</span> prev-duplex in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>result:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> - result:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">prev:offset</span> + result<span class="Special"> &lt;- </span>get *in, <span class="Constant">prev:offset</span> <span class="muControl">reply</span> result ] @@ -88,25 +80,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># reserve locations 0, 1 and 2 to check for missing null check</span> <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">3</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">3</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">3</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">8</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">8</span>:address:duplex-list - <span class="Constant">10</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">8</span>:address:duplex-list - <span class="Constant">11</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">8</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">14</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:address:duplex-list, <span class="Constant">4</span>:address:duplex-list + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">8</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">8</span>:address:duplex-list:character + <span class="Constant">10</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">8</span>:address:duplex-list:character + <span class="Constant">11</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">8</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">12</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">13</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">14</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:address:duplex-list:character, <span class="Constant">4</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">0</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># no modifications to null pointers</span> @@ -125,18 +117,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># l:address:duplex-list &lt;- insert-duplex x:location, in:address:duplex-list</span> <span class="Comment"># Inserts 'x' after 'in'. Returns some pointer into the list.</span> -<span class="muRecipe">recipe</span> insert-duplex [ +<span class="muRecipe">recipe</span> insert-duplex x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>new-node:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - new-node:address:duplex-list<span class="Special"> &lt;- </span>new <span class="Constant">duplex-list:type</span> - val:address:location<span class="Special"> &lt;- </span>get-address *new-node, <span class="Constant">value:offset</span> + <span class="Constant">load-ingredients</span> + new-node<span class="Special"> &lt;- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> + val:address:_elem<span class="Special"> &lt;- </span>get-address *new-node, <span class="Constant">value:offset</span> *val<span class="Special"> &lt;- </span>copy x - next-node:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> + next-node:address:duplex-list:_elem<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> <span class="Comment"># in.next = new-node</span> - y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span> + y:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span> *y<span class="Special"> &lt;- </span>copy new-node <span class="Comment"># new-node.prev = in</span> y<span class="Special"> &lt;- </span>get-address *new-node, <span class="Constant">prev:offset</span> @@ -154,28 +144,28 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> inserting-into-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list <span class="Comment"># 2 points inside list</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># 2 points inside list</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> @@ -191,29 +181,29 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> inserting-at-end-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list <span class="Comment"># 2 points inside list</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list <span class="Comment"># now at end of list</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># 2 points inside list</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character <span class="Comment"># now at end of list</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> @@ -229,27 +219,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> inserting-after-start-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> @@ -263,21 +253,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># l:address:duplex-list &lt;- remove-duplex in:address:duplex-list</span> <span class="Comment"># Removes 'in' from its surrounding list. Returns some valid pointer into the</span> <span class="Comment"># rest of the list.</span> <span class="Comment">#</span> <span class="Comment"># Returns null if and only if list is empty. Beware: in that case any pointers</span> <span class="Comment"># to the head are now invalid.</span> -<span class="muRecipe">recipe</span> remove-duplex [ +<span class="muRecipe">recipe</span> remove-duplex in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>next-node:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># if 'in' is null, return</span> <span class="muControl">reply-unless</span> in, in - next-node:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> - prev-node:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">prev:offset</span> + next-node:address:duplex-list:_elem<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span> + prev-node:address:duplex-list:_elem<span class="Special"> &lt;- </span>get *in, <span class="Constant">prev:offset</span> <span class="Comment"># null in's pointers</span> - x:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span> + x:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span> *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> x<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">prev:offset</span> *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> @@ -301,22 +290,22 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> removing-from-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list <span class="Comment"># 2 points at second element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># 2 points at second element</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">0</span> <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># remove returned non-null</span> @@ -330,21 +319,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> removing-from-start-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># removing from head? return value matters.</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># scanning next, skipping deleted element</span> @@ -357,24 +346,24 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> removing-from-end-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># delete last element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">0</span> <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># remove returned non-null</span> @@ -388,11 +377,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> removing-from-singleton-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">next:offset</span> - <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">prev:offset</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">next:offset</span> + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">prev:offset</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># remove returned null</span> @@ -405,51 +394,49 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># Remove values between 'start' and 'end' (both exclusive). Returns some valid</span> <span class="Comment"># pointer into the rest of the list.</span> <span class="Comment"># Also clear pointers back out from start/end for hygiene.</span> -<span class="muRecipe">recipe</span> remove-duplex-between [ +<span class="muRecipe">recipe</span> remove-duplex-between start:address:duplex-list:_elem, end:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>start:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - end:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> start, start + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> start <span class="Comment"># start-&gt;next-&gt;prev = 0</span> <span class="Comment"># start-&gt;next = end</span> - next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">next:offset</span> + next:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">next:offset</span> nothing-to-delete?:boolean<span class="Special"> &lt;- </span>equal *next, end - <span class="muControl">reply-if</span> nothing-to-delete?, start - prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address **next, <span class="Constant">prev:offset</span> + <span class="muControl">reply-if</span> nothing-to-delete? + prev:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address **next, <span class="Constant">prev:offset</span> *prev<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> *next<span class="Special"> &lt;- </span>copy end - <span class="muControl">reply-unless</span> end, start + <span class="muControl">reply-unless</span> end <span class="Comment"># end-&gt;prev-&gt;next = 0</span> <span class="Comment"># end-&gt;prev = start</span> prev<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">prev:offset</span> next<span class="Special"> &lt;- </span>get-address **prev, <span class="Constant">next:offset</span> *next<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> *prev<span class="Special"> &lt;- </span>copy start - <span class="muControl">reply</span> start ] <span class="muScenario">scenario</span> remove-range [ <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">18</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">17</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">16</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">15</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">18</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">17</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">16</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">15</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list:character run [ <span class="Comment"># delete 16 onwards</span> <span class="Comment"># first pointer: to the third element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - remove-duplex-between <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex-between <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">0</span> <span class="Comment"># now check the list</span> - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">7</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">7</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">9</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">7</span>:address:duplex-list + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">5</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">7</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">7</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">9</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">7</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">13</span> @@ -461,30 +448,30 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> remove-range-to-end [ <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">18</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">17</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">16</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">15</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">18</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">17</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">16</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">15</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list:character run [ <span class="Comment"># delete 15, 16 and 17</span> <span class="Comment"># first pointer: to the third element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># second pointer: to the fifth element</span> - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list - remove-duplex-between <span class="Constant">2</span>:address:duplex-list, <span class="Constant">3</span>:address:duplex-list + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list:character + remove-duplex-between <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">3</span>:address:duplex-list:character <span class="Comment"># now check the list</span> - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">7</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">7</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">9</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">7</span>:address:duplex-list + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">5</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">7</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">7</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">9</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">7</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">13</span> @@ -496,19 +483,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> remove-range-empty [ <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list:character run [ <span class="Comment"># delete 16 onwards</span> <span class="Comment"># first pointer: to the third element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - remove-duplex-between <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + remove-duplex-between <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">2</span>:address:duplex-list:character <span class="Comment"># now check the list</span> - <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list, <span class="Constant">value:offset</span> - <span class="Constant">7</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list + <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">5</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list:character, <span class="Constant">value:offset</span> + <span class="Constant">7</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">13</span> @@ -517,23 +504,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># l:address:duplex-list &lt;- insert-duplex-range in:address:duplex-list, new:address:duplex-list</span> <span class="Comment"># Inserts list beginning at 'new' after 'in'. Returns some pointer into the list.</span> -<span class="muRecipe">recipe</span> insert-duplex-range [ +<span class="muRecipe">recipe</span> insert-duplex-range in:address:duplex-list:_elem, start:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> in, in - <span class="muControl">reply-unless</span> start, in - end:address:duplex-list<span class="Special"> &lt;- </span>copy start + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> in + <span class="muControl">reply-unless</span> start + end:address:duplex-list:_elem<span class="Special"> &lt;- </span>copy start <span class="Delimiter">{</span> - next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex end + next:address:duplex-list:_elem<span class="Special"> &lt;- </span>next-duplex end/insert-range <span class="muControl">break-unless</span> next end<span class="Special"> &lt;- </span>copy next <span class="muControl">loop</span> <span class="Delimiter">}</span> - next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex in - dest:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">next:offset</span> + next:address:duplex-list:_elem<span class="Special"> &lt;- </span>next-duplex in + dest:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">next:offset</span> *dest<span class="Special"> &lt;- </span>copy next <span class="Delimiter">{</span> <span class="muControl">break-unless</span> next @@ -544,43 +529,39 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *dest<span class="Special"> &lt;- </span>copy start dest<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">prev:offset</span> *dest<span class="Special"> &lt;- </span>copy in - <span class="muControl">reply</span> in ] -<span class="muRecipe">recipe</span> append-duplex [ +<span class="muRecipe">recipe</span> append-duplex in:address:duplex-list:_elem, new:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - new:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - last:address:duplex-list<span class="Special"> &lt;- </span>last-duplex in - dest:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *last, <span class="Constant">next:offset</span> + <span class="Constant">load-ingredients</span> + last:address:duplex-list:_elem<span class="Special"> &lt;- </span>last-duplex in + dest:address:address:duplex-list:_elem<span class="Special"> &lt;- </span>get-address *last, <span class="Constant">next:offset</span> *dest<span class="Special"> &lt;- </span>copy new - <span class="muControl">reply-unless</span> new, in/same-as-ingredient:<span class="Constant">0</span> + <span class="muControl">reply-unless</span> new dest<span class="Special"> &lt;- </span>get-address *new, <span class="Constant">prev:offset</span> *dest<span class="Special"> &lt;- </span>copy last - <span class="muControl">reply</span> in/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> last-duplex [ +<span class="muRecipe">recipe</span> last-duplex in:address:duplex-list:_elem<span class="muRecipe"> -&gt; </span>result:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - result:address:duplex-list<span class="Special"> &lt;- </span>copy in + <span class="Constant">load-ingredients</span> + result<span class="Special"> &lt;- </span>copy in <span class="Delimiter">{</span> - next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex result + next:address:duplex-list:_elem<span class="Special"> &lt;- </span>next-duplex result <span class="muControl">break-unless</span> next result<span class="Special"> &lt;- </span>copy next <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> result ] <span class="Comment"># helper for debugging</span> -<span class="muRecipe">recipe</span> dump-duplex-from [ +<span class="muRecipe">recipe</span> dump-duplex-from x:address:duplex-list:_elem [ <span class="Constant">local-scope</span> - x:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> $print x, <span class="Constant">[: ]</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> x - c:character<span class="Special"> &lt;- </span>get *x, <span class="Constant">value:offset</span> + c:_elem<span class="Special"> &lt;- </span>get *x, <span class="Constant">value:offset</span> $print c, <span class="Constant">[ ]</span> x<span class="Special"> &lt;- </span>next-duplex x <span class="Delimiter">{</span> @@ -593,6 +574,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> $print <span class="Constant">10/newline</span>, <span class="Constant">[---]</span>, <span class="Constant">10/newline</span> ] + +<span class="muRecipe">recipe</span> force-specialization-duplex-list-character [ + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>push-duplex <span class="Constant">2</span>:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:character<span class="Special"> &lt;- </span>first-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">2</span>:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>remove-duplex-between <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>insert-duplex-range <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>append-duplex <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> &lt;- </span>last-duplex <span class="Constant">1</span>:address:duplex-list:character +] </pre> </body> </html> diff --git a/html/066stream.mu.html b/html/066stream.mu.html index 23a019f6..54e65159 100644 --- a/html/066stream.mu.html +++ b/html/066stream.mu.html @@ -13,12 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } -.muControl { color: #c0a020; } --> </style> @@ -68,7 +68,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> end-of-stream? [ <span class="Constant">local-scope</span> in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - idx:address:number<span class="Special"> &lt;- </span>get *in, <span class="Constant">index:offset</span> + idx:number<span class="Special"> &lt;- </span>get *in, <span class="Constant">index:offset</span> s:address:array:character<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span> len:number<span class="Special"> &lt;- </span>length *s result:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len diff --git a/html/070display.cc.html b/html/070display.cc.html index 61a6395e..8fb46c4d 100644 --- a/html/070display.cc.html +++ b/html/070display.cc.html @@ -41,7 +41,11 @@ bool Autodisplay = <span class="Constant">true</span><span class="Delimiter">;</ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> OPEN_CONSOLE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;open-console&quot;</span>] = OPEN_CONSOLE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;open-console&quot;</span><span class="Delimiter">,</span> OPEN_CONSOLE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case OPEN_CONSOLE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case OPEN_CONSOLE: <span class="Delimiter">{</span> tb_init<span class="Delimiter">();</span> @@ -50,16 +54,20 @@ case OPEN_CONSOLE: <span class="Delimiter">{</span> long long int height = tb_height<span class="Delimiter">();</span> if <span class="Delimiter">(</span>width &gt; <span class="Constant">222</span> || height &gt; <span class="Constant">222</span><span class="Delimiter">)</span> tb_shutdown<span class="Delimiter">();</span> if <span class="Delimiter">(</span>width &gt; <span class="Constant">222</span><span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;sorry, mu doesn't support windows wider than 222 characters. Please resize your window.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;sorry, mu doesn't support windows wider than 222 characters. Please resize your window.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>height &gt; <span class="Constant">222</span><span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;sorry, mu doesn't support windows taller than 222 characters. Please resize your window.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;sorry, mu doesn't support windows taller than 222 characters. Please resize your window.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CLOSE_CONSOLE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;close-console&quot;</span>] = CLOSE_CONSOLE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;close-console&quot;</span><span class="Delimiter">,</span> CLOSE_CONSOLE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case CLOSE_CONSOLE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case CLOSE_CONSOLE: <span class="Delimiter">{</span> tb_shutdown<span class="Delimiter">();</span> @@ -72,7 +80,11 @@ tb_shutdown<span class="Delimiter">();</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CLEAR_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;clear-display&quot;</span>] = CLEAR_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;clear-display&quot;</span><span class="Delimiter">,</span> CLEAR_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case CLEAR_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case CLEAR_DISPLAY: <span class="Delimiter">{</span> tb_clear<span class="Delimiter">();</span> @@ -83,7 +95,11 @@ case CLEAR_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SYNC_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;sync-display&quot;</span>] = SYNC_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;sync-display&quot;</span><span class="Delimiter">,</span> SYNC_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SYNC_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case SYNC_DISPLAY: <span class="Delimiter">{</span> tb_sync<span class="Delimiter">();</span> @@ -93,7 +109,11 @@ case SYNC_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CLEAR_LINE_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;clear-line-on-display&quot;</span>] = CLEAR_LINE_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;clear-line-on-display&quot;</span><span class="Delimiter">,</span> CLEAR_LINE_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case CLEAR_LINE_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case CLEAR_LINE_ON_DISPLAY: <span class="Delimiter">{</span> long long int width = tb_width<span class="Delimiter">();</span> @@ -108,35 +128,43 @@ case CLEAR_LINE_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> PRINT_CHARACTER_TO_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;print-character-to-display&quot;</span>] = PRINT_CHARACTER_TO_DISPLAY<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;print-character-to-display&quot;</span><span class="Delimiter">,</span> PRINT_CHARACTER_TO_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span> - int h=tb_height<span class="Delimiter">(),</span> w=tb_width<span class="Delimiter">();</span> - long long int height = <span class="Delimiter">(</span>h &gt;= <span class="Constant">0</span><span class="Delimiter">)</span> ? h : <span class="Constant">0</span><span class="Delimiter">;</span> - long long int width = <span class="Delimiter">(</span>w &gt;= <span class="Constant">0</span><span class="Delimiter">)</span> ? w : <span class="Constant">0</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'print-character-to-display' requires at least one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'print-character-to-display' requires at least one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'print-character-to-display' should be a character, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'print-character-to-display' should be a character, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'print-character-to-display' should be a foreground color number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;third ingredient of 'print-character-to-display' should be a background color number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span> + int h=tb_height<span class="Delimiter">(),</span> w=tb_width<span class="Delimiter">();</span> + long long int height = <span class="Delimiter">(</span>h &gt;= <span class="Constant">0</span><span class="Delimiter">)</span> ? h : <span class="Constant">0</span><span class="Delimiter">;</span> + long long int width = <span class="Delimiter">(</span>w &gt;= <span class="Constant">0</span><span class="Delimiter">)</span> ? w : <span class="Constant">0</span><span class="Delimiter">;</span> long long int c = 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> int color = TB_BLACK<span class="Delimiter">;</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'print-character-to-display' should be a foreground color number, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> color = 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> int bg_color = TB_BLACK<span class="Delimiter">;</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: third ingredient of 'print-character-to-display' should be a background color number, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> bg_color = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> if <span class="Delimiter">(</span>bg_color == <span class="Constant">0</span><span class="Delimiter">)</span> bg_color = TB_BLACK<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -170,7 +198,11 @@ case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CURSOR_POSITION_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;cursor-position-on-display&quot;</span>] = CURSOR_POSITION_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;cursor-position-on-display&quot;</span><span class="Delimiter">,</span> CURSOR_POSITION_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case CURSOR_POSITION_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case CURSOR_POSITION_ON_DISPLAY: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> @@ -182,22 +214,26 @@ case CURSOR_POSITION_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MOVE_CURSOR_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;move-cursor-on-display&quot;</span>] = MOVE_CURSOR_ON_DISPLAY<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;move-cursor-on-display&quot;</span><span class="Delimiter">,</span> MOVE_CURSOR_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case MOVE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'move-cursor-on-display' requires two ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'move-cursor-on-display' requires two ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'move-cursor-on-display' should be a row number, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'move-cursor-on-display' should be a row number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - Display_row = 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> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'move-cursor-on-display' should be a column number, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'move-cursor-on-display' should be a column number, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case MOVE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> + Display_row = 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> Display_column = 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> tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span> @@ -207,7 +243,11 @@ case MOVE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MOVE_CURSOR_DOWN_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;move-cursor-down-on-display&quot;</span>] = MOVE_CURSOR_DOWN_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;move-cursor-down-on-display&quot;</span><span class="Delimiter">,</span> MOVE_CURSOR_DOWN_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MOVE_CURSOR_DOWN_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MOVE_CURSOR_DOWN_ON_DISPLAY: <span class="Delimiter">{</span> int h=tb_height<span class="Delimiter">();</span> @@ -223,7 +263,11 @@ case MOVE_CURSOR_DOWN_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MOVE_CURSOR_UP_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;move-cursor-up-on-display&quot;</span>] = MOVE_CURSOR_UP_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;move-cursor-up-on-display&quot;</span><span class="Delimiter">,</span> MOVE_CURSOR_UP_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MOVE_CURSOR_UP_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MOVE_CURSOR_UP_ON_DISPLAY: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Display_row &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -237,7 +281,11 @@ case MOVE_CURSOR_UP_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MOVE_CURSOR_RIGHT_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;move-cursor-right-on-display&quot;</span>] = MOVE_CURSOR_RIGHT_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;move-cursor-right-on-display&quot;</span><span class="Delimiter">,</span> MOVE_CURSOR_RIGHT_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MOVE_CURSOR_RIGHT_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MOVE_CURSOR_RIGHT_ON_DISPLAY: <span class="Delimiter">{</span> int w=tb_width<span class="Delimiter">();</span> @@ -253,7 +301,11 @@ case MOVE_CURSOR_RIGHT_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> MOVE_CURSOR_LEFT_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;move-cursor-left-on-display&quot;</span>] = MOVE_CURSOR_LEFT_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;move-cursor-left-on-display&quot;</span><span class="Delimiter">,</span> MOVE_CURSOR_LEFT_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case MOVE_CURSOR_LEFT_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case MOVE_CURSOR_LEFT_ON_DISPLAY: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Display_column &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -267,7 +319,11 @@ case MOVE_CURSOR_LEFT_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> DISPLAY_WIDTH<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;display-width&quot;</span>] = DISPLAY_WIDTH<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;display-width&quot;</span><span class="Delimiter">,</span> DISPLAY_WIDTH<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case DISPLAY_WIDTH: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case DISPLAY_WIDTH: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -278,7 +334,11 @@ case DISPLAY_WIDTH: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> DISPLAY_HEIGHT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;display-height&quot;</span>] = DISPLAY_HEIGHT<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;display-height&quot;</span><span class="Delimiter">,</span> DISPLAY_HEIGHT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case DISPLAY_HEIGHT: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case DISPLAY_HEIGHT: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -289,7 +349,11 @@ case DISPLAY_HEIGHT: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> HIDE_CURSOR_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;hide-cursor-on-display&quot;</span>] = HIDE_CURSOR_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;hide-cursor-on-display&quot;</span><span class="Delimiter">,</span> HIDE_CURSOR_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case HIDE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case HIDE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> tb_set_cursor<span class="Delimiter">(</span>TB_HIDE_CURSOR<span class="Delimiter">,</span> TB_HIDE_CURSOR<span class="Delimiter">);</span> @@ -299,7 +363,11 @@ case HIDE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SHOW_CURSOR_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;show-cursor-on-display&quot;</span>] = SHOW_CURSOR_ON_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;show-cursor-on-display&quot;</span><span class="Delimiter">,</span> SHOW_CURSOR_ON_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SHOW_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case SHOW_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> tb_set_cursor<span class="Delimiter">(</span>Display_row<span class="Delimiter">,</span> Display_column<span class="Delimiter">);</span> @@ -309,7 +377,11 @@ case SHOW_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> HIDE_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;hide-display&quot;</span>] = HIDE_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;hide-display&quot;</span><span class="Delimiter">,</span> HIDE_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case HIDE_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case HIDE_DISPLAY: <span class="Delimiter">{</span> Autodisplay = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -319,7 +391,11 @@ case HIDE_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SHOW_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;show-display&quot;</span>] = SHOW_DISPLAY<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;show-display&quot;</span><span class="Delimiter">,</span> SHOW_DISPLAY<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SHOW_DISPLAY: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case SHOW_DISPLAY: <span class="Delimiter">{</span> Autodisplay = <span class="Constant">true</span><span class="Delimiter">;</span> @@ -332,7 +408,11 @@ case SHOW_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> WAIT_FOR_SOME_INTERACTION<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;wait-for-some-interaction&quot;</span>] = WAIT_FOR_SOME_INTERACTION<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;wait-for-some-interaction&quot;</span><span class="Delimiter">,</span> WAIT_FOR_SOME_INTERACTION<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case WAIT_FOR_SOME_INTERACTION: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case WAIT_FOR_SOME_INTERACTION: <span class="Delimiter">{</span> tb_event event<span class="Delimiter">;</span> @@ -343,7 +423,11 @@ case WAIT_FOR_SOME_INTERACTION: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CHECK_FOR_INTERACTION<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;check-for-interaction&quot;</span>] = CHECK_FOR_INTERACTION<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;check-for-interaction&quot;</span><span class="Delimiter">,</span> CHECK_FOR_INTERACTION<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case CHECK_FOR_INTERACTION: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case CHECK_FOR_INTERACTION: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">// result and status</span> @@ -406,7 +490,11 @@ case CHECK_FOR_INTERACTION: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> INTERACTIONS_LEFT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;interactions-left?&quot;</span>] = INTERACTIONS_LEFT<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;interactions-left?&quot;</span><span class="Delimiter">,</span> INTERACTIONS_LEFT<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case INTERACTIONS_LEFT: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case INTERACTIONS_LEFT: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -419,7 +507,11 @@ case INTERACTIONS_LEFT: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> CLEAR_DISPLAY_FROM<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;clear-display-from&quot;</span>] = CLEAR_DISPLAY_FROM<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;clear-display-from&quot;</span><span class="Delimiter">,</span> CLEAR_DISPLAY_FROM<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case CLEAR_DISPLAY_FROM: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case CLEAR_DISPLAY_FROM: <span class="Delimiter">{</span> <span class="Comment">// todo: error checking</span> diff --git a/html/071print.mu.html b/html/071print.mu.html index c4334f55..444a8359 100644 --- a/html/071print.mu.html +++ b/html/071print.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -81,8 +81,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-if</span> done? curr:address:screen-cell<span class="Special"> &lt;- </span>index-address *buf, i curr-content:address:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">contents:offset</span> - *curr-content<span class="Special"> &lt;- </span>copy <span class="Constant">[ ]</span> - curr-color:address:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">color:offset</span> + *curr-content<span class="Special"> &lt;- </span>copy <span class="Constant">0/empty</span> + curr-color:address:number<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">color:offset</span> *curr-color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span> i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -558,7 +558,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> cursor-to-next-line [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> screen<span class="Special"> &lt;- </span>cursor-down screen screen<span class="Special"> &lt;- </span>cursor-to-start-of-line screen <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> @@ -594,7 +594,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> hide-cursor [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># if x exists (not real display), do nothing</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen @@ -607,7 +607,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> show-cursor [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># if x exists (not real display), do nothing</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen @@ -620,7 +620,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> hide-screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># if x exists (not real display), do nothing</span> <span class="Comment"># todo: help test this</span> <span class="Delimiter">{</span> @@ -634,7 +634,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> show-screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># if x exists (not real display), do nothing</span> <span class="Comment"># todo: help test this</span> <span class="Delimiter">{</span> @@ -648,7 +648,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> print-string [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> @@ -697,7 +697,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> print-integer [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> diff --git a/html/072scenario_screen.cc.html b/html/072scenario_screen.cc.html index 5100c44c..ade20fff 100644 --- a/html/072scenario_screen.cc.html +++ b/html/072scenario_screen.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.traceAbsent { color: #c00000; } .traceContains { color: #008000; } +.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -43,7 +43,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario screen-in-scenario [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span> <span class="Comment"># 'a'</span> + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">97</span> <span class="Comment"># 'a'</span> ] screen-should-contain [ <span class="Comment"># 01234</span> @@ -57,8 +57,8 @@ scenario screen-in-scenario [ scenario screen-in-scenario-unicode-color [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">955</span>/greek-small-lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>/a + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">955</span>/greek-small-lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">97</span>/a ] screen-should-contain [ <span class="Comment"># 01234</span> @@ -73,8 +73,8 @@ scenario screen-in-scenario-unicode-color [ scenario screen-in-scenario-color [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">955</span>/greek-small-lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">7</span>/white + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">955</span>/greek-small-lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">7</span>/white ] <span class="Comment"># screen-should-contain shows everything</span> screen-should-contain [ @@ -102,11 +102,11 @@ scenario screen-in-scenario-color [ <span class="Delimiter">:(scenario screen_in_scenario_error)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> scenario screen-in-scenario-error [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span> <span class="Comment"># 'a'</span> + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">97</span> <span class="Comment"># 'a'</span> ] screen-should-contain [ <span class="Comment"># 01234</span> @@ -115,16 +115,16 @@ scenario screen-in-scenario-error [ <span class="Delimiter">.</span> <span class="Delimiter">.</span> ] ] -<span class="traceContains">+warn: expected screen location (0, 0) to contain 98 ('b') instead of 97 ('a')</span> +<span class="traceContains">+error: expected screen location (0, 0) to contain 98 ('b') instead of 97 ('a')</span> <span class="Delimiter">:(scenario screen_in_scenario_color_error)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> <span class="Comment"># screen-should-contain can check unicode characters in the fake screen</span> scenario screen-in-scenario-color [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ - screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">1</span>/red + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen<span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">1</span>/red ] screen-should-contain-in-color <span class="Constant">2</span>/green<span class="Delimiter">,</span> [ <span class="Comment"># 01234</span> @@ -133,21 +133,21 @@ scenario screen-in-scenario-color [ <span class="Delimiter">.</span> <span class="Delimiter">.</span> ] ] -<span class="traceContains">+warn: expected screen location (0, 0) to be in color 2 instead of 1</span> +<span class="traceContains">+error: expected screen location (0, 0) to be in color 2 instead of 1</span> <span class="Comment">//: allow naming just for 'screen'</span> <span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span> if <span class="Delimiter">(</span>s == <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">:(scenarios run)</span> -<span class="Delimiter">:(scenario convert_names_does_not_warn_when_mixing_special_names_and_numeric_locations)</span> +<span class="Delimiter">:(scenario convert_names_does_not_fail_when_mixing_special_names_and_numeric_locations)</span> <span class="Special">% Scenario_testing_scenario = true;</span> -<span class="Special">% Hide_warnings = true;</span> +<span class="Special">% Hide_errors = true;</span> recipe main [ screen:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number ] -<span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span> -$warn: <span class="Constant">0</span> +<span class="traceAbsent">-error: mixing variable names and numeric addresses in main</span> +$error: <span class="Constant">0</span> <span class="Delimiter">:(scenarios run_mu_scenario)</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> @@ -171,15 +171,13 @@ const long long int SCREEN = Next_predefined_global_for_scenarios++<span class=" <span class="Delimiter">:(before &quot;End Special Scenario Variable Names(r)&quot;)</span> Name[r][<span class="Constant">&quot;screen&quot;</span>] = SCREEN<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span> +<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr, recipe result)&quot;)</span> <span class="Comment">// rewrite `assume-screen width, height` to</span> -<span class="Comment">// `screen:address &lt;- new-fake-screen width, height`</span> +<span class="Comment">// `screen:address:screen &lt;- new-fake-screen width, height`</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;assume-screen&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;new-fake-screen&quot;</span>]<span class="Delimiter">;</span> curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;new-fake-screen&quot;</span><span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>operation<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">&quot;screen:address&quot;</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">&quot;screen:address:screen&quot;</span><span class="Delimiter">));</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> @@ -187,7 +185,11 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == < <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SCREEN_SHOULD_CONTAIN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;screen-should-contain&quot;</span>] = SCREEN_SHOULD_CONTAIN<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen-should-contain&quot;</span><span class="Delimiter">,</span> SCREEN_SHOULD_CONTAIN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -198,7 +200,11 @@ case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SCREEN_SHOULD_CONTAIN_IN_COLOR<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;screen-should-contain-in-color&quot;</span>] = SCREEN_SHOULD_CONTAIN_IN_COLOR<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen-should-contain-in-color&quot;</span><span class="Delimiter">,</span> SCREEN_SHOULD_CONTAIN_IN_COLOR<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SCREEN_SHOULD_CONTAIN_IN_COLOR: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case SCREEN_SHOULD_CONTAIN_IN_COLOR: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -223,16 +229,16 @@ struct raw_string_stream <span class="Delimiter">{</span> <span class="Delimiter">:(code)</span> void check_screen<span class="Delimiter">(</span>const string&amp; expected_contents<span class="Delimiter">,</span> const int color<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Comment">// not supported</span> - long long int screen_location = Memory[SCREEN]<span class="Delimiter">;</span> - int data_offset = find_element_name<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;data&quot;</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> + long long int screen_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> SCREEN<span class="Delimiter">);</span> + int data_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;data&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>data_offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> long long int screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:array:character</span> - long long int screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span> <span class="Comment">// type: array:character</span> - int width_offset = find_element_name<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">);</span> - long long int screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span> - int height_offset = find_element_name<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">);</span> - long long int screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span> + long long int screen_data_start = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_data_location<span class="Delimiter">);</span> <span class="Comment">// type: array:character</span> + int width_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + long long int screen_width = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+width_offset<span class="Delimiter">);</span> + int height_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + long long int screen_height = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+height_offset<span class="Delimiter">);</span> raw_string_stream cursor<span class="Delimiter">(</span>expected_contents<span class="Delimiter">);</span> <span class="Comment">// todo: too-long expected_contents should fail</span> long long int addr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// skip length</span> @@ -243,21 +249,21 @@ void check_screen<span class="Delimiter">(</span>const string&amp; expected_cont for <span class="Delimiter">(</span>long long int column = <span class="Constant">0</span><span class="Delimiter">;</span> column &lt; screen_width<span class="Delimiter">;</span> ++column<span class="Delimiter">,</span> addr+= <span class="Comment">/*</span><span class="Comment">size of screen-cell</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> const int cell_color_offset = <span class="Constant">1</span><span class="Delimiter">;</span> uint32_t curr = cursor<span class="Delimiter">.</span>get<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Memory[addr] == <span class="Constant">0</span> &amp;&amp; isspace<span class="Delimiter">(</span>curr<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>curr == <span class="Constant">' '</span> &amp;&amp; color != -<span class="Constant">1</span> &amp;&amp; color != Memory[addr+cell_color_offset]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> == <span class="Constant">0</span> &amp;&amp; isspace<span class="Delimiter">(</span>curr<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr == <span class="Constant">' '</span> &amp;&amp; color != -<span class="Constant">1</span> &amp;&amp; color != get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr+cell_color_offset<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// filter out other colors</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>Memory[addr] != <span class="Constant">0</span> &amp;&amp; Memory[addr] == curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>color == -<span class="Constant">1</span> || color == Memory[addr+cell_color_offset]<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> != <span class="Constant">0</span> &amp;&amp; Memory[addr] == curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>color == -<span class="Constant">1</span> || color == get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr+cell_color_offset<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// contents match but color is off</span> if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// genuine test in a mu file</span> - raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;, address &quot;</span> &lt;&lt; addr &lt;&lt; <span class="Constant">&quot;, value &quot;</span> &lt;&lt; Memory[addr] &lt;&lt; <span class="Constant">&quot;) to be in color &quot;</span> &lt;&lt; color &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; Memory[addr+cell_color_offset] &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;, address &quot;</span> &lt;&lt; addr &lt;&lt; <span class="Constant">&quot;, value &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;) to be in color &quot;</span> &lt;&lt; color &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>Memory[addr+cell_color_offset]<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// just testing check_screen</span> - raise &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to be in color &quot;</span> &lt;&lt; color &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; Memory[addr+cell_color_offset] &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to be in color &quot;</span> &lt;&lt; color &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr+cell_color_offset<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -267,26 +273,28 @@ void check_screen<span class="Delimiter">(</span>const string&amp; expected_cont <span class="Delimiter">}</span> <span class="Comment">// really a mismatch</span> - <span class="Comment">// can't print multi-byte unicode characters in warnings just yet. not very useful for debugging anyway.</span> + <span class="Comment">// can't print multi-byte unicode characters in errors just yet. not very useful for debugging anyway.</span> char expected_pretty[<span class="Constant">10</span>] = <span class="Delimiter">{</span><span class="Constant">0</span><span class="Delimiter">};</span> if <span class="Delimiter">(</span>curr &lt; <span class="Constant">256</span> &amp;&amp; !iscntrl<span class="Delimiter">(</span>curr<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// &quot; ('&lt;curr&gt;')&quot;</span> expected_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">3</span>] = static_cast&lt;unsigned char&gt;<span class="Delimiter">(</span>curr<span class="Delimiter">),</span> expected_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> char actual_pretty[<span class="Constant">10</span>] = <span class="Delimiter">{</span><span class="Constant">0</span><span class="Delimiter">};</span> - if <span class="Delimiter">(</span>Memory[addr] &lt; <span class="Constant">256</span> &amp;&amp; !iscntrl<span class="Delimiter">(</span>Memory[addr]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> &lt; <span class="Constant">256</span> &amp;&amp; !iscntrl<span class="Delimiter">(</span>Memory[addr]<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// &quot; ('&lt;curr&gt;')&quot;</span> - actual_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">3</span>] = static_cast&lt;unsigned char&gt;<span class="Delimiter">(</span>Memory[addr]<span class="Delimiter">),</span> actual_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span> + actual_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">3</span>] = static_cast&lt;unsigned char&gt;<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)),</span> actual_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + ostringstream color_phrase<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>color != -<span class="Constant">1</span><span class="Delimiter">)</span> color_phrase &lt;&lt; <span class="Constant">&quot; in color &quot;</span> &lt;&lt; color<span class="Delimiter">;</span> if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// genuine test in a mu file</span> - raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to contain &quot;</span> &lt;&lt; curr &lt;&lt; expected_pretty &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; Memory[addr] &lt;&lt; actual_pretty &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to contain &quot;</span> &lt;&lt; curr &lt;&lt; expected_pretty &lt;&lt; color_phrase<span class="Delimiter">.</span>str<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">))</span> &lt;&lt; actual_pretty &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> dump_screen<span class="Delimiter">();</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// just testing check_screen</span> - raise &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to contain &quot;</span> &lt;&lt; curr &lt;&lt; expected_pretty &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; Memory[addr] &lt;&lt; actual_pretty &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; row &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; column &lt;&lt; <span class="Constant">&quot;) to contain &quot;</span> &lt;&lt; curr &lt;&lt; expected_pretty &lt;&lt; color_phrase<span class="Delimiter">.</span>str<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; instead of &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">))</span> &lt;&lt; actual_pretty &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -305,7 +313,7 @@ raw_string_stream::raw_string_stream<span class="Delimiter">(</span>const string bool raw_string_stream::at_end<span class="Delimiter">()</span> const <span class="Delimiter">{</span> if <span class="Delimiter">(</span>index &gt;= max<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>tb_utf8_char_length<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &gt; max-index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;unicode string seems corrupted at index &quot;</span>&lt;&lt; index &lt;&lt; <span class="Constant">&quot; character &quot;</span> &lt;&lt; static_cast&lt;int&gt;<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;unicode string seems corrupted at index &quot;</span>&lt;&lt; index &lt;&lt; <span class="Constant">&quot; character &quot;</span> &lt;&lt; static_cast&lt;int&gt;<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<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> @@ -343,7 +351,11 @@ void raw_string_stream::skip_whitespace_and_comments<span class="Delimiter">()</ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _DUMP_SCREEN<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$dump-screen&quot;</span>] = _DUMP_SCREEN<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$dump-screen&quot;</span><span class="Delimiter">,</span> _DUMP_SCREEN<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _DUMP_SCREEN: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _DUMP_SCREEN: <span class="Delimiter">{</span> dump_screen<span class="Delimiter">();</span> @@ -352,23 +364,23 @@ case _DUMP_SCREEN: <span class="Delimiter">{</span> <span class="Delimiter">:(code)</span> void dump_screen<span class="Delimiter">()</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Comment">// not supported</span> - long long int screen_location = Memory[SCREEN]<span class="Delimiter">;</span> - int width_offset = find_element_name<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">);</span> - long long int screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span> - int height_offset = find_element_name<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">);</span> - long long int screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span> - int data_offset = find_element_name<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;data&quot;</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> + long long int screen_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> SCREEN<span class="Delimiter">);</span> + int width_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + long long int screen_width = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+width_offset<span class="Delimiter">);</span> + int height_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> + long long int screen_height = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+height_offset<span class="Delimiter">);</span> + int data_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;data&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>data_offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> long long int screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:array:character</span> - long long int screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span> <span class="Comment">// type: array:character</span> - assert<span class="Delimiter">(</span>Memory[screen_data_start] == screen_width*screen_height<span class="Delimiter">);</span> + long long int screen_data_start = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_data_location<span class="Delimiter">);</span> <span class="Comment">// type: array:character</span> + assert<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_data_start<span class="Delimiter">)</span> == screen_width*screen_height<span class="Delimiter">);</span> long long int curr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// skip length</span> for <span class="Delimiter">(</span>long long int row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span> cerr &lt;&lt; <span class="Constant">'.'</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int col = <span class="Constant">0</span><span class="Delimiter">;</span> col &lt; screen_width<span class="Delimiter">;</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Memory[curr]<span class="Delimiter">)</span> - cerr &lt;&lt; to_unicode<span class="Delimiter">(</span>Memory[curr]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">))</span> + cerr &lt;&lt; to_unicode<span class="Delimiter">(</span>static_cast&lt;uint32_t&gt;<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)));</span> else cerr &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> curr += <span class="Comment">/*</span><span class="Comment">size of screen-cell</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">;</span> diff --git a/html/073scenario_screen_test.mu.html b/html/073scenario_screen_test.mu.html index aa6f42b9..ba50c80e 100644 --- a/html/073scenario_screen_test.mu.html +++ b/html/073scenario_screen_test.mu.html @@ -33,7 +33,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> print-character-at-top-left-2 [ assume-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> run [ - screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">97/a</span> + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen, <span class="Constant">97/a</span> ] screen-should-contain [ <span class="Constant"> .a .</span> @@ -45,11 +45,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">5/width</span>, <span class="Constant">3/height</span> run [ <span class="Comment"># print a character</span> - screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">97/a</span> + screen:address:screen<span class="Special"> &lt;- </span>print-character screen:address:screen, <span class="Constant">97/a</span> <span class="Comment"># move cursor to start of line</span> - screen:address<span class="Special"> &lt;- </span>move-cursor screen:address, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> + screen:address:screen<span class="Special"> &lt;- </span>move-cursor screen:address:screen, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> <span class="Comment"># clear line</span> - screen:address<span class="Special"> &lt;- </span>clear-line screen:address + screen:address:screen<span class="Special"> &lt;- </span>clear-line screen:address:screen ] screen-should-contain [ <span class="Constant"> . .</span> diff --git a/html/074console.mu.html b/html/074console.mu.html index 191c33e8..62f88c3a 100644 --- a/html/074console.mu.html +++ b/html/074console.mu.html @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -61,7 +61,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> new-fake-console [ <span class="Constant">local-scope</span> result:address:console<span class="Special"> &lt;- </span>new <span class="Constant">console:type</span> - buf:address:address:array:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span> + buf:address:address:array:event<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span> *buf<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> idx:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">index:offset</span> *idx<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> @@ -96,7 +96,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># newlines, tabs, ctrl-d..</span> <span class="muRecipe">recipe</span> read-key [ <span class="Constant">local-scope</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + console:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> x:event, console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console <span class="muControl">reply-if</span> quit?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit? <span class="muControl">reply-unless</span> found?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit? @@ -107,9 +107,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> send-keys-to-channel [ <span class="Constant">local-scope</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + console:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> c:character, console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-key console <span class="muControl">loop-unless</span> found? @@ -124,7 +124,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> wait-for-event [ <span class="Constant">local-scope</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + console:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> _, console, found?:boolean<span class="Special"> &lt;- </span>read-event console <span class="muControl">loop-unless</span> found? @@ -135,7 +135,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># use this helper to skip rendering if there's lots of other events queued up</span> <span class="muRecipe">recipe</span> has-more-events? [ <span class="Constant">local-scope</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + console:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> console <span class="Comment"># fake consoles should be plenty fast; never skip</span> diff --git a/html/075scenario_console.cc.html b/html/075scenario_console.cc.html index c578c2a8..6ef48e09 100644 --- a/html/075scenario_console.cc.html +++ b/html/075scenario_console.cc.html @@ -43,10 +43,10 @@ scenario keyboard-in-scenario [ type [abc] ] run [ - <span class="Constant">1</span>:character<span class="Delimiter">,</span> console:address<span class="Delimiter">,</span> <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>read-key console:address - <span class="Constant">3</span>:character<span class="Delimiter">,</span> console:address<span class="Delimiter">,</span> <span class="Constant">4</span>:boolean<span class="Special"> &lt;- </span>read-key console:address - <span class="Constant">5</span>:character<span class="Delimiter">,</span> console:address<span class="Delimiter">,</span> <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>read-key console:address - <span class="Constant">7</span>:character<span class="Delimiter">,</span> console:address<span class="Delimiter">,</span> <span class="Constant">8</span>:boolean<span class="Delimiter">,</span> <span class="Constant">9</span>:boolean<span class="Special"> &lt;- </span>read-key console:address + <span class="Constant">1</span>:character<span class="Delimiter">,</span> console:address:console<span class="Delimiter">,</span> <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console + <span class="Constant">3</span>:character<span class="Delimiter">,</span> console:address:console<span class="Delimiter">,</span> <span class="Constant">4</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console + <span class="Constant">5</span>:character<span class="Delimiter">,</span> console:address:console<span class="Delimiter">,</span> <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console + <span class="Constant">7</span>:character<span class="Delimiter">,</span> console:address:console<span class="Delimiter">,</span> <span class="Constant">8</span>:boolean<span class="Delimiter">,</span> <span class="Constant">9</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> @@ -70,47 +70,50 @@ Name[r][<span class="Constant">&quot;console&quot;</span>] = CONSOLE<span class= <span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span> if <span class="Delimiter">(</span>s == <span class="Constant">&quot;console&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> -<span class="Comment">//: Unlike assume-keyboard, assume-console is easiest to implement as just a</span> -<span class="Comment">//: primitive recipe.</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> ASSUME_CONSOLE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;assume-console&quot;</span>] = ASSUME_CONSOLE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;assume-console&quot;</span><span class="Delimiter">,</span> ASSUME_CONSOLE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case ASSUME_CONSOLE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case ASSUME_CONSOLE: <span class="Delimiter">{</span> <span class="Comment">// create a temporary recipe just for parsing; it won't contain valid instructions</span> istringstream in<span class="Delimiter">(</span><span class="Constant">&quot;[&quot;</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">&quot;]&quot;</span><span class="Delimiter">);</span> - recipe r = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + recipe r<span class="Delimiter">;</span> + slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">,</span> r<span class="Delimiter">);</span> long long int num_events = count_events<span class="Delimiter">(</span>r<span class="Delimiter">);</span> - <span class="Comment">// initialize the events</span> + <span class="Comment">// initialize the events like in new-fake-console</span> long long int size = num_events*size_of_event<span class="Delimiter">()</span> + <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span> long long int event_data_address = Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> - Memory[event_data_address] = num_events<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> event_data_address<span class="Delimiter">,</span> num_events<span class="Delimiter">);</span> ++Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> const instruction&amp; curr = r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;left-click&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'touch-event' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">;</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'type' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">0</span>] = TB_KEY_MOUSE_LEFT<span class="Delimiter">;</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'row' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">1</span>] = to_integer<span class="Delimiter">(</span>curr<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="Delimiter">);</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'column' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">2</span>] = to_integer<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">tag for 'touch-event' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'type' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">,</span> TB_KEY_MOUSE_LEFT<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'row' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> to_integer<span class="Delimiter">(</span>curr<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="Delimiter">));</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'column' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">,</span> to_integer<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span> Current_routine<span class="Delimiter">-&gt;</span>alloc += size_of_event<span class="Delimiter">();</span> <span class="Delimiter">}</span> else if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;press&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string key = curr<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="Delimiter">;</span> if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>key<span class="Delimiter">))</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>] = to_integer<span class="Delimiter">(</span>key<span class="Delimiter">);</span> - else if <span class="Delimiter">(</span>Key<span class="Delimiter">.</span>find<span class="Delimiter">(</span>key<span class="Delimiter">)</span> != Key<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>] = Key[key]<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span><span class="Delimiter">,</span> to_integer<span class="Delimiter">(</span>key<span class="Delimiter">));</span> + else if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Key<span class="Delimiter">,</span> key<span class="Delimiter">))</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span><span class="Delimiter">,</span> Key[key]<span class="Delimiter">);</span> else - raise &lt;&lt; <span class="Constant">&quot;assume-console: can't press &quot;</span> &lt;&lt; key &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span>] &lt; <span class="Constant">256</span><span class="Delimiter">)</span> + raise_error &lt;&lt; <span class="Constant">&quot;assume-console: can't press &quot;</span> &lt;&lt; key &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Constant">1</span><span class="Delimiter">)</span> &lt; <span class="Constant">256</span><span class="Delimiter">)</span> <span class="Comment">// these keys are in ascii</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'text' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">tag for 'text' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> else <span class="Delimiter">{</span> <span class="Comment">// distinguish from unicode</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'keycode' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">tag for 'keycode' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-&gt;</span>alloc += size_of_event<span class="Delimiter">();</span> <span class="Delimiter">}</span> @@ -123,22 +126,23 @@ case ASSUME_CONSOLE: <span class="Delimiter">{</span> long long int num_keyboard_events = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> long long int curr = <span class="Constant">0</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; num_keyboard_events<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'text' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">tag for 'text' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> uint32_t curr_character<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr &lt; SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> tb_utf8_char_to_unicode<span class="Delimiter">(</span>&amp;curr_character<span class="Delimiter">,</span> &amp;raw_contents[curr]<span class="Delimiter">);</span> - Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Comment">/*</span><span class="Comment">skip exclusive container tag</span><span class="Comment">*/</span><span class="Constant">1</span>] = curr_character<span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc+<span class="Comment">/*</span><span class="Comment">skip exclusive container tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> curr_character<span class="Delimiter">);</span> curr += tb_utf8_char_length<span class="Delimiter">(</span>raw_contents[curr]<span class="Delimiter">);</span> Current_routine<span class="Delimiter">-&gt;</span>alloc += size_of_event<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>alloc == event_data_address+size<span class="Delimiter">);</span> - <span class="Comment">// wrap the array of events in an event object</span> - ensure_space<span class="Delimiter">(</span>size_of_events<span class="Delimiter">());</span> - Memory[CONSOLE] = Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> - Current_routine<span class="Delimiter">-&gt;</span>alloc += size_of_events<span class="Delimiter">();</span> - Memory[Memory[CONSOLE]+<span class="Comment">/*</span><span class="Comment">offset of 'data' in container 'events'</span><span class="Comment">*/</span><span class="Constant">1</span>] = event_data_address<span class="Delimiter">;</span> + <span class="Comment">// wrap the array of events in a console object</span> + ensure_space<span class="Delimiter">(</span>size_of_console<span class="Delimiter">());</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> CONSOLE<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">);</span> + Current_routine<span class="Delimiter">-&gt;</span>alloc += size_of_console<span class="Delimiter">();</span> + long long int console_address = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> CONSOLE<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> console_address+<span class="Comment">/*</span><span class="Comment">offset of 'data' in container 'events'</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> event_data_address<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -212,15 +216,15 @@ scenario events-in-scenario [ ] run [ <span class="Comment"># 3 keyboard events; each event occupies 4 locations</span> - <span class="Constant">1</span>:event<span class="Special"> &lt;- </span>read-event console:address - <span class="Constant">5</span>:event<span class="Special"> &lt;- </span>read-event console:address - <span class="Constant">9</span>:event<span class="Special"> &lt;- </span>read-event console:address + <span class="Constant">1</span>:event<span class="Special"> &lt;- </span>read-event console:address:console + <span class="Constant">5</span>:event<span class="Special"> &lt;- </span>read-event console:address:console + <span class="Constant">9</span>:event<span class="Special"> &lt;- </span>read-event console:address:console <span class="Comment"># mouse click</span> - <span class="Constant">13</span>:event<span class="Special"> &lt;- </span>read-event console:address + <span class="Constant">13</span>:event<span class="Special"> &lt;- </span>read-event console:address:console <span class="Comment"># non-character keycode</span> - <span class="Constant">17</span>:event<span class="Special"> &lt;- </span>read-event console:address + <span class="Constant">17</span>:event<span class="Special"> &lt;- </span>read-event console:address:console <span class="Comment"># final keyboard event</span> - <span class="Constant">21</span>:event<span class="Special"> &lt;- </span>read-event console:address + <span class="Constant">21</span>:event<span class="Special"> &lt;- </span>read-event console:address:console ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># 'text'</span> @@ -256,21 +260,26 @@ scenario events-in-scenario [ <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> REPLACE_IN_CONSOLE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;replace-in-console&quot;</span>] = REPLACE_IN_CONSOLE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;replace-in-console&quot;</span><span class="Delimiter">,</span> REPLACE_IN_CONSOLE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case REPLACE_IN_CONSOLE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case REPLACE_IN_CONSOLE: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> - if <span class="Delimiter">(</span>!Memory[CONSOLE]<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; <span class="Constant">&quot;console not initialized</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> CONSOLE<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; <span class="Constant">&quot;console not initialized</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - long long int console_data = Memory[Memory[CONSOLE]+<span class="Constant">1</span>]<span class="Delimiter">;</span> - long long int size = Memory[console_data]<span class="Delimiter">;</span> <span class="Comment">// array size</span> + long long int console_address = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> CONSOLE<span class="Delimiter">);</span> + long long int console_data = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> console_address+<span class="Constant">1</span><span class="Delimiter">);</span> + long long int size = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> console_data<span class="Delimiter">);</span> <span class="Comment">// array size</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">,</span> curr = console_data+<span class="Constant">1</span><span class="Delimiter">;</span> i &lt; size<span class="Delimiter">;</span> ++i<span class="Delimiter">,</span> curr+=size_of_event<span class="Delimiter">())</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Memory[curr] != <span class="Comment">/*</span><span class="Comment">text</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Memory[curr+<span class="Constant">1</span>] != ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)</span> != <span class="Comment">/*</span><span class="Comment">text</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr+<span class="Constant">1</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="Identifier">continue</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int n = <span class="Constant">0</span><span class="Delimiter">;</span> n &lt; size_of_event<span class="Delimiter">();</span> ++n<span class="Delimiter">)</span> - Memory[curr+n] = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span>n<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr+n<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>n<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -292,20 +301,20 @@ long long int size_of_event<span class="Delimiter">()</span> <span class="Delimi <span class="Comment">// memoize result if already computed</span> static long long int result = <span class="Constant">0</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>result<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> - vector&lt;type_ordinal&gt; type<span class="Delimiter">;</span> - type<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;event&quot;</span>]<span class="Delimiter">);</span> + type_tree* type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;event&quot;</span><span class="Delimiter">));</span> result = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span> + delete type<span class="Delimiter">;</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> -long long int size_of_events<span class="Delimiter">()</span> <span class="Delimiter">{</span> +long long int size_of_console<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Comment">// memoize result if already computed</span> static long long int result = <span class="Constant">0</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>result<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> - vector&lt;type_ordinal&gt; type<span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;console&quot;</span>]<span class="Delimiter">);</span> - type<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[<span class="Constant">&quot;console&quot;</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;console&quot;</span><span class="Delimiter">));</span> + type_tree* type = new type_tree<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;console&quot;</span><span class="Delimiter">));</span> result = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span> + delete type<span class="Delimiter">;</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> diff --git a/html/076scenario_console_test.mu.html b/html/076scenario_console_test.mu.html index b33cb4cd..bc0f6688 100644 --- a/html/076scenario_console_test.mu.html +++ b/html/076scenario_console_test.mu.html @@ -37,10 +37,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[abc]</span> ] run [ - <span class="Constant">1</span>:character, console:address, <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>read-key console:address - <span class="Constant">3</span>:character, console:address, <span class="Constant">4</span>:boolean<span class="Special"> &lt;- </span>read-key console:address - <span class="Constant">5</span>:character, console:address, <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>read-key console:address - <span class="Constant">7</span>:character, console:address, <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>read-key console:address + <span class="Constant">1</span>:character, console:address:console, <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console + <span class="Constant">3</span>:character, console:address:console, <span class="Constant">4</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console + <span class="Constant">5</span>:character, console:address:console, <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console + <span class="Constant">7</span>:character, console:address:console, <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>read-key console:address:console ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> diff --git a/html/080trace_browser.cc.html b/html/080trace_browser.cc.html index 9ac50591..d209225b 100644 --- a/html/080trace_browser.cc.html +++ b/html/080trace_browser.cc.html @@ -32,7 +32,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _BROWSE_TRACE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$browse-trace&quot;</span>] = _BROWSE_TRACE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$browse-trace&quot;</span><span class="Delimiter">,</span> _BROWSE_TRACE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _BROWSE_TRACE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _BROWSE_TRACE: <span class="Delimiter">{</span> start_trace_browser<span class="Delimiter">();</span> @@ -105,7 +109,7 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter for <span class="Delimiter">(</span>int screen_row = tb_height<span class="Delimiter">();</span> screen_row &gt; <span class="Constant">0</span> &amp;&amp; Top_of_screen &gt; <span class="Constant">0</span><span class="Delimiter">;</span> --screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span> --Top_of_screen<span class="Delimiter">;</span> if <span class="Delimiter">(</span>Top_of_screen &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> - while <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span> &amp;&amp; Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Top_of_screen<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + while <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span> &amp;&amp; !contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> Top_of_screen<span class="Delimiter">))</span> --Top_of_screen<span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span><span class="Delimiter">)</span> @@ -117,7 +121,7 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter for <span class="Delimiter">(</span>int screen_row = tb_height<span class="Delimiter">();</span> screen_row &gt; <span class="Constant">0</span> &amp;&amp; Top_of_screen &gt; <span class="Constant">0</span><span class="Delimiter">;</span> --screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span> --Top_of_screen<span class="Delimiter">;</span> if <span class="Delimiter">(</span>Top_of_screen &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> - while <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span> &amp;&amp; Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Top_of_screen<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + while <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span> &amp;&amp; !contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> Top_of_screen<span class="Delimiter">))</span> --Top_of_screen<span class="Delimiter">;</span> <span class="Delimiter">}</span> refresh_screen_rows<span class="Delimiter">();</span> @@ -127,13 +131,13 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter <span class="Delimiter">}</span> if <span class="Delimiter">(</span>key == TB_KEY_CARRIAGE_RETURN<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// expand lines under current by one level</span> - assert<span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Display_row<span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Trace_index<span class="Delimiter">,</span> Display_row<span class="Delimiter">));</span> long long int start_index = Trace_index[Display_row]<span class="Delimiter">;</span> long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">// simultaneously compute end_index and min_depth</span> int min_depth = <span class="Constant">9999</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>index<span class="Delimiter">)</span> != Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> index<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth &gt; Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>start_index<span class="Delimiter">).</span>depth<span class="Delimiter">);</span> @@ -151,13 +155,13 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter <span class="Delimiter">}</span> if <span class="Delimiter">(</span>key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// collapse all lines under current</span> - assert<span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Display_row<span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Trace_index<span class="Delimiter">,</span> Display_row<span class="Delimiter">));</span> long long int start_index = Trace_index[Display_row]<span class="Delimiter">;</span> long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">// end_index is the next line at a depth same as or lower than start_index</span> int initial_depth = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>start_index<span class="Delimiter">).</span>depth<span class="Delimiter">;</span> for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>index<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> index<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth &lt;= initial_depth<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -179,7 +183,7 @@ void refresh_screen_rows<span class="Delimiter">()</span> <span class="Delimiter Trace_index<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> for <span class="Delimiter">(</span>screen_row = <span class="Constant">0</span><span class="Delimiter">,</span> index = Top_of_screen<span class="Delimiter">;</span> screen_row &lt; tb_height<span class="Delimiter">()</span> &amp;&amp; index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++screen_row<span class="Delimiter">,</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// skip lines without depth for now</span> - while <span class="Delimiter">(</span>Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>index<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> index<span class="Delimiter">))</span> <span class="Delimiter">{</span> ++index<span class="Delimiter">;</span> if <span class="Delimiter">(</span>index &gt;= SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">))</span> <span class="Identifier">goto</span> done<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -192,7 +196,7 @@ done:<span class="Delimiter">;</span> void render<span class="Delimiter">()</span> <span class="Delimiter">{</span> long long int screen_row = <span class="Constant">0</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>screen_row = <span class="Constant">0</span><span class="Delimiter">;</span> screen_row &lt; tb_height<span class="Delimiter">();</span> ++screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>screen_row<span class="Delimiter">)</span> == Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Trace_index<span class="Delimiter">,</span> screen_row<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Trace_index[screen_row]<span class="Delimiter">);</span> ostringstream out<span class="Delimiter">;</span> out &lt;&lt; std::setw<span class="Delimiter">(</span><span class="Constant">4</span><span class="Delimiter">)</span> &lt;&lt; curr_line<span class="Delimiter">.</span>depth &lt;&lt; <span class="Constant">' '</span> &lt;&lt; curr_line<span class="Delimiter">.</span>label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; curr_line<span class="Delimiter">.</span>contents<span class="Delimiter">;</span> @@ -216,8 +220,8 @@ void render<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Delimiter">}</span> long long int lines_hidden<span class="Delimiter">(</span>long long int screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>screen_row<span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">());</span> - if <span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>screen_row+<span class="Constant">1</span><span class="Delimiter">)</span> == Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Trace_index<span class="Delimiter">,</span> screen_row<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Trace_index<span class="Delimiter">,</span> screen_row+<span class="Constant">1</span><span class="Delimiter">))</span> <span class="Identifier">return</span> SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">)</span>-Trace_index[screen_row]<span class="Delimiter">;</span> else <span class="Identifier">return</span> Trace_index[screen_row+<span class="Constant">1</span>] - Trace_index[screen_row]<span class="Delimiter">;</span> diff --git a/html/081run_interactive.cc.html b/html/081run_interactive.cc.html index 79db9059..3802f61a 100644 --- a/html/081run_interactive.cc.html +++ b/html/081run_interactive.cc.html @@ -13,8 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.cSpecial { color: #008000; } .traceContains { color: #008000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -36,46 +36,53 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(scenario run_interactive_code)</span> recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new [<span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>copy <span class="Constant">34</span>] run-interactive <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:number/<span class="Special">raw &lt;- </span>copy <span class="Constant">1</span>:number/<span class="Special">raw</span> ] -<span class="traceContains">+mem: storing 34 in location 1</span> +<span class="traceContains">+mem: storing 34 in location 3</span> <span class="Delimiter">:(scenario run_interactive_empty)</span> recipe main [ - <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>run-interactive <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Special">raw</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>run-interactive <span class="Constant">1</span>:address:array:character ] <span class="Comment"># result is null</span> -<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 2</span> -<span class="Comment">//: run code in 'interactive mode', i.e. with warnings off and return:</span> +<span class="Comment">//: run code in 'interactive mode', i.e. with errors+warnings off and return:</span> <span class="Comment">//: stringified output in case we want to print it to screen</span> -<span class="Comment">//: any warnings encountered</span> +<span class="Comment">//: any errors+warnings encountered</span> <span class="Comment">//: simulated screen any prints went to</span> <span class="Comment">//: any 'app' layer traces generated</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> RUN_INTERACTIVE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;run-interactive&quot;</span>] = RUN_INTERACTIVE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;run-interactive&quot;</span><span class="Delimiter">,</span> RUN_INTERACTIVE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case RUN_INTERACTIVE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'run-interactive' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'run-interactive' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'run-interactive' should be a string, but got &quot;</span> &lt;&lt; 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>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'run-interactive' should be a string, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case RUN_INTERACTIVE: <span class="Delimiter">{</span> bool new_code_pushed_to_stack = run_interactive<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> if <span class="Delimiter">(</span>!new_code_pushed_to_stack<span class="Delimiter">)</span> <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">5</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>trace_contents<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">));</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>trace_error_warning_contents<span class="Delimiter">());</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>trace_contents<span class="Delimiter">(</span><span class="Constant">&quot;app&quot;</span><span class="Delimiter">));</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>trace_app_contents<span class="Delimiter">());</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">4</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// completed</span> - cleanup_run_interactive<span class="Delimiter">();</span> + run_code_end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// done with this instruction</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> @@ -85,6 +92,9 @@ case RUN_INTERACTIVE: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> bool Track_most_recent_products = <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before &quot;End Tracing&quot;)</span> +trace_stream* Save_trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> +string Save_trace_file<span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Setup&quot;)</span> Track_most_recent_products = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> @@ -92,7 +102,7 @@ Track_most_recent_products = <span class="Constant">false</span><span class="Del <span class="Comment">// all warnings.</span> <span class="Comment">// returns true if successfully called (no errors found during load and transform)</span> bool run_interactive<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> != Recipe_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">()</span> &amp;&amp; Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>] != <span class="Constant">0</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> &amp;&amp; get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// try to sandbox the run as best you can</span> <span class="Comment">// todo: test this</span> if <span class="Delimiter">(</span>!Current_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -101,54 +111,83 @@ bool run_interactive<span class="Delimiter">(</span>long long int address<span c <span class="Delimiter">}</span> string command = trim<span class="Delimiter">(</span>strip_comments<span class="Delimiter">(</span>read_mu_string<span class="Delimiter">(</span>address<span class="Delimiter">)));</span> if <span class="Delimiter">(</span>command<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>]<span class="Delimiter">);</span> - Name[Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>]]<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> - <span class="Comment">// stuff to undo later, in cleanup_run_interactive()</span> - Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Trace_file = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span> <span class="Comment">// if there wasn't already a stream we don't want to save it</span> - Trace_stream = new trace_stream<span class="Delimiter">;</span> - Trace_stream<span class="Delimiter">-&gt;</span>collect_layers<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">);</span> - Trace_stream<span class="Delimiter">-&gt;</span>collect_layers<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">&quot;app&quot;</span><span class="Delimiter">);</span> - <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">&quot;interactive&quot;</span><span class="Delimiter">));</span> + Name[get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + run_code_begin<span class="Delimiter">();</span> + <span class="Comment">// don't kill the current routine on parse errors</span> + routine* save_current_routine = Current_routine<span class="Delimiter">;</span> + Current_routine = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Comment">// call run(string) but without the scheduling</span> load<span class="Delimiter">(</span>string<span class="Delimiter">(</span><span class="Constant">&quot;recipe interactive [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">)</span> + <span class="Constant">&quot;local-scope</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + - <span class="Constant">&quot;screen:address &lt;- next-ingredient</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + + <span class="Constant">&quot;screen:address:screen &lt;- next-ingredient</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;$start-tracking-products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + command + <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;$stop-tracking-products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;reply screen</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> transform_all<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">)</span> &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + Current_routine = save_current_routine<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">&quot;error&quot;</span><span class="Delimiter">)</span> &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// now call 'sandbox' which will run 'interactive' in a separate routine,</span> <span class="Comment">// and wait for it</span> - Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>Recipe_ordinal[<span class="Constant">&quot;sandbox&quot;</span>]<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>Save_trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ++Save_trace_stream<span class="Delimiter">-&gt;</span>callstack_depth<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;trace&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;run-interactive: incrementing callstack depth to &quot;</span> &lt;&lt; Save_trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt;&lt; end<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>Save_trace_stream<span class="Delimiter">-&gt;</span>callstack_depth &lt; <span class="Constant">9000</span><span class="Delimiter">);</span> <span class="Comment">// 9998-101 plus cushion</span> + <span class="Delimiter">}</span> + Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;sandbox&quot;</span><span class="Delimiter">)));</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +void run_code_begin<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// stuff to undo later, in run_code_end()</span> + Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> + Hide_errors = <span class="Constant">true</span><span class="Delimiter">;</span> + Disable_redefine_warnings = <span class="Constant">true</span><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">&quot;&quot;</span><span class="Delimiter">;</span> + Trace_stream = new trace_stream<span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-&gt;</span>collect_depth = App_depth<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +void run_code_end<span class="Delimiter">()</span> <span class="Delimiter">{</span> + Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> + Hide_errors = <span class="Constant">false</span><span class="Delimiter">;</span> + Disable_redefine_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> + delete 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> +<span class="Delimiter">}</span> + <span class="Delimiter">:(before &quot;End Load Recipes&quot;)</span> load<span class="Delimiter">(</span>string<span class="Delimiter">(</span> <span class="Constant">&quot;recipe interactive [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">)</span> + <span class="Comment">// just a dummy version to initialize the Recipe_ordinal and so on</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;recipe sandbox [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;local-scope</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + - <span class="Constant">&quot;screen:address/shared &lt;- new-fake-screen 30, 5</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + - <span class="Constant">&quot;r:number/routine_id &lt;- start-running interactive:recipe, screen:address</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + + <span class="Constant">&quot;screen:address:screen/shared &lt;- new-fake-screen 30, 5</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + + <span class="Constant">&quot;r:number/routine_id &lt;- start-running interactive:recipe, screen</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;limit-time r, 100000/instructions</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;wait-for-routine r</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;sandbox-state:number &lt;- routine-state r/routine_id</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;completed?:boolean &lt;- equal sandbox-state, 1/completed</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;output:address:array:character &lt;- $most-recent-products</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + - <span class="Constant">&quot;warnings:address:array:character &lt;- save-trace [warn]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + - <span class="Constant">&quot;stashes:address:array:character &lt;- save-trace [app]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + + <span class="Constant">&quot;warnings:address:array:character &lt;- save-errors-warnings</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + + <span class="Constant">&quot;stashes:address:array:character &lt;- save-app-trace</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;$cleanup-run-interactive</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;reply output, warnings, screen, stashes, completed?</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> + <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> transform_all<span class="Delimiter">();</span> recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Comment">//: adjust errors/warnings in the sandbox</span> +<span class="Delimiter">:(after &quot;string maybe(string s)&quot;)</span> + if <span class="Delimiter">(</span>s == <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span> + <span class="Delimiter">:(scenario run_interactive_comments)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [<span class="Comment"># ab</span> @@ -158,19 +197,14 @@ add <span class="Constant">2</span><span class="Delimiter">,</span> <span class= ] <span class="traceContains">+mem: storing 52 in location 4</span> -<span class="Delimiter">:(scenario run_interactive_just_comments_without_trace)</span> -recipe main [ - $close-trace - <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [<span class="Comment"># ab</span> -] - <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>run-interactive <span class="Constant">1</span>:address:array:character - <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character -] - <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _START_TRACKING_PRODUCTS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$start-tracking-products&quot;</span>] = _START_TRACKING_PRODUCTS<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$start-tracking-products&quot;</span><span class="Delimiter">,</span> _START_TRACKING_PRODUCTS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _START_TRACKING_PRODUCTS: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _START_TRACKING_PRODUCTS: <span class="Delimiter">{</span> Track_most_recent_products = <span class="Constant">true</span><span class="Delimiter">;</span> @@ -180,7 +214,11 @@ case _START_TRACKING_PRODUCTS: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _STOP_TRACKING_PRODUCTS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$stop-tracking-products&quot;</span>] = _STOP_TRACKING_PRODUCTS<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$stop-tracking-products&quot;</span><span class="Delimiter">,</span> _STOP_TRACKING_PRODUCTS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _STOP_TRACKING_PRODUCTS: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _STOP_TRACKING_PRODUCTS: <span class="Delimiter">{</span> Track_most_recent_products = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -190,7 +228,11 @@ case _STOP_TRACKING_PRODUCTS: <span class="Delimiter">{</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _MOST_RECENT_PRODUCTS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$most-recent-products&quot;</span>] = _MOST_RECENT_PRODUCTS<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$most-recent-products&quot;</span><span class="Delimiter">,</span> _MOST_RECENT_PRODUCTS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _MOST_RECENT_PRODUCTS: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case _MOST_RECENT_PRODUCTS: <span class="Delimiter">{</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -199,33 +241,47 @@ case _MOST_RECENT_PRODUCTS: <span class="Delimiter">{</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -SAVE_TRACE<span class="Delimiter">,</span> +SAVE_ERRORS_WARNINGS<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;save-trace&quot;</span>] = SAVE_TRACE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;save-errors-warnings&quot;</span><span class="Delimiter">,</span> SAVE_ERRORS_WARNINGS<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SAVE_ERRORS_WARNINGS: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case SAVE_TRACE: <span class="Delimiter">{</span> +case SAVE_ERRORS_WARNINGS: <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>trace_contents<span class="Delimiter">(</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="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>trace_error_warning_contents<span class="Delimiter">());</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> -_CLEANUP_RUN_INTERACTIVE<span class="Delimiter">,</span> +SAVE_APP_TRACE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;$cleanup-run-interactive&quot;</span>] = _CLEANUP_RUN_INTERACTIVE<span class="Delimiter">;</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;save-app-trace&quot;</span><span class="Delimiter">,</span> SAVE_APP_TRACE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case SAVE_APP_TRACE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> -case _CLEANUP_RUN_INTERACTIVE: <span class="Delimiter">{</span> - cleanup_run_interactive<span class="Delimiter">();</span> +case SAVE_APP_TRACE: <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>trace_app_contents<span class="Delimiter">());</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> -void cleanup_run_interactive<span class="Delimiter">()</span> <span class="Delimiter">{</span> - Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Trace_stream &amp;&amp; Trace_stream<span class="Delimiter">-&gt;</span>is_narrowly_collecting<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// hack</span> - delete Trace_stream<span class="Delimiter">;</span> - Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> +_CLEANUP_RUN_INTERACTIVE<span class="Delimiter">,</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$cleanup-run-interactive&quot;</span><span class="Delimiter">,</span> _CLEANUP_RUN_INTERACTIVE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> +case _CLEANUP_RUN_INTERACTIVE: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case _CLEANUP_RUN_INTERACTIVE: <span class="Delimiter">{</span> + run_code_end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario &quot;run_interactive_returns_stringified_result&quot;)</span> @@ -242,9 +298,9 @@ recipe main [ recipe main [ <span class="Comment"># try to interactively add 2 and 2</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [ - <span class="Constant">100</span>:address:array:character<span class="Special"> &lt;- </span>new [a] - <span class="Constant">101</span>:address:array:character<span class="Special"> &lt;- </span>new [b] - <span class="Constant">102</span>:address:array:character<span class="Special"> &lt;- </span>string-append <span class="Constant">100</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">101</span>:address:array:character + x:address:array:character<span class="Special"> &lt;- </span>new [a] + y:address:array:character<span class="Special"> &lt;- </span>new [b] + z:address:array:character<span class="Special"> &lt;- </span>string-append x:address:array:character<span class="Delimiter">,</span> y:address:array:character ] <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>run-interactive <span class="Constant">1</span>:address:array:character <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy <span class="Constant">2</span>:address:array:character/lookup @@ -253,18 +309,31 @@ recipe main [ <span class="traceContains">+mem: storing 97 in location 11</span> <span class="traceContains">+mem: storing 98 in location 12</span> -<span class="Delimiter">:(scenario &quot;run_interactive_returns_warnings&quot;)</span> +<span class="Delimiter">:(scenario &quot;run_interactive_returns_errors&quot;)</span> recipe main [ - <span class="Comment"># run a command that generates a warning</span> - <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [get <span class="Constant">1234</span>:number<span class="Delimiter">,</span> foo:offset] + <span class="Comment"># run a command that generates an error</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [x:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> +get x:number<span class="Delimiter">,</span> foo:offset] <span class="Constant">2</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:character<span class="Special"> &lt;- </span>run-interactive <span class="Constant">1</span>:address:array:character <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:array:character/lookup ] -<span class="Comment"># warning should be &quot;unknown element foo in container number&quot;</span> +<span class="Comment"># error should be &quot;unknown element foo in container number&quot;</span> <span class="traceContains">+mem: storing 117 in location 11</span> <span class="traceContains">+mem: storing 110 in location 12</span> <span class="traceContains">+mem: storing 107 in location 13</span> <span class="traceContains">+mem: storing 110 in location 14</span> +<span class="Comment"># ...</span> + +<span class="Delimiter">:(scenario run_interactive_with_comment)</span> +recipe main [ + <span class="Comment"># 2 instructions, with a comment after the first</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> &lt;- </span>new [a:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># abc</span> +b:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> +] + <span class="Constant">2</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:character<span class="Special"> &lt;- </span>run-interactive <span class="Constant">1</span>:address:array:character +] +<span class="Comment"># no errors</span> +<span class="traceContains">+mem: storing 0 in location 3</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> string Most_recent_products<span class="Delimiter">;</span> @@ -283,10 +352,10 @@ void track_most_recent_products<span class="Delimiter">(</span>const instruction if <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> tb_shutdown<span class="Delimiter">();</span> - cerr &lt;&lt; read_mu_string<span class="Delimiter">(</span>trace_contents<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + cerr &lt;&lt; read_mu_string<span class="Delimiter">(</span>trace_error_warning_contents<span class="Delimiter">())</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> cerr &lt;&lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;: &quot;</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span> - cerr &lt;&lt; products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> + cerr &lt;&lt; no_scientific<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)));</span> @@ -296,7 +365,7 @@ void track_most_recent_products<span class="Delimiter">(</span>const instruction <span class="Comment">// End Record Product Special-cases</span> <span class="Delimiter">}</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span> - out &lt;&lt; products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> + out &lt;&lt; no_scientific<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span> out &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> Most_recent_products = out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> @@ -310,7 +379,7 @@ string strip_comments<span class="Delimiter">(</span>string in<span class="Delim result &lt;&lt; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> - while <span class="Delimiter">(</span>i &lt; SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> &amp;&amp; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> + while <span class="Delimiter">(</span>i+<span class="Constant">1</span> &lt; SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> &amp;&amp; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i+<span class="Constant">1</span><span class="Delimiter">)</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> ++i<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -320,21 +389,34 @@ string strip_comments<span class="Delimiter">(</span>string in<span class="Delim long long int stringified_value_of_location<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// convert to string</span> ostringstream out<span class="Delimiter">;</span> - out &lt;&lt; Memory[address]<span class="Delimiter">;</span> + out &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">));</span> <span class="Identifier">return</span> new_mu_string<span class="Delimiter">(</span>out<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> -long long int trace_contents<span class="Delimiter">(</span>const string&amp; layer<span class="Delimiter">)</span> <span class="Delimiter">{</span> +long long int trace_error_warning_contents<span class="Delimiter">()</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + ostringstream out<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>depth &gt; Warning_depth<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + out &lt;&lt; p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>*--p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">.</span>end<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> out &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string result = out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>result<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + truncate<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Identifier">return</span> new_mu_string<span class="Delimiter">(</span>result<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +long long int trace_app_contents<span class="Delimiter">()</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span>layer<span class="Delimiter">)</span> &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> ostringstream out<span class="Delimiter">;</span> for <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>label != layer<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>depth != App_depth<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> out &lt;&lt; p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">;</span> if <span class="Delimiter">(</span>*--p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">.</span>end<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> out &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> string result = out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> - assert<span class="Delimiter">(</span>!result<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + if <span class="Delimiter">(</span>result<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> truncate<span class="Delimiter">(</span>result<span class="Delimiter">);</span> <span class="Identifier">return</span> new_mu_string<span class="Delimiter">(</span>result<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -349,51 +431,58 @@ void truncate<span class="Delimiter">(</span>string&amp; x<span class="Delimiter <span class="Delimiter">}</span> <span class="Comment">//: simpler version of run-interactive: doesn't do any running, just loads</span> -<span class="Comment">//: recipes and reports warnings.</span> +<span class="Comment">//: recipes and reports errors+warnings.</span> + <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> RELOAD<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;reload&quot;</span>] = RELOAD<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;reload&quot;</span><span class="Delimiter">,</span> RELOAD<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case RELOAD: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'reload' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'reload' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'reload' should be a literal string, but got &quot;</span> &lt;&lt; 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>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'reload' should be a string, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Trace_file = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span> <span class="Comment">// if there wasn't already a stream we don't want to save it</span> - Trace_stream = new trace_stream<span class="Delimiter">;</span> - Trace_stream<span class="Delimiter">-&gt;</span>collect_layers<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> - Disable_redefine_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +case RELOAD: <span class="Delimiter">{</span> <span class="Comment">// clear any containers in advance</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Type[recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> string code = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + run_code_begin<span class="Delimiter">();</span> + routine* save_current_routine = Current_routine<span class="Delimiter">;</span> + Current_routine = <span class="Constant">NULL</span><span class="Delimiter">;</span> vector&lt;recipe_ordinal&gt; recipes_reloaded = load<span class="Delimiter">(</span>code<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>recipes_reloaded<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> Name<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recipes_reloaded<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> transform_all<span class="Delimiter">();</span> Trace_stream<span class="Delimiter">-&gt;</span>newline<span class="Delimiter">();</span> <span class="Comment">// flush trace</span> - Disable_redefine_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> - Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> + Current_routine = save_current_routine<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>trace_contents<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">));</span> - <span class="Comment">// hack: assume collect_layers isn't set anywhere else</span> - if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>is_narrowly_collecting<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - delete Trace_stream<span class="Delimiter">;</span> - Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>trace_error_warning_contents<span class="Delimiter">());</span> + run_code_end<span class="Delimiter">();</span> <span class="Comment">// wait until we're done with the trace contents</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario reload_continues_past_error)</span> +recipe main [ + local-scope + x:address:array:character<span class="Special"> &lt;- </span>new [recipe foo [ + get <span class="Constant">1234</span>:number<span class="Delimiter">,</span> foo:offset +]] + reload x + <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+mem: storing 34 in location 1</span> </pre> </body> </html> diff --git a/html/082persist.cc.html b/html/082persist.cc.html index 01788333..1f6ed24f 100644 --- a/html/082persist.cc.html +++ b/html/082persist.cc.html @@ -14,7 +14,6 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.PreProc { color: #c000c0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Identifier { color: #804000; } @@ -37,13 +36,28 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> RESTORE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;restore&quot;</span>] = RESTORE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;restore&quot;</span><span class="Delimiter">,</span> RESTORE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case RESTORE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'restore' requires exactly one ingredient, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <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_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'restore' requires exactly one ingredient, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string filename<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'restore' should be a string, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case RESTORE: <span class="Delimiter">{</span> string filename<span class="Delimiter">;</span> if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</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> <span class="Delimiter">{</span> filename = 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="Delimiter">;</span> @@ -51,11 +65,12 @@ case RESTORE: <span class="Delimiter">{</span> else if <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</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> <span class="Delimiter">{</span> filename = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> - else <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'restore' should be a string, but got &quot;</span> &lt;&lt; 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>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Current_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// do nothing in tests</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>Current_scenario<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// do nothing in tests</span> string contents = slurp<span class="Delimiter">(</span><span class="Constant">&quot;lesson/&quot;</span>+filename<span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> if <span class="Delimiter">(</span>contents<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> @@ -85,13 +100,31 @@ string slurp<span class="Delimiter">(</span>const string&amp; filename<span clas <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> SAVE<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> -Recipe_ordinal[<span class="Constant">&quot;save&quot;</span>] = SAVE<span class="Delimiter">;</span> -<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;save&quot;</span><span class="Delimiter">,</span> SAVE<span class="Delimiter">);</span> +<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> case SAVE: <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'save' requires exactly two ingredients, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;'save' requires exactly two ingredients, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;first ingredient of 'save' should be a string, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; 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> &lt;&lt; <span class="Constant">&quot;second ingredient of 'save' should be an address:array:character, but got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; 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 &quot;End Primitive Recipe Implementations&quot;)</span> +case SAVE: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Current_scenario<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// do nothing in tests</span> string filename<span class="Delimiter">;</span> if <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</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> <span class="Delimiter">{</span> @@ -100,14 +133,6 @@ case SAVE: <span class="Delimiter">{</span> else if <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</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> <span class="Delimiter">{</span> filename = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> - else <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: first ingredient of 'save' should be a string, but got &quot;</span> &lt;&lt; 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>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: second ingredient of 'save' should be an address:array:character, but got &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> ofstream fout<span class="Delimiter">((</span><span class="Constant">&quot;lesson/&quot;</span>+filename<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> string contents = read_mu_string<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> fout &lt;&lt; contents<span class="Delimiter">;</span> @@ -117,7 +142,7 @@ case SAVE: <span class="Delimiter">{</span> <span class="Comment">// explicitly say '--all' for git 1.9</span> int status = system<span class="Delimiter">(</span><span class="Constant">&quot;cd lesson; git add --all .; git diff HEAD --exit-code &gt;/dev/null || git commit -a -m . &gt;/dev/null&quot;</span><span class="Delimiter">);</span> if <span class="Delimiter">(</span>status != <span class="Constant">0</span><span class="Delimiter">)</span> - raise &lt;&lt; <span class="Constant">&quot;error in commit: contents &quot;</span> &lt;&lt; contents &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> + raise_error &lt;&lt; <span class="Constant">&quot;error in commit: contents &quot;</span> &lt;&lt; contents &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -126,9 +151,6 @@ bool exists<span class="Delimiter">(</span>const string&amp; filename<span class struct stat dummy<span class="Delimiter">;</span> <span class="Identifier">return</span> <span class="Constant">0</span> == stat<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &amp;dummy<span class="Delimiter">);</span> <span class="Delimiter">}</span> - -<span class="Delimiter">:(before &quot;End Includes&quot;)</span> -<span class="PreProc">#include</span><span class="Constant">&lt;sys/stat.h&gt;</span> </pre> </body> </html> diff --git a/html/098check_type_pointers.cc.html b/html/098check_type_pointers.cc.html new file mode 100644 index 00000000..74de0da6 --- /dev/null +++ b/html/098check_type_pointers.cc.html @@ -0,0 +1,67 @@ +<!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 - 098check_type_pointers.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.Delimiter { color: #a04060; } +.Identifier { color: #804000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Delimiter">:(before &quot;End Transform All&quot;)</span> +check_type_pointers<span class="Delimiter">();</span> + +<span class="Delimiter">:(code)</span> +void check_type_pointers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>map&lt;recipe_ordinal<span class="Delimiter">,</span> recipe&gt;::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> + if <span class="Delimiter">(</span>any_type_ingredient_in_header<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + const recipe&amp; r = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction&amp; inst = r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;' -- &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; has no type</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;' -- &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; has no type name</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;' -- &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; has no type</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error &lt;&lt; maybe<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;' -- &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; has no type name</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/999spaces.cc.html b/html/999spaces.cc.html index dbcc31d2..dac58e9d 100644 --- a/html/999spaces.cc.html +++ b/html/999spaces.cc.html @@ -56,14 +56,11 @@ assert<span class="Delimiter">(</span>Next_recipe_ordinal == <span class="Consta <span class="SalientComment">//:: Depths for tracing</span> <span class="Comment">//:</span> <span class="Comment">//: 0 - unused</span> -<span class="Comment">//: 1-99 - app-level trace statements in mu</span> -<span class="Comment">//: 100 - schedule</span> -assert<span class="Delimiter">(</span>Scheduling_depth == <span class="Constant">100</span><span class="Delimiter">);</span> -<span class="Comment">//: 101-9998 - call-stack statements (mostly label run)</span> +<span class="Comment">//: 1-100 - app-level trace statements in mu</span> +<span class="Comment">//: 101-9989 - call-stack statements (mostly label run)</span> assert<span class="Delimiter">(</span>Initial_callstack_depth == <span class="Constant">101</span><span class="Delimiter">);</span> -assert<span class="Delimiter">(</span>Max_callstack_depth == <span class="Constant">9998</span><span class="Delimiter">);</span> -<span class="Comment">//: 9999 - intra-instruction lines (mostly label mem)</span> -assert<span class="Delimiter">(</span>Primitive_recipe_depth == <span class="Constant">9999</span><span class="Delimiter">);</span> +assert<span class="Delimiter">(</span>Max_callstack_depth == <span class="Constant">9989</span><span class="Delimiter">);</span> +<span class="Comment">//: 9990-9999 - intra-instruction lines (mostly label mem)</span> </pre> </body> </html> diff --git a/html/channel.mu.html b/html/channel.mu.html index 420eed5e..12babbde 100644 --- a/html/channel.mu.html +++ b/html/channel.mu.html @@ -13,12 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -33,11 +33,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># example program: communicating between routines using channels</span> <span class="muRecipe">recipe</span> producer [ - <span class="Comment"># produce numbers 1 to 5 on a channel</span> + <span class="Comment"># produce characters 1 to 5 on a channel</span> <span class="Constant">local-scope</span> chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># n = 0</span> - n:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> + n:character<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>lesser-than n, <span class="Constant">5</span> <span class="muControl">break-unless</span> done? @@ -56,9 +56,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="Comment"># read an integer from the channel</span> - n:number, chan:address:channel<span class="Special"> &lt;- </span>read chan + n:character, chan:address:channel<span class="Special"> &lt;- </span>read chan <span class="Comment"># other threads might get between these prints</span> - $print <span class="Constant">[consume: ]</span>, n:number, <span class="Constant">[ </span> + $print <span class="Constant">[consume: ]</span>, n:character, <span class="Constant">[ </span> <span class="Constant">]</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> @@ -68,8 +68,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">local-scope</span> chan:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3</span> <span class="Comment"># create two background 'routines' that communicate by a channel</span> - routine1:number<span class="Special"> &lt;- </span>start-running <span class="Constant">producer:recipe</span>, chan - routine2:number<span class="Special"> &lt;- </span>start-running <span class="Constant">consumer:recipe</span>, chan + routine1:character<span class="Special"> &lt;- </span>start-running <span class="Constant">producer:recipe</span>, chan + routine2:character<span class="Special"> &lt;- </span>start-running <span class="Constant">consumer:recipe</span>, chan wait-for-routine routine1 wait-for-routine routine2 ] diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html index 56b4842e..5e11ad01 100644 --- a/html/chessboard.mu.html +++ b/html/chessboard.mu.html @@ -13,16 +13,16 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .SalientComment { color: #00ffff; } -.muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .CommentedCode { color: #6c6c6c; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.muScenario { color: #00af00; } --> </style> @@ -61,7 +61,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## But enough about mu. Here's what it looks like to run the chessboard program.</span> <span class="muScenario">scenario</span> print-board-and-read-move [ - $close-trace <span class="Comment"># administrivia: most scenarios save and check traces, but this one gets too large/slow</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># we'll make the screen really wide because the program currently prints out a long line</span> assume-screen <span class="Constant">120/width</span>, <span class="Constant">20/height</span> <span class="Comment"># initialize keyboard to type in a move</span> @@ -70,7 +70,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">]</span> ] run [ - screen:address, console:address<span class="Special"> &lt;- </span>chessboard screen:address, console:address + screen:address:screen, console:address:console<span class="Special"> &lt;- </span>chessboard screen:address:screen, console:address:console <span class="Comment"># icon for the cursor</span> screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">9251/␣</span> ] @@ -104,8 +104,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> chessboard [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + console:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> board:address:array:address:array:character<span class="Special"> &lt;- </span>initial-position <span class="Comment"># hook up stdin</span> stdin:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span> @@ -147,7 +147,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> new-board [ <span class="Constant">local-scope</span> - initial-position:address:array:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + initial-position:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># assert(length(initial-position) == 64)</span> len:number<span class="Special"> &lt;- </span>length *initial-position correct-length?:boolean<span class="Special"> &lt;- </span>equal len, <span class="Constant">64</span> @@ -168,7 +168,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> new-file [ <span class="Constant">local-scope</span> - position:address:array:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + position:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> index:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> index<span class="Special"> &lt;- </span>multiply index, <span class="Constant">8</span> result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, <span class="Constant">8</span> @@ -187,7 +187,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe</span> print-board [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> board:address:array:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> row:number<span class="Special"> &lt;- </span>copy <span class="Constant">7</span> <span class="Comment"># start printing from the top of the board</span> <span class="Comment"># print each row</span> @@ -236,7 +236,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># B P _ _ _ _ p B</span> <span class="Comment"># N P _ _ _ _ p n</span> <span class="Comment"># R P _ _ _ _ p r</span> - initial-position:address:array:number<span class="Special"> &lt;- </span>new-array <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">81/Q</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">113/q</span>, <span class="Constant">75/K</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">107/k</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span> + initial-position:address:array:character<span class="Special"> &lt;- </span>new-array <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">81/Q</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">113/q</span>, <span class="Constant">75/K</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">107/k</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span> <span class="CommentedCode">#? 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r,</span> <span class="CommentedCode">#? 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,</span> <span class="CommentedCode">#? 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, </span> @@ -253,7 +253,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span> run [ <span class="Constant">1</span>:address:array:address:array:character/board<span class="Special"> &lt;- </span>initial-position - screen:address<span class="Special"> &lt;- </span>print-board screen:address, <span class="Constant">1</span>:address:array:address:array:character/board + screen:address:screen<span class="Special"> &lt;- </span>print-board screen:address:screen, <span class="Constant">1</span>:address:array:address:array:character/board ] screen-should-contain [ <span class="Comment"># 012345678901234567890123456789</span> @@ -282,12 +282,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } to-rank:number ] -<span class="Comment"># result:address:move, quit?:boolean, error?:boolean &lt;- read-move stdin:address:channel, screen:address</span> +<span class="Comment"># result:address:move, quit?:boolean, error?:boolean &lt;- read-move stdin:address:channel, screen:address:screen</span> <span class="Comment"># prints only error messages to screen</span> <span class="muRecipe">recipe</span> read-move [ <span class="Constant">local-scope</span> stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> from-file:number, quit?:boolean, error?:boolean<span class="Special"> &lt;- </span>read-file stdin, screen <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error? <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error? @@ -314,12 +314,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> result, quit?, error? ] -<span class="Comment"># file:number, quit:boolean, error:boolean &lt;- read-file stdin:address:channel, screen:address</span> +<span class="Comment"># file:number, quit:boolean, error:boolean &lt;- read-file stdin:address:channel, screen:address:screen</span> <span class="Comment"># valid values for file: 0-7</span> <span class="muRecipe">recipe</span> read-file [ <span class="Constant">local-scope</span> stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> c:character, stdin<span class="Special"> &lt;- </span>read stdin <span class="Delimiter">{</span> q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">81/Q</span> @@ -365,12 +365,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> file, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span> ] -<span class="Comment"># rank:number &lt;- read-rank stdin:address:channel, screen:address</span> +<span class="Comment"># rank:number &lt;- read-rank stdin:address:channel, screen:address:screen</span> <span class="Comment"># valid values: 0-7, -1 (quit), -2 (error)</span> <span class="muRecipe">recipe</span> read-rank [ <span class="Constant">local-scope</span> stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> c:character, stdin<span class="Special"> &lt;- </span>read stdin <span class="Delimiter">{</span> q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8/Q</span> @@ -416,7 +416,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">local-scope</span> stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> expected:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> c:character, stdin<span class="Special"> &lt;- </span>read stdin <span class="Delimiter">{</span> match?:boolean<span class="Special"> &lt;- </span>equal c, expected @@ -432,7 +432,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">2</span>:number <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id @@ -504,7 +504,7 @@ F read-move-blocking: routine failed to terminate on newline] assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">2</span>:number <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id @@ -531,7 +531,7 @@ F read-move-quit: routine failed to terminate on 'q'] assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">2</span>:number <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id @@ -552,7 +552,7 @@ F read-move-file: routine failed to pause <span class="muRecipe">after</span> co assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">2</span>:number <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id @@ -574,7 +574,7 @@ F read-move-file: routine failed to pause <span class="muRecipe">after</span> co assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">2</span>:number <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id @@ -623,7 +623,7 @@ F read-move-file: routine failed to pause <span class="muRecipe">after</span> co <span class="Constant">7</span>:address:number<span class="Special"> &lt;- </span>get-address *<span class="Constant">3</span>:address:move, <span class="Constant">to-rank:offset</span> *<span class="Constant">7</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">3/'4'</span> <span class="Constant">2</span>:address:array:address:array:character/board<span class="Special"> &lt;- </span>make-move <span class="Constant">2</span>:address:array:address:array:character/board, <span class="Constant">3</span>:address:move - screen:address<span class="Special"> &lt;- </span>print-board screen:address, <span class="Constant">2</span>:address:array:address:array:character/board + screen:address:screen<span class="Special"> &lt;- </span>print-board screen:address:screen, <span class="Constant">2</span>:address:array:address:array:character/board ] screen-should-contain [ <span class="Comment"># 012345678901234567890123456789</span> diff --git a/html/console.mu.html b/html/console.mu.html index 116fb450..1a14d4ed 100644 --- a/html/console.mu.html +++ b/html/console.mu.html @@ -13,12 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } .Constant { color: #00a0a0; } -.muControl { color: #c0a020; } --> </style> diff --git a/html/counters.mu.html b/html/counters.mu.html index 9a02adca..495def81 100644 --- a/html/counters.mu.html +++ b/html/counters.mu.html @@ -17,7 +17,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } -.muControl { color: #c0a020; } --> </style> @@ -32,18 +31,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># example program: maintain multiple counters with isolated lexical scopes</span> <span class="Comment"># (spaces)</span> -<span class="muRecipe">recipe</span> new-counter [ - <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply</span> <span class="Constant">default-space</span> +<span class="muRecipe">recipe</span> new-counter n:number<span class="muRecipe"> -&gt; </span><span class="Constant">default-space</span>:address:array:location [ + <span class="Constant">default-space</span><span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> + <span class="Constant">load-ingredients</span> ] -<span class="muRecipe">recipe</span> increment-counter [ +<span class="muRecipe">recipe</span> increment-counter outer:address:array:location/names:new-counter, x:number<span class="muRecipe"> -&gt; </span>n:number/space:<span class="Constant">1</span> [ <span class="Constant">local-scope</span> - <span class="Constant">0</span>:address:array:location/names:new-counter<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span> - x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - n:number/space:<span class="Constant">1</span><span class="Special"> &lt;- </span>add n:number/space:<span class="Constant">1</span>, x - <span class="muControl">reply</span> n:number/space:<span class="Constant">1</span> + <span class="Constant">load-ingredients</span> + <span class="Constant">0</span>:address:array:location/names:new-counter<span class="Special"> &lt;- </span>copy outer <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span> + n/space:<span class="Constant">1</span><span class="Special"> &lt;- </span>add n/space:<span class="Constant">1</span>, x ] <span class="muRecipe">recipe</span> main [ diff --git a/html/edit/001-editor.mu.html b/html/edit/001-editor.mu.html index be568c9d..916e93c6 100644 --- a/html/edit/001-editor.mu.html +++ b/html/edit/001-editor.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } +.muScenario { color: #00af00; } .muData { color: #ffff00; } .Special { color: #ff6060; } -.muScenario { color: #00af00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -37,9 +37,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># temporary main for this layer: just render the given string at the given</span> <span class="Comment"># screen dimensions, then stop</span> -<span class="muRecipe">recipe!</span> main [ +<span class="muRecipe">recipe!</span> main text:address:array:character [ <span class="Constant">local-scope</span> - text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> open-console hide-screen <span class="Constant">0/screen</span> new-editor text, <span class="Constant">0/screen</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> @@ -52,7 +52,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> run [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> - new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> ] screen-should-contain [ <span class="Comment"># top line of screen reserved for menu</span> @@ -79,19 +79,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } cursor-column:number ] -<span class="Comment"># editor:address, screen &lt;- new-editor s:address:array:character, screen:address, left:number, right:number</span> -<span class="Comment"># creates a new editor widget and renders its initial appearance to screen.</span> -<span class="Comment"># top/left/right constrain the screen area available to the new editor.</span> -<span class="Comment"># right is exclusive.</span> -<span class="muRecipe">recipe</span> new-editor [ +<span class="Comment"># creates a new editor widget and renders its initial appearance to screen</span> +<span class="Comment"># top/left/right constrain the screen area available to the new editor</span> +<span class="Comment"># right is exclusive</span> +<span class="muRecipe">recipe</span> new-editor s:address:array:character, screen:address:screen, left:number, right:number<span class="muRecipe"> -&gt; </span>result:address:editor-data [ <span class="Constant">local-scope</span> - s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># no clipping of bounds</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> right<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span> - result:address:editor-data<span class="Special"> &lt;- </span>new <span class="Constant">editor-data:type</span> + result<span class="Special"> &lt;- </span>new <span class="Constant">editor-data:type</span> <span class="Comment"># initialize screen-related fields</span> x:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">left:offset</span> *x<span class="Special"> &lt;- </span>copy left @@ -102,11 +98,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *x<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span> x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-column:offset</span> *x<span class="Special"> &lt;- </span>copy left - init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span> + init:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span> *init<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167/§</span>, <span class="Constant">0/tail</span> - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">top-of-screen:offset</span> *top-of-screen<span class="Special"> &lt;- </span>copy *init - y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">before-cursor:offset</span> + y:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">before-cursor:offset</span> *y<span class="Special"> &lt;- </span>copy *init result<span class="Special"> &lt;- </span>insert-text result, s <span class="Comment"># initialize cursor to top of screen</span> @@ -115,20 +111,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># initial render to screen, just for some old tests</span> _, _, screen, result<span class="Special"> &lt;- </span>render screen, result <span class="Constant"> &lt;editor-initialization&gt;</span> - <span class="muControl">reply</span> result ] -<span class="muRecipe">recipe</span> insert-text [ +<span class="muRecipe">recipe</span> insert-text editor:address:editor-data, text:address:array:character<span class="muRecipe"> -&gt; </span>editor:address:editor-data [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># early exit if text is empty</span> <span class="muControl">reply-unless</span> text, editor/same-as-ingredient:<span class="Constant">0</span> len:number<span class="Special"> &lt;- </span>length *text <span class="muControl">reply-unless</span> len, editor/same-as-ingredient:<span class="Constant">0</span> idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># now we can start appending the rest, character by character</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + curr:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len <span class="muControl">break-if</span> done? @@ -145,7 +139,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-initializes-without-data [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">3/height</span> run [ - <span class="Constant">1</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">0/data</span>, screen:address, <span class="Constant">2/left</span>, <span class="Constant">5/right</span> + <span class="Constant">1</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">0/data</span>, screen:address:screen, <span class="Constant">2/left</span>, <span class="Constant">5/right</span> <span class="Constant">2</span>:editor-data<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:editor-data ] memory-should-contain [ @@ -165,22 +159,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># last-row:number, last-column:number, screen, editor &lt;- render screen:address, editor:address:editor-data</span> -<span class="Comment">#</span> <span class="Comment"># Assumes cursor should be at coordinates (cursor-row, cursor-column) and</span> <span class="Comment"># updates before-cursor to match. Might also move coordinates if they're</span> <span class="Comment"># outside text.</span> -<span class="muRecipe">recipe</span> render [ +<span class="muRecipe">recipe</span> render screen:address:screen, editor:address:editor-data<span class="muRecipe"> -&gt; </span>last-row:number, last-column:number, screen:address:screen, editor:address:editor-data [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="muControl">reply-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"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> screen-height:number<span class="Special"> &lt;- </span>screen-height screen right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> <span class="Comment"># traversing editor</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span> + curr:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + prev:address:duplex-list:character<span class="Special"> &lt;- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span> curr<span class="Special"> &lt;- </span>next-duplex curr <span class="Comment"># traversing screen</span> <span class="Constant"> +render-loop-initialization</span> @@ -189,7 +180,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } column:number<span class="Special"> &lt;- </span>copy left cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> screen<span class="Special"> &lt;- </span>move-cursor screen, row, column <span class="Delimiter">{</span> <span class="Constant"> +next-character</span> @@ -251,7 +242,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># save first character off-screen</span> - bottom-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">bottom-of-screen:offset</span> + bottom-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">bottom-of-screen:offset</span> *bottom-of-screen<span class="Special"> &lt;- </span>copy curr <span class="Comment"># is cursor to the right of the last line? move to end</span> <span class="Delimiter">{</span> @@ -268,11 +259,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> row, column, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span> ] -<span class="muRecipe">recipe</span> clear-line-delimited [ +<span class="muRecipe">recipe</span> clear-line-delimited screen:address:screen, column:number, right:number [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>greater-than column, right <span class="muControl">break-if</span> done? @@ -282,13 +271,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> clear-screen-from [ +<span class="muRecipe">recipe</span> clear-screen-from screen:address:screen, row:number, column:number, left:number, right:number<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># if it's the real screen, use the optimized primitive</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> screen @@ -302,12 +287,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> clear-rest-of-screen [ +<span class="muRecipe">recipe</span> clear-rest-of-screen screen:address:screen, row:number, left:number, right:number [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> screen<span class="Special"> &lt;- </span>move-cursor screen, row, left screen-height:number<span class="Special"> &lt;- </span>screen-height screen @@ -326,7 +308,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } run [ s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -340,7 +322,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">5/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">1/left</span>, <span class="Constant">5/right</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -354,7 +336,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } run [ s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">5/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">1/left</span>, <span class="Constant">5/right</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -368,7 +350,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc def]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -388,7 +370,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> ] <span class="Comment"># still wrap, even though the line would fit. We need room to click on the</span> <span class="Comment"># end of the line</span> @@ -410,7 +392,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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="Constant">3</span>:number<span class="Special"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -433,7 +415,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant"># de</span> <span class="Constant">f]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -462,12 +444,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } color<span class="Special"> &lt;- </span>get-color color, c ] -<span class="Comment"># color &lt;- get-color color:number, c:character</span> <span class="Comment"># so far the previous color is all the information we need; that may change</span> -<span class="muRecipe">recipe</span> get-color [ +<span class="muRecipe">recipe</span> get-color color:number, c:character<span class="muRecipe"> -&gt; </span>color:number [ <span class="Constant">local-scope</span> - color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> color-is-white?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">7/white</span> <span class="Comment"># if color is white and next character is '#', switch color to blue</span> <span class="Delimiter">{</span> @@ -516,7 +496,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d &lt;- e</span> <span class="Constant">f]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">8/right</span> + new-editor s:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">8/right</span> ] screen-should-contain [ <span class="Constant"> . .</span> diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html index 787e3a4e..c1f1128f 100644 --- a/html/edit/002-typing.mu.html +++ b/html/edit/002-typing.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .Special { color: #ff6060; } -.muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.muScenario { color: #00af00; } --> </style> @@ -37,27 +37,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># temporary main: interactive editor</span> <span class="Comment"># hit ctrl-c to exit</span> -<span class="muRecipe">recipe!</span> main [ +<span class="muRecipe">recipe!</span> main text:address:array:character [ <span class="Constant">local-scope</span> - text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> open-console editor:address:editor-data<span class="Special"> &lt;- </span>new-editor text, <span class="Constant">0/screen</span>, <span class="Constant">5/left</span>, <span class="Constant">45/right</span> editor-event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, editor close-console ] -<span class="muRecipe">recipe</span> editor-event-loop [ +<span class="muRecipe">recipe</span> editor-event-loop screen:address:screen, console:address:console, editor:address:editor-data [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span> <span class="Constant"> +next-event</span> cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span> cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span> screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column - e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console + e:event, console:address:console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console <span class="muControl">loop-unless</span> found? <span class="muControl">break-if</span> quit? <span class="Comment"># only in tests</span> trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span> @@ -82,11 +80,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># process click, return if it was on current editor</span> -<span class="muRecipe">recipe</span> move-cursor-in-editor [ +<span class="muRecipe">recipe</span> move-cursor-in-editor screen:address:screen, editor:address:editor-data, t:touch-event<span class="muRecipe"> -&gt; </span>in-focus?:boolean [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> editor, <span class="Constant">0/false</span> click-row:number<span class="Special"> &lt;- </span>get t, <span class="Constant">row:offset</span> <span class="muControl">reply-unless</span> click-row, <span class="Constant">0/false</span> <span class="Comment"># ignore clicks on 'menu'</span> @@ -106,24 +102,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> <span class="Constant">1/true</span> ] -<span class="Comment"># editor &lt;- snap-cursor screen:address, editor:address:editor-data, target-row:number, target-column:number</span> -<span class="Comment">#</span> <span class="Comment"># Variant of 'render' that only moves the cursor (coordinates and</span> <span class="Comment"># before-cursor). If it's past the end of a line, it 'slides' it left. If it's</span> <span class="Comment"># past the last line it positions at end of last line.</span> -<span class="muRecipe">recipe</span> snap-cursor [ +<span class="muRecipe">recipe</span> snap-cursor screen:address:screen, editor:address:editor-data, target-row:number, target-column:number<span class="muRecipe"> -&gt; </span>editor:address:editor-data [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - target-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - target-column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> editor, <span class="Constant">1/top</span>, editor/same-as-ingredient:<span class="Constant">1</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> editor left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> screen-height:number<span class="Special"> &lt;- </span>screen-height screen <span class="Comment"># count newlines until screen row</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span> + curr:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + prev:address:duplex-list:character<span class="Special"> &lt;- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span> curr<span class="Special"> &lt;- </span>next-duplex curr row:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span> column:number<span class="Special"> &lt;- </span>copy left @@ -131,7 +122,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *cursor-row<span class="Special"> &lt;- </span>copy target-row cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> *cursor-column<span class="Special"> &lt;- </span>copy target-column - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> <span class="Delimiter">{</span> <span class="Constant"> +next-character</span> <span class="muControl">break-unless</span> curr @@ -195,23 +186,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *cursor-column<span class="Special"> &lt;- </span>copy column *before-cursor<span class="Special"> &lt;- </span>copy prev <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">1</span> ] -<span class="Comment"># screen, editor, go-render?:boolean &lt;- handle-keyboard-event screen:address, editor:address:editor-data, e:event</span> <span class="Comment"># Process an event 'e' and try to minimally update the screen.</span> <span class="Comment"># Set 'go-render?' to true to indicate the caller must perform a non-minimal update.</span> -<span class="muRecipe">recipe</span> handle-keyboard-event [ +<span class="muRecipe">recipe</span> handle-keyboard-event screen:address:screen, editor:address:editor-data, e:event<span class="muRecipe"> -&gt; </span>screen:address:screen, editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - e:event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> editor, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + <span class="Constant">load-ingredients</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-unless</span> editor screen-width:number<span class="Special"> &lt;- </span>screen-width screen screen-height:number<span class="Special"> &lt;- </span>screen-height screen left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> save-row:number<span class="Special"> &lt;- </span>copy *cursor-row @@ -225,27 +213,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> &lt;handle-special-character&gt;</span> <span class="Comment"># ignore any other special characters</span> regular-character?:boolean<span class="Special"> &lt;- </span>greater-or-equal *c, <span class="Constant">32/space</span> - <span class="muControl">reply-unless</span> regular-character?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-unless</span> regular-character? <span class="Comment"># otherwise type it in</span> <span class="Constant"> &lt;insert-character-begin&gt;</span> editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, *c, screen <span class="Constant"> &lt;insert-character-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># special key to modify the text or move the cursor</span> k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span> assert k, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span> <span class="Comment"># handlers for each special key will go here</span> <span class="Constant"> &lt;handle-special-key&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> ] -<span class="muRecipe">recipe</span> insert-at-cursor [ +<span class="muRecipe">recipe</span> insert-at-cursor editor:address:editor-data, c:character, screen:address:screen<span class="muRecipe"> -&gt; </span>editor:address:editor-data, screen:address:screen, go-render?:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + <span class="Constant">load-ingredients</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> insert-duplex c, *before-cursor *before-cursor<span class="Special"> &lt;- </span>next-duplex *before-cursor cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> @@ -260,7 +248,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> &lt;insert-character-special-case&gt;</span> <span class="Comment"># but mostly we'll just move the cursor right</span> *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span> - next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + next:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="Delimiter">{</span> <span class="Comment"># at end of all text? no need to scroll? just print the character and leave</span> at-end?:boolean<span class="Special"> &lt;- </span>equal next, <span class="Constant">0/null</span> @@ -272,20 +260,22 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-if</span> overflow? move-cursor screen, save-row, save-column print-character screen, c - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="Comment"># not at right margin? print the character and rest of line</span> <span class="muControl">break-unless</span> next at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, screen-width <span class="muControl">break-if</span> at-right? - curr:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor + curr:address:duplex-list:character<span class="Special"> &lt;- </span>copy *before-cursor move-cursor screen, save-row, save-column curr-column:number<span class="Special"> &lt;- </span>copy save-column <span class="Delimiter">{</span> <span class="Comment"># hit right margin? give up and let caller render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> at-right?:boolean<span class="Special"> &lt;- </span>greater-than curr-column, right - <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span> + <span class="muControl">reply-if</span> at-right? <span class="muControl">break-unless</span> curr <span class="Comment"># newline? done.</span> currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> @@ -296,16 +286,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } curr<span class="Special"> &lt;- </span>next-duplex curr <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> ] <span class="Comment"># helper for tests</span> -<span class="muRecipe">recipe</span> editor-render [ +<span class="muRecipe">recipe</span> editor-render screen:address:screen, editor:address:editor-data<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> row:number, column:number<span class="Special"> &lt;- </span>render screen, editor @@ -319,11 +310,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-handles-empty-event-queue [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console <span class="Constant">[]</span> run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -336,14 +327,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-handles-mouse-clicks [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> <span class="Comment"># on the 'b'</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -363,13 +354,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Constant"> $clear-trace</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">7</span> <span class="Comment"># last line, to the right of text</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -384,13 +375,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Constant"> $clear-trace</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">7</span> <span class="Comment"># interior line, to the right of text</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -405,13 +396,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Constant"> $clear-trace</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">7</span> <span class="Comment"># below text</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -426,7 +417,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc]</span> <span class="Comment"># editor occupies only left half of screen</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -434,7 +425,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">3</span>, <span class="Constant">8</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -454,7 +445,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-handles-mouse-clicks-in-menu-area [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -462,7 +453,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">0</span>, <span class="Constant">3</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -476,14 +467,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [ 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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ type <span class="Constant">[abc]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -497,7 +488,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># type two letters at different places</span> @@ -507,7 +498,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[d]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -521,7 +512,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -529,7 +520,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[d]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -544,7 +535,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -552,7 +543,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[e]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -567,7 +558,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -575,7 +566,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[d]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -590,7 +581,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -598,7 +589,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[e]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -614,7 +605,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -622,7 +613,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[ef]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -637,13 +628,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [ 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"> &lt;- </span>new <span class="Constant">[ab]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[01]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -658,14 +649,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-wraps-line-on-insert [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># type a letter</span> assume-console [ type <span class="Constant">[e]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># no wrap yet</span> screen-should-contain [ @@ -680,7 +671,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[f]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># now wrap</span> screen-should-contain [ @@ -697,7 +688,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abcdefg</span> <span class="Constant">defg]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># type more text at the start</span> assume-console [ @@ -705,7 +696,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[abc]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -740,20 +731,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> below-screen? <span class="Constant"> &lt;scroll-down&gt;</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [ 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"> &lt;- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> type <span class="Constant">[f]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -773,13 +765,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [ 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"> &lt;- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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">3</span> <span class="Comment"># right before the wrap icon</span> type <span class="Constant">[f]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -799,13 +791,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-wraps-cursor-to-left-margin [ 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"> &lt;- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">2/left</span>, <span class="Constant">7/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">2/left</span>, <span class="Constant">7/right</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">5</span> <span class="Comment"># line is full; no wrap icon yet</span> type <span class="Constant">[01]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -836,13 +828,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> assume-console [ type <span class="Constant">[0</span> <span class="Constant">1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -860,17 +852,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> &lt;insert-enter-begin&gt;</span> editor<span class="Special"> &lt;- </span>insert-new-line-and-indent editor, screen <span class="Constant"> &lt;insert-enter-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> insert-new-line-and-indent [ +<span class="muRecipe">recipe</span> insert-new-line-and-indent editor:address:editor-data, screen:address:screen<span class="muRecipe"> -&gt; </span>editor:address:editor-data, screen:address:screen, go-render?:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> screen-height:number<span class="Special"> &lt;- </span>screen-height screen @@ -884,13 +876,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height <span class="Comment"># must be equal, never greater</span> <span class="muControl">break-unless</span> below-screen? <span class="Constant"> &lt;scroll-down&gt;</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> <span class="Delimiter">}</span> <span class="Comment"># indent if necessary</span> indent?:boolean<span class="Special"> &lt;- </span>get *editor, <span class="Constant">indent?:offset</span> - <span class="muControl">reply-unless</span> indent?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> - d:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> - end-of-previous-line:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor + <span class="muControl">reply-unless</span> indent? + d:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + end-of-previous-line:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex *before-cursor indent:number<span class="Special"> &lt;- </span>line-indent end-of-previous-line, d i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> @@ -900,19 +893,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> ] <span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span> <span class="Comment"># the number of spaces at the start of the line containing 'curr'.</span> -<span class="muRecipe">recipe</span> line-indent [ +<span class="muRecipe">recipe</span> line-indent curr:address:duplex-list:character, start:address:duplex-list:character<span class="muRecipe"> -&gt; </span>result:number [ <span class="Constant">local-scope</span> - curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - <span class="muControl">reply-unless</span> curr, result + <span class="muControl">reply-unless</span> curr at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start - <span class="muControl">reply-if</span> at-start?, result + <span class="muControl">reply-if</span> at-start? <span class="Delimiter">{</span> curr<span class="Special"> &lt;- </span>prev-duplex curr <span class="muControl">break-unless</span> curr @@ -934,19 +925,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> result ] <span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline-2 [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> assume-console [ type <span class="Constant">[0</span> <span class="Constant">1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -960,7 +950,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [ 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"> &lt;- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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 [ press enter ] @@ -972,7 +962,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . .</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># line should be fully cleared</span> screen-should-contain [ @@ -989,7 +979,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span> <span class="Constant"> cd</span> <span class="Constant">ef]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># position cursor after 'cd' and hit 'newline'</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">8</span> @@ -997,7 +987,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1013,7 +1003,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span> <span class="Constant"> cd</span> <span class="Constant">ef]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># position cursor after 'cd' and hit 'newline' surrounded by paste markers</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">8</span> @@ -1022,7 +1012,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press <span class="Constant">65506</span> <span class="Comment"># end paste</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1039,7 +1029,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> paste-start? indent?:address:boolean<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">indent?:offset</span> *indent?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -1049,18 +1040,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> paste-end? indent?:address:boolean<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">indent?:offset</span> *indent?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] <span class="SalientComment">## helpers</span> -<span class="muRecipe">recipe</span> draw-horizontal [ +<span class="muRecipe">recipe</span> draw-horizontal screen:address:screen, row:number, x:number, right:number [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> style:character, style-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> style-found? diff --git a/html/edit/003-shortcuts.mu.html b/html/edit/003-shortcuts.mu.html index 82273ba7..023f8448 100644 --- a/html/edit/003-shortcuts.mu.html +++ b/html/edit/003-shortcuts.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } +.muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .Special { color: #ff6060; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -43,12 +43,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># just one character in final line</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span> <span class="Constant">cd]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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 [ press tab ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -65,7 +65,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen <span class="Constant"> &lt;insert-character-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -74,7 +75,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-handles-backspace-key [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -82,7 +83,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press backspace ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -104,46 +105,48 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } delete-previous-character?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">8/backspace</span> <span class="muControl">break-unless</span> delete-previous-character? <span class="Constant"> &lt;backspace-character-begin&gt;</span> - editor, screen, go-render?:boolean, backspaced-cell:address:duplex-list<span class="Special"> &lt;- </span>delete-before-cursor editor, screen + editor, screen, go-render?:boolean, backspaced-cell:address:duplex-list:character<span class="Special"> &lt;- </span>delete-before-cursor editor, screen <span class="Constant"> &lt;backspace-character-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="Comment"># editor, screen, go-render?:boolean, backspaced-cell:address:duplex-list &lt;- delete-before-cursor editor:address:editor-data, screen</span> <span class="Comment"># return values:</span> <span class="Comment"># go-render? - whether caller needs to update the screen</span> <span class="Comment"># backspaced-cell - value deleted (or 0 if nothing was deleted) so we can save it for undo, etc.</span> -<span class="muRecipe">recipe</span> delete-before-cursor [ +<span class="muRecipe">recipe</span> delete-before-cursor editor:address:editor-data, screen:address:screen<span class="muRecipe"> -&gt; </span>editor:address:editor-data, screen:address:screen, go-render?:boolean, backspaced-cell:address:duplex-list:character [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + <span class="Constant">load-ingredients</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> <span class="Comment"># if at start of text (before-cursor at § sentinel), return</span> - prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor - <span class="muControl">reply-unless</span> prev, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span> + prev:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex *before-cursor + go-render?, backspaced-cell<span class="Special"> &lt;- </span>copy <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span> + <span class="muControl">reply-unless</span> prev trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[delete-before-cursor]</span> original-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span> editor, scroll?:boolean<span class="Special"> &lt;- </span>move-cursor-coordinates-left editor - backspaced-cell:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor + backspaced-cell:address:duplex-list:character<span class="Special"> &lt;- </span>copy *before-cursor remove-duplex *before-cursor <span class="Comment"># will also neatly trim next/prev pointers in backspaced-cell/*before-cursor</span> *before-cursor<span class="Special"> &lt;- </span>copy prev - <span class="muControl">reply-if</span> scroll?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>, backspaced-cell + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply-if</span> scroll? screen-width:number<span class="Special"> &lt;- </span>screen-width screen cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span> cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span> <span class="Comment"># did we just backspace over a newline?</span> same-row?:boolean<span class="Special"> &lt;- </span>equal cursor-row, original-row - <span class="muControl">reply-unless</span> same-row?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, backspaced-cell + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply-unless</span> same-row? left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + curr:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column curr-column:number<span class="Special"> &lt;- </span>copy cursor-column <span class="Delimiter">{</span> <span class="Comment"># hit right margin? give up and let caller render</span> - at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width - <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, backspaced-cell + at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, right + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply-if</span> at-right? <span class="muControl">break-unless</span> curr <span class="Comment"># newline? done.</span> currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> @@ -156,13 +159,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> <span class="Comment"># we're guaranteed not to be at the right margin</span> screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">32/space</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, backspaced-cell + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> ] -<span class="muRecipe">recipe</span> move-cursor-coordinates-left [ +<span class="muRecipe">recipe</span> move-cursor-coordinates-left editor:address:editor-data<span class="muRecipe"> -&gt; </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - before-cursor:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span> + <span class="Constant">load-ingredients</span> + before-cursor:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> @@ -172,7 +175,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-if</span> at-left-margin? trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[decrementing cursor column]</span> *cursor-column<span class="Special"> &lt;- </span>subtract *cursor-column, <span class="Constant">1</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># if at left margin, we must move to previous row:</span> top-of-screen?:boolean<span class="Special"> &lt;- </span>equal *cursor-row, <span class="Constant">1</span> <span class="Comment"># exclude menu bar</span> @@ -193,28 +197,26 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> previous-character-is-newline? <span class="Comment"># compute length of previous line</span> trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[switching to previous line]</span> - d:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + d:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> end-of-line:number<span class="Special"> &lt;- </span>previous-line-length before-cursor, d *cursor-column<span class="Special"> &lt;- </span>add left, end-of-line - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># case 2: if previous-character was not newline, we're just at a wrapped line</span> trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[wrapping to previous line]</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> *cursor-column<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span> <span class="Comment"># leave room for wrap icon</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, go-render? ] <span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span> <span class="Comment"># the length of the previous line before the 'curr' pointer.</span> -<span class="muRecipe">recipe</span> previous-line-length [ +<span class="muRecipe">recipe</span> previous-line-length curr:address:duplex-list:character, start:address:duplex-list:character<span class="muRecipe"> -&gt; </span>result:number [ <span class="Constant">local-scope</span> - curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - <span class="muControl">reply-unless</span> curr, result + <span class="muControl">reply-unless</span> curr at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start - <span class="muControl">reply-if</span> at-start?, result + <span class="muControl">reply-if</span> at-start? <span class="Delimiter">{</span> curr<span class="Special"> &lt;- </span>prev-duplex curr <span class="muControl">break-unless</span> curr @@ -226,7 +228,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } result<span class="Special"> &lt;- </span>add result, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> result ] <span class="muScenario">scenario</span> editor-clears-last-line-on-backspace [ @@ -234,13 +235,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># just one character in final line</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span> <span class="Constant">cd]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">0</span> <span class="Comment"># cursor at only character in final line</span> press backspace ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -256,19 +257,77 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] +<span class="muScenario">scenario</span> editor-joins-and-wraps-lines-on-backspace [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Comment"># initialize editor with two long-ish but non-wrapping lines</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc def</span> +<span class="Constant">ghi jkl]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + <span class="Comment"># position the cursor at the start of the second and hit backspace</span> + assume-console [ + left-click <span class="Constant">2</span>, <span class="Constant">0</span> + press backspace + ] + run [ + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + ] + <span class="Comment"># resulting single line should wrap correctly</span> + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc defgh↩.</span> + <span class="Constant"> .i jkl .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] +] + +<span class="muScenario">scenario</span> editor-wraps-long-lines-on-backspace [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Comment"># initialize editor in part of the screen with a long line</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc def ghij]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">8/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data + <span class="Comment"># confirm that it wraps</span> + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc def↩ .</span> + <span class="Constant"> . ghij .</span> + <span class="Constant"> .┈┈┈┈┈┈┈┈ .</span> + ] +<span class="Constant"> $clear-trace</span> + <span class="Comment"># position the cursor somewhere in the middle of the top screen line and hit backspace</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">4</span> + press backspace + ] + run [ + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + ] + <span class="Comment"># resulting single line should wrap correctly and not overflow its bounds</span> + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcdef ↩ .</span> + <span class="Constant"> .ghij .</span> + <span class="Constant"> .┈┈┈┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] +] + <span class="Comment"># delete - delete character at cursor</span> <span class="muScenario">scenario</span> editor-handles-delete-key [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ press delete ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -282,7 +341,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press delete ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -298,25 +357,26 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } delete-next-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65522/delete</span> <span class="muControl">break-unless</span> delete-next-character? <span class="Constant"> &lt;delete-character-begin&gt;</span> - editor, screen, go-render?:boolean, deleted-cell:address:duplex-list<span class="Special"> &lt;- </span>delete-at-cursor editor, screen + editor, screen, go-render?:boolean, deleted-cell:address:duplex-list:character<span class="Special"> &lt;- </span>delete-at-cursor editor, screen <span class="Constant"> &lt;delete-character-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> delete-at-cursor [ +<span class="muRecipe">recipe</span> delete-at-cursor editor:address:editor-data, screen:address:screen<span class="muRecipe"> -&gt; </span>editor:address:editor-data, screen:address:screen, go-render?:boolean, deleted-cell:address:duplex-list:character [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - candidate:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor - <span class="muControl">reply-unless</span> candidate, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span> - currc:character<span class="Special"> &lt;- </span>get *candidate, <span class="Constant">value:offset</span> - remove-duplex candidate + <span class="Constant">load-ingredients</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + deleted-cell:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-unless</span> deleted-cell + currc:character<span class="Special"> &lt;- </span>get *deleted-cell, <span class="Constant">value:offset</span> + remove-duplex deleted-cell deleted-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span> - <span class="muControl">reply-if</span> deleted-newline?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, candidate/deleted-cell + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply-if</span> deleted-newline? <span class="Comment"># wasn't a newline? render rest of line</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="Comment"># refresh after remove-duplex above</span> + curr:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="Comment"># refresh after remove-duplex above</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column @@ -325,7 +385,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> <span class="Comment"># hit right margin? give up and let caller render</span> at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width - <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, candidate/deleted-cell + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply-if</span> at-right? <span class="muControl">break-unless</span> curr <span class="Comment"># newline? done.</span> currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> @@ -338,7 +399,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> <span class="Comment"># we're guaranteed not to be at the right margin</span> screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">32/space</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, candidate/deleted-cell + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> ] <span class="Comment"># right arrow</span> @@ -346,7 +407,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-moves-cursor-right-with-key [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -354,7 +415,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -370,7 +431,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } move-to-next-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65514/right-arrow</span> <span class="muControl">break-unless</span> move-to-next-character? <span class="Comment"># if not at end of text</span> - next-cursor:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + next-cursor:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="muControl">break-unless</span> next-cursor <span class="Comment"># scan to next character</span> <span class="Constant"> &lt;move-cursor-begin&gt;</span> @@ -379,15 +440,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">2/right-arrow</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-cursor-coordinates-right [ +<span class="muRecipe">recipe</span> move-cursor-coordinates-right editor:address:editor-data, screen-height:number<span class="muRecipe"> -&gt; </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - before-cursor:address:duplex-list<span class="Special"> &lt;- </span>get *editor <span class="Constant">before-cursor:offset</span> + <span class="Constant">load-ingredients</span> + before-cursor:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor <span class="Constant">before-cursor:offset</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> @@ -400,10 +460,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span> *cursor-column<span class="Special"> &lt;- </span>copy left below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height <span class="Comment"># must be equal</span> - <span class="muControl">reply-unless</span> below-screen?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-unless</span> below-screen? <span class="Constant"> &lt;scroll-down&gt;</span> *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># if the line wraps, move cursor to start of next row</span> <span class="Delimiter">{</span> @@ -412,7 +474,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } at-wrap?:boolean<span class="Special"> &lt;- </span>equal *cursor-column, wrap-column <span class="muControl">break-unless</span> at-wrap? <span class="Comment"># and if next character isn't newline</span> - next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex before-cursor + next:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex before-cursor <span class="muControl">break-unless</span> next next-character:character<span class="Special"> &lt;- </span>get *next, <span class="Constant">value:offset</span> newline?:boolean<span class="Special"> &lt;- </span>equal next-character, <span class="Constant">10/newline</span> @@ -423,18 +485,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply-unless</span> below-screen?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> <span class="Constant"> &lt;scroll-down&gt;</span> *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># otherwise move cursor one character right</span> *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> ] <span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow [ 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># type right-arrow a few times to get to start of second line</span> @@ -445,7 +508,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press right-arrow <span class="Comment"># next line</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> <span class="Comment"># type something and ensure it goes where it should</span> @@ -453,7 +516,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -469,7 +532,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ press right-arrow @@ -479,7 +542,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -493,7 +556,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow [ 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"> &lt;- </span>new <span class="Constant">[abcdef]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -501,7 +564,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press right-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -523,7 +586,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># line just barely wrapping</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># position cursor at last character before wrap and hit right-arrow</span> @@ -532,7 +595,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press right-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -545,7 +608,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press right-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -559,7 +622,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [ 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"> &lt;- </span>new <span class="Constant">[abcdef]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">6/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">1/left</span>, <span class="Constant">6/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -567,7 +630,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press right-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -589,7 +652,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># move to end of line, press right-arrow, type a character</span> @@ -599,7 +662,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># new character should be in next line</span> screen-should-contain [ @@ -619,7 +682,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> editor-moves-cursor-left-with-key [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -628,7 +691,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -645,14 +708,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> move-to-previous-character? trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[left arrow]</span> <span class="Comment"># if not at start of text (before-cursor at § sentinel)</span> - prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor - <span class="muControl">reply-unless</span> prev, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + prev:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex *before-cursor + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-unless</span> prev <span class="Constant"> &lt;move-cursor-begin&gt;</span> editor, go-render?<span class="Special"> &lt;- </span>move-cursor-coordinates-left editor *before-cursor<span class="Special"> &lt;- </span>copy prev undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/left-arrow</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -661,7 +725,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># initialize editor with two lines</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># position cursor at start of second line (so there's no previous newline)</span> @@ -670,7 +734,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press left-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -687,7 +751,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># position cursor further down (so there's a newline before the character at</span> @@ -698,7 +762,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -715,7 +779,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># position cursor at start of text, press left-arrow, then type a character</span> @@ -725,7 +789,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># left-arrow should have had no effect</span> screen-should-contain [ @@ -744,7 +808,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> d] - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># position cursor right after empty line</span> @@ -754,7 +818,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -770,7 +834,7 @@ d] assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize editor with text containing an empty line</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> screen-should-contain [ @@ -786,7 +850,7 @@ d] press left-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -805,7 +869,7 @@ d] 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -813,7 +877,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -826,7 +890,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -845,16 +909,16 @@ d] editor, go-render?<span class="Special"> &lt;- </span>move-to-previous-line editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">3/up-arrow</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-to-previous-line [ +<span class="muRecipe">recipe</span> move-to-previous-line editor:address:editor-data<span class="muRecipe"> -&gt; </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> already-at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *cursor-row, <span class="Constant">1/top</span> @@ -864,21 +928,23 @@ d] <span class="Comment"># if not at newline, move to start of line (previous newline)</span> <span class="Comment"># then scan back another line</span> <span class="Comment"># if either step fails, give up without modifying cursor or coordinates</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor + curr:address:duplex-list:character<span class="Special"> &lt;- </span>copy *before-cursor <span class="Delimiter">{</span> - old:address:duplex-list<span class="Special"> &lt;- </span>copy curr + old:address:duplex-list:character<span class="Special"> &lt;- </span>copy curr c2:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> at-newline?:boolean<span class="Special"> &lt;- </span>equal c2, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> at-newline? - curr:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line curr, editor + curr:address:duplex-list:character<span class="Special"> &lt;- </span>before-previous-line curr, editor no-motion?:boolean<span class="Special"> &lt;- </span>equal curr, old - <span class="muControl">reply-if</span> no-motion?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-if</span> no-motion? <span class="Delimiter">}</span> <span class="Delimiter">{</span> old<span class="Special"> &lt;- </span>copy curr curr<span class="Special"> &lt;- </span>before-previous-line curr, editor no-motion?:boolean<span class="Special"> &lt;- </span>equal curr, old - <span class="muControl">reply-if</span> no-motion?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-if</span> no-motion? <span class="Delimiter">}</span> *before-cursor<span class="Special"> &lt;- </span>copy curr *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span> @@ -888,7 +954,7 @@ d] <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, target-column <span class="muControl">break-if</span> done? - curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + curr:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="muControl">break-unless</span> curr currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span> @@ -898,13 +964,15 @@ d] *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="Comment"># if cursor already at top, scroll up</span> <span class="muControl">break-unless</span> already-at-top? <span class="Constant"> &lt;scroll-up&gt;</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -912,7 +980,7 @@ d] 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"> &lt;- </span>new <span class="Constant">[ab</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -920,7 +988,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -933,7 +1001,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -948,7 +1016,7 @@ d] 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"> &lt;- </span>new [ def] - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -956,7 +1024,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -969,7 +1037,7 @@ def] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -986,7 +1054,7 @@ def] <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># click on the third line and hit up-arrow, so you end up just after a newline</span> @@ -995,7 +1063,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1008,7 +1076,7 @@ def] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1025,7 +1093,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># cursor starts out at (1, 0)</span> @@ -1033,7 +1101,7 @@ def] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1047,7 +1115,7 @@ def] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1066,17 +1134,16 @@ def] editor, go-render?<span class="Special"> &lt;- </span>move-to-next-line editor, screen-height undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">4/down-arrow</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-to-next-line [ +<span class="muRecipe">recipe</span> move-to-next-line editor:address:editor-data, screen-height:number<span class="muRecipe"> -&gt; </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> last-line:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1</span> @@ -1086,7 +1153,7 @@ def] <span class="muControl">break-if</span> already-at-bottom? <span class="Comment"># scan to start of next line, then to right column or until end of line</span> max:number<span class="Special"> &lt;- </span>subtract right, left - next-line:address:duplex-list<span class="Special"> &lt;- </span>before-start-of-next-line *before-cursor, max + next-line:address:duplex-list:character<span class="Special"> &lt;- </span>before-start-of-next-line *before-cursor, max <span class="Delimiter">{</span> <span class="Comment"># already at end of buffer? try to scroll up (so we can see more</span> <span class="Comment"># warnings or sandboxes below)</span> @@ -1094,7 +1161,8 @@ def] <span class="muControl">break-unless</span> no-motion? scroll?:boolean<span class="Special"> &lt;- </span>greater-than *cursor-row, <span class="Constant">1</span> <span class="muControl">break-if</span> scroll?, <span class="Constant">+try-to-scroll:label</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span> *before-cursor<span class="Special"> &lt;- </span>copy next-line @@ -1103,7 +1171,7 @@ def] <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, target-column <span class="muControl">break-if</span> done? - curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + curr:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="muControl">break-unless</span> curr currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span> @@ -1113,18 +1181,19 @@ def] *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Constant"> +try-to-scroll</span> <span class="Constant"> &lt;scroll-down&gt;</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> ] <span class="muScenario">scenario</span> editor-adjusts-column-at-next-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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">de]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ @@ -1132,7 +1201,7 @@ def] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1145,7 +1214,7 @@ def] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1156,78 +1225,13 @@ def] ] ] -<span class="muScenario">scenario</span> editor-scrolls-at-end-on-down-arrow [ - 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"> &lt;- </span>new <span class="Constant">[abc</span> -<span class="Constant">de]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:editor-data -<span class="Constant"> $clear-trace</span> - <span class="Comment"># try to move down past end of text</span> - assume-console [ - left-click <span class="Constant">2</span>, <span class="Constant">0</span> - press down-arrow - ] - run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data - <span class="Constant">3</span>:number<span class="Special"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> - ] - <span class="Comment"># screen should scroll, moving cursor to end of text</span> - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span> - <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span> - ] - assume-console [ - type <span class="Constant">[0]</span> - ] - run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data - ] - screen-should-contain [ - <span class="Constant"> . .</span> - <span class="Constant"> .de0 .</span> -<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> - <span class="Constant"> . .</span> - ] - <span class="Comment"># try to move down again</span> -<span class="Constant"> $clear-trace</span> - assume-console [ - left-click <span class="Constant">2</span>, <span class="Constant">0</span> - press down-arrow - ] - run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data - <span class="Constant">3</span>:number<span class="Special"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> - ] - <span class="Comment"># screen stops scrolling because cursor is already at top</span> - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span> - <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span> - ] - check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> - assume-console [ - type <span class="Constant">[1]</span> - ] - run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data - ] - screen-should-contain [ - <span class="Constant"> . .</span> - <span class="Constant"> .de01 .</span> -<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> - <span class="Constant"> . .</span> - ] -] - <span class="Comment"># ctrl-a/home - move cursor to start of line</span> <span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a [ 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on second line, press ctrl-a</span> @@ -1236,7 +1240,7 @@ def] press ctrl-a ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1256,7 +1260,8 @@ def] move-to-start-of-line editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -1268,20 +1273,21 @@ def] move-to-start-of-line editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-to-start-of-line [ +<span class="muRecipe">recipe</span> move-to-start-of-line editor:address:editor-data [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># update cursor column</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> *cursor-column<span class="Special"> &lt;- </span>copy left <span class="Comment"># update before-cursor</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - init:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + init:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> <span class="Comment"># while not at start of line, move </span> <span class="Delimiter">{</span> at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal *before-cursor, init @@ -1299,7 +1305,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on first line (no newline before), press ctrl-a</span> @@ -1308,7 +1314,7 @@ def] press ctrl-a ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1324,7 +1330,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Constant"> $clear-trace</span> <span class="Comment"># start on second line, press 'home'</span> assume-console [ @@ -1332,7 +1338,7 @@ def] press home ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1348,7 +1354,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on first line (no newline before), press 'home'</span> @@ -1357,7 +1363,7 @@ def] press home ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1375,7 +1381,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on first line, press ctrl-e</span> @@ -1384,7 +1390,7 @@ def] press ctrl-e ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1399,7 +1405,7 @@ def] type <span class="Constant">[z]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1425,7 +1431,8 @@ def] move-to-end-of-line editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -1437,18 +1444,19 @@ def] move-to-end-of-line editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-to-end-of-line [ +<span class="muRecipe">recipe</span> move-to-end-of-line editor:address:editor-data [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + <span class="Constant">load-ingredients</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> <span class="Comment"># while not at start of line, move </span> <span class="Delimiter">{</span> - next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + next:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="muControl">break-unless</span> next <span class="Comment"># end of text</span> nextc:character<span class="Special"> &lt;- </span>get *next, <span class="Constant">value:offset</span> at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal nextc, <span class="Constant">10/newline</span> @@ -1463,7 +1471,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on second line (no newline after), press ctrl-e</span> @@ -1472,7 +1480,7 @@ def] press ctrl-e ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1488,7 +1496,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on first line, press 'end'</span> @@ -1497,7 +1505,7 @@ def] press end ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1513,7 +1521,7 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> <span class="Comment"># start on second line (no newline after), press 'end'</span> @@ -1522,7 +1530,7 @@ def] press end ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1540,14 +1548,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start on second line, press ctrl-u</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">2</span> press ctrl-u ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes to start of line</span> screen-should-contain [ @@ -1564,20 +1572,21 @@ def] delete-to-start-of-line?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">21/ctrl-u</span> <span class="muControl">break-unless</span> delete-to-start-of-line? <span class="Constant"> &lt;delete-to-start-of-line-begin&gt;</span> - deleted-cells:address:duplex-list<span class="Special"> &lt;- </span>delete-to-start-of-line editor + deleted-cells:address:duplex-list:character<span class="Special"> &lt;- </span>delete-to-start-of-line editor <span class="Constant"> &lt;delete-to-start-of-line-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> delete-to-start-of-line [ +<span class="muRecipe">recipe</span> delete-to-start-of-line editor:address:editor-data<span class="muRecipe"> -&gt; </span>result:address:duplex-list:character [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># compute range to delete</span> - init:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - start:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor - end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + init:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + start:address:duplex-list:character<span class="Special"> &lt;- </span>copy *before-cursor + end:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor <span class="Delimiter">{</span> at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal start, init <span class="muControl">break-if</span> at-start-of-text? @@ -1589,28 +1598,27 @@ def] <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># snip it out</span> - result:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start + result:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex start remove-duplex-between start, end <span class="Comment"># adjust cursor</span> - *before-cursor<span class="Special"> &lt;- </span>prev-duplex end + *before-cursor<span class="Special"> &lt;- </span>copy start left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> *cursor-column<span class="Special"> &lt;- </span>copy left - <span class="muControl">reply</span> result ] <span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-2 [ 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start on first line (no newline before), press ctrl-u</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">2</span> press ctrl-u ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes to start of line</span> screen-should-contain [ @@ -1626,14 +1634,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start past end of line, press ctrl-u</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">3</span> press ctrl-u ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes to start of line</span> screen-should-contain [ @@ -1649,14 +1657,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start past end of final line, press ctrl-u</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">3</span> press ctrl-u ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes to start of line</span> screen-should-contain [ @@ -1674,14 +1682,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start on first line, press ctrl-k</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> press ctrl-k ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes to end of line</span> screen-should-contain [ @@ -1698,18 +1706,19 @@ def] delete-to-end-of-line?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">11/ctrl-k</span> <span class="muControl">break-unless</span> delete-to-end-of-line? <span class="Constant"> &lt;delete-to-end-of-line-begin&gt;</span> - deleted-cells:address:duplex-list<span class="Special"> &lt;- </span>delete-to-end-of-line editor + deleted-cells:address:duplex-list:character<span class="Special"> &lt;- </span>delete-to-end-of-line editor <span class="Constant"> &lt;delete-to-end-of-line-end&gt;</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> delete-to-end-of-line [ +<span class="muRecipe">recipe</span> delete-to-end-of-line editor:address:editor-data<span class="muRecipe"> -&gt; </span>result:address:duplex-list:character [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># compute range to delete</span> - start:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span> - end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start + start:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span> + end:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex start <span class="Delimiter">{</span> at-end-of-text?:boolean<span class="Special"> &lt;- </span>equal end, <span class="Constant">0/null</span> <span class="muControl">break-if</span> at-end-of-text? @@ -1720,23 +1729,22 @@ def] <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># snip it out</span> - result:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start + result<span class="Special"> &lt;- </span>next-duplex start remove-duplex-between start, end - <span class="muControl">reply</span> result ] <span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-2 [ 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start on second line (no newline after), press ctrl-k</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">1</span> press ctrl-k ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes to end of line</span> screen-should-contain [ @@ -1752,14 +1760,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start at end of line</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">2</span> press ctrl-k ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes just last character</span> screen-should-contain [ @@ -1775,14 +1783,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start past end of line</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">3</span> press ctrl-k ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes nothing</span> screen-should-contain [ @@ -1798,14 +1806,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start at end of text</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">2</span> press ctrl-k ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes just the final character</span> screen-should-contain [ @@ -1821,14 +1829,14 @@ def] 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"> &lt;- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Comment"># start past end of text</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">3</span> press ctrl-k ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># cursor deletes nothing</span> screen-should-contain [ @@ -1850,7 +1858,7 @@ def] <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -1863,7 +1871,7 @@ def] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen slides by one line</span> screen-should-contain [ @@ -1876,29 +1884,25 @@ def] <span class="muRecipe">after</span> <span class="Constant">&lt;scroll-down&gt;</span> [ trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[scroll down]</span> - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> max:number<span class="Special"> &lt;- </span>subtract right, left - old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen + old-top:address:duplex-list:character<span class="Special"> &lt;- </span>copy *top-of-screen *top-of-screen<span class="Special"> &lt;- </span>before-start-of-next-line *top-of-screen, max no-movement?:boolean<span class="Special"> &lt;- </span>equal old-top, *top-of-screen - <span class="Comment"># Hack: this reply doesn't match one of the locations of &lt;scroll-down&gt;,</span> - <span class="Comment"># directly within insert-at-cursor. However, I'm unable to trigger the</span> - <span class="Comment"># error.. If necessary create a duplicate copy of &lt;scroll-down&gt; with the</span> - <span class="Comment"># right 'reply-if'.</span> - <span class="muControl">reply-if</span> no-movement?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-if</span> no-movement? ] <span class="Comment"># takes a pointer into the doubly-linked list, scans ahead at most 'max'</span> <span class="Comment"># positions until the next newline</span> <span class="Comment"># beware: never return null pointer.</span> -<span class="muRecipe">recipe</span> before-start-of-next-line [ +<span class="muRecipe">recipe</span> before-start-of-next-line original:address:duplex-list:character, max:number<span class="muRecipe"> -&gt; </span>curr:address:duplex-list:character [ <span class="Constant">local-scope</span> - original:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - max:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>copy original + curr:address:duplex-list:character<span class="Special"> &lt;- </span>copy original <span class="Comment"># skip the initial newline if it exists</span> <span class="Delimiter">{</span> c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> @@ -1931,7 +1935,7 @@ def] <span class="Constant">g</span> <span class="Constant">h</span> <span class="Constant">i]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> @@ -1944,7 +1948,7 @@ def] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -1963,14 +1967,14 @@ def] <span class="Constant">k</span> <span class="Constant">l</span> <span class="Constant">m]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at last line, then try to move further down</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">0</span> press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line containing a wrap icon</span> screen-should-contain [ @@ -1984,7 +1988,7 @@ def] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -2002,14 +2006,14 @@ def] <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdef]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at end, type a character</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">4</span> type <span class="Constant">[g]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -2032,14 +2036,14 @@ def] <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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">3</span>, <span class="Constant">4</span> type [ ] ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -2063,14 +2067,14 @@ def] <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdefgh]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at end of screen and try to move right</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">3</span> press right-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -2095,14 +2099,14 @@ def] <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at end of screen and try to move right</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">3</span> press right-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -2119,6 +2123,71 @@ def] ] ] +<span class="muScenario">scenario</span> editor-scrolls-at-end-on-down-arrow [ + 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"> &lt;- </span>new <span class="Constant">[abc</span> +<span class="Constant">de]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + <span class="Comment"># try to move down past end of text</span> + assume-console [ + left-click <span class="Constant">2</span>, <span class="Constant">0</span> + press down-arrow + ] + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># screen should scroll, moving cursor to end of text</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span> + <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span> + ] + assume-console [ + type <span class="Constant">[0]</span> + ] + run [ + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .de0 .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + <span class="Comment"># try to move down again</span> +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">2</span>, <span class="Constant">0</span> + press down-arrow + ] + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># screen stops scrolling because cursor is already at top</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span> + <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span> + ] + check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> + assume-console [ + type <span class="Constant">[1]</span> + ] + run [ + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .de01 .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] +] + <span class="muScenario">scenario</span> editor-combines-page-and-line-scroll [ <span class="Comment"># screen has 1 line for menu + 3 lines</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> @@ -2130,7 +2199,7 @@ def] <span class="Constant">e</span> <span class="Constant">f</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># scroll down one page and one line</span> assume-console [ press page-down @@ -2138,7 +2207,7 @@ def] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen scrolls down 3 lines</span> screen-should-contain [ @@ -2159,7 +2228,7 @@ def] <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2172,7 +2241,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen slides by one line</span> screen-should-contain [ @@ -2185,33 +2254,33 @@ def] <span class="muRecipe">after</span> <span class="Constant">&lt;scroll-up&gt;</span> [ trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[scroll up]</span> - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + old-top:address:duplex-list:character<span class="Special"> &lt;- </span>copy *top-of-screen *top-of-screen<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor no-movement?:boolean<span class="Special"> &lt;- </span>equal old-top, *top-of-screen - <span class="muControl">reply-if</span> no-movement?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> + go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply-if</span> no-movement? ] <span class="Comment"># takes a pointer into the doubly-linked list, scans back to before start of</span> <span class="Comment"># previous *wrapped* line</span> <span class="Comment"># beware: never return null pointer</span> -<span class="muRecipe">recipe</span> before-previous-line [ +<span class="muRecipe">recipe</span> before-previous-line curr:address:duplex-list:character, editor:address:editor-data<span class="muRecipe"> -&gt; </span>curr:address:duplex-list:character [ <span class="Constant">local-scope</span> - curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span> <span class="Comment"># compute max, number of characters to skip</span> <span class="Comment"># 1 + len%(width-1)</span> <span class="Comment"># except rotate second term to vary from 1 to width-1 rather than 0 to width-2</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span> max-line-length:number<span class="Special"> &lt;- </span>subtract right, left, <span class="Constant">-1/exclusive-right</span>, <span class="Constant">1/wrap-icon</span> - sentinel:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + sentinel:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> len:number<span class="Special"> &lt;- </span>previous-line-length curr, sentinel <span class="Delimiter">{</span> <span class="muControl">break-if</span> len <span class="Comment"># empty line; just skip this newline</span> - prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr + prev:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex curr <span class="muControl">reply-unless</span> prev, curr <span class="muControl">reply</span> prev <span class="Delimiter">}</span> @@ -2227,7 +2296,7 @@ def] <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max <span class="muControl">break-if</span> done? - prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr + prev:address:duplex-list:character<span class="Special"> &lt;- </span>prev-duplex curr <span class="muControl">break-unless</span> prev curr<span class="Special"> &lt;- </span>copy prev count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span> @@ -2245,7 +2314,7 @@ def] <span class="Constant">g</span> <span class="Constant">h</span> <span class="Constant">i]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> @@ -2257,7 +2326,7 @@ def] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2270,7 +2339,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -2289,13 +2358,13 @@ def] <span class="Constant">k</span> <span class="Constant">l</span> <span class="Constant">m]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at top of second page</span> assume-console [ press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2309,7 +2378,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -2324,7 +2393,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -2339,7 +2408,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -2362,7 +2431,7 @@ def] <span class="Constant">g</span> <span class="Constant">h</span> <span class="Constant">i]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .abcde↩ .</span> @@ -2374,7 +2443,7 @@ def] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2387,7 +2456,7 @@ def] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows partial wrapped line</span> screen-should-contain [ @@ -2408,12 +2477,12 @@ def] c d e] - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> assume-console [ press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2425,7 +2494,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2437,7 +2506,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2456,13 +2525,13 @@ e] <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at top of second page</span> assume-console [ press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2475,7 +2544,7 @@ e] press left-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -2500,7 +2569,7 @@ e] <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2515,7 +2584,7 @@ e] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen slides by one line</span> screen-should-contain [ @@ -2529,7 +2598,7 @@ e] press up-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen remains unchanged</span> screen-should-contain [ @@ -2548,7 +2617,7 @@ e] <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2560,7 +2629,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows next page</span> screen-should-contain [ @@ -2575,15 +2644,15 @@ e] <span class="Delimiter">{</span> page-down?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">6/ctrl-f</span> <span class="muControl">break-unless</span> page-down? - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + old-top:address:duplex-list:character<span class="Special"> &lt;- </span>copy *top-of-screen <span class="Constant"> &lt;move-cursor-begin&gt;</span> page-down editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top - <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>not no-movement? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -2591,28 +2660,28 @@ e] <span class="Delimiter">{</span> page-down?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65518/page-down</span> <span class="muControl">break-unless</span> page-down? - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + old-top:address:duplex-list:character<span class="Special"> &lt;- </span>copy *top-of-screen <span class="Constant"> &lt;move-cursor-begin&gt;</span> page-down editor undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top - <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>not no-movement? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] <span class="Comment"># page-down skips entire wrapped lines, so it can't scroll past lines</span> <span class="Comment"># taking up the entire screen</span> -<span class="muRecipe">recipe</span> page-down [ +<span class="muRecipe">recipe</span> page-down editor:address:editor-data<span class="muRecipe"> -&gt; </span>editor:address:editor-data [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># if editor contents don't overflow screen, do nothing</span> - bottom-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">bottom-of-screen:offset</span> - <span class="muControl">reply-unless</span> bottom-of-screen, editor/same-as-ingredient:<span class="Constant">0</span> + bottom-of-screen:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">bottom-of-screen:offset</span> + <span class="muControl">reply-unless</span> bottom-of-screen <span class="Comment"># if not, position cursor at final character</span> - before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> *before-cursor<span class="Special"> &lt;- </span>prev-duplex bottom-of-screen <span class="Comment"># keep one line in common with previous page</span> <span class="Delimiter">{</span> @@ -2623,16 +2692,15 @@ e] <span class="Delimiter">}</span> <span class="Comment"># move cursor and top-of-screen to start of that line</span> move-to-start-of-line editor - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *top-of-screen<span class="Special"> &lt;- </span>copy *before-cursor - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span> ] <span class="muScenario">scenario</span> editor-does-not-scroll-past-end [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">b]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> @@ -2645,7 +2713,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen remains unmodified</span> screen-should-contain [ @@ -2664,7 +2732,7 @@ e] <span class="Constant">b</span> <span class="Constant">cdefgh]</span> <span class="Comment"># editor screen triggers wrap of last line</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -2677,7 +2745,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows entire wrapped line</span> screen-should-contain [ @@ -2695,7 +2763,7 @@ e] <span class="Comment"># and still has something left over</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">bcdefgh]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -2708,7 +2776,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows entire wrapped line</span> screen-should-contain [ @@ -2727,7 +2795,7 @@ e] <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2739,7 +2807,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows next page</span> screen-should-contain [ @@ -2753,7 +2821,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows original page again</span> screen-should-contain [ @@ -2768,15 +2836,15 @@ e] <span class="Delimiter">{</span> page-up?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">2/ctrl-b</span> <span class="muControl">break-unless</span> page-up? - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + old-top:address:duplex-list:character<span class="Special"> &lt;- </span>copy *top-of-screen <span class="Constant"> &lt;move-cursor-begin&gt;</span> editor<span class="Special"> &lt;- </span>page-up editor, screen-height undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top - <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>not no-movement? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] @@ -2784,36 +2852,34 @@ e] <span class="Delimiter">{</span> page-up?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65519/page-up</span> <span class="muControl">break-unless</span> page-up? - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + old-top:address:duplex-list:character<span class="Special"> &lt;- </span>copy *top-of-screen <span class="Constant"> &lt;move-cursor-begin&gt;</span> editor<span class="Special"> &lt;- </span>page-up editor, screen-height undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span> <span class="Constant"> &lt;move-cursor-end&gt;</span> no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top <span class="Comment"># don't bother re-rendering if nothing changed. todo: test this</span> - <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + go-render?<span class="Special"> &lt;- </span>not no-movement? + <span class="muControl">reply</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> page-up [ +<span class="muRecipe">recipe</span> page-up editor:address:editor-data, screen-height:number<span class="muRecipe"> -&gt; </span>editor:address:editor-data [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> max:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1/menu-bar</span>, <span class="Constant">1/overlapping-line</span> count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max <span class="muControl">break-if</span> done? - prev:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor + prev:address:duplex-list:character<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor <span class="muControl">break-unless</span> prev *top-of-screen<span class="Special"> &lt;- </span>copy prev count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span> ] <span class="muScenario">scenario</span> editor-can-scroll-up-multiple-pages [ @@ -2828,7 +2894,7 @@ e] <span class="Constant">f</span> <span class="Constant">g</span> <span class="Constant">h]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2841,7 +2907,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows third page</span> screen-should-contain [ @@ -2855,7 +2921,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows second page</span> screen-should-contain [ @@ -2869,7 +2935,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows original page again</span> screen-should-contain [ @@ -2895,7 +2961,7 @@ e] <span class="Constant">n</span> <span class="Constant">o]</span> <span class="Comment"># editor screen triggers wrap of last line</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -2912,7 +2978,7 @@ e] press down-arrow ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows entire wrapped line</span> screen-should-contain [ @@ -2928,7 +2994,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen resets</span> screen-should-contain [ @@ -2948,7 +3014,7 @@ e] <span class="Comment"># and still has something left over</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">bcdefgh]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -2961,7 +3027,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen shows entire wrapped line</span> screen-should-contain [ @@ -2975,7 +3041,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># screen resets</span> screen-should-contain [ @@ -2998,7 +3064,7 @@ e] <span class="Constant">gxx</span> <span class="Constant">hxx</span> <span class="Constant">]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .axx .</span> @@ -3009,7 +3075,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -3021,7 +3087,7 @@ e] press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -3034,7 +3100,7 @@ e] press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -3056,7 +3122,7 @@ exy fxy gxy ] - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .axy .</span> @@ -3067,7 +3133,7 @@ gxy press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -3079,7 +3145,7 @@ gxy press page-down ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -3092,7 +3158,7 @@ gxy press page-up ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html index 406c19a9..172b1dcc 100644 --- a/html/edit/004-programming-environment.mu.html +++ b/html/edit/004-programming-environment.mu.html @@ -13,16 +13,16 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .Special { color: #ff6060; } -.muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .CommentedCode { color: #6c6c6c; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.muScenario { color: #00af00; } --> </style> @@ -46,7 +46,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } initial-sandbox:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> hide-screen <span class="Constant">0/screen</span> env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox - env<span class="Special"> &lt;- </span>restore-sandboxes env render-all <span class="Constant">0/screen</span>, env event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env <span class="Comment"># never gets here</span> @@ -58,15 +57,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } sandbox-in-focus?:boolean <span class="Comment"># false =&gt; cursor in recipes; true =&gt; cursor in current-sandbox</span> ] -<span class="muRecipe">recipe</span> new-programming-environment [ +<span class="muRecipe">recipe</span> new-programming-environment screen:address:screen, initial-recipe-contents:address:array:character, initial-sandbox-contents:address:array:character<span class="muRecipe"> -&gt; </span>result:address:programming-environment-data [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - initial-recipe-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - initial-sandbox-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> width:number<span class="Special"> &lt;- </span>screen-width screen height:number<span class="Special"> &lt;- </span>screen-height screen <span class="Comment"># top menu</span> - result:address:programming-environment-data<span class="Special"> &lt;- </span>new <span class="Constant">programming-environment-data:type</span> + result<span class="Special"> &lt;- </span>new <span class="Constant">programming-environment-data:type</span> draw-horizontal screen, <span class="Constant">0</span>, <span class="Constant">0/left</span>, width, <span class="Constant">32/space</span>, <span class="Constant">0/black</span>, <span class="Constant">238/grey</span> button-start:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">20</span> button-on-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-start, <span class="Constant">0</span> @@ -84,15 +81,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } new-left:number<span class="Special"> &lt;- </span>add divider, <span class="Constant">1</span> current-sandbox:address:address:editor-data<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">current-sandbox:offset</span> *current-sandbox<span class="Special"> &lt;- </span>new-editor initial-sandbox-contents, screen, new-left, width/right -<span class="Constant"> +programming-environment-initialization</span> - <span class="muControl">reply</span> result ] -<span class="muRecipe">recipe</span> event-loop [ +<span class="muRecipe">recipe</span> event-loop screen:address:screen, console:address:console, env:address:programming-environment-data [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span> current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span> sandbox-in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span> @@ -222,10 +215,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> resize [ +<span class="muRecipe">recipe</span> resize screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>env:address:programming-environment-data [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> clear-screen screen <span class="Comment"># update screen dimensions</span> width:number<span class="Special"> &lt;- </span>screen-width screen divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span> @@ -249,16 +241,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *cursor-row<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> cursor-column:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">cursor-column:offset</span> *cursor-column<span class="Special"> &lt;- </span>copy *left - <span class="muControl">reply</span> env/same-as-ingredient:<span class="Constant">1</span> ] <span class="muScenario">scenario</span> point-at-multiple-editors [ - $close-trace <span class="Comment"># trace too long</span> + 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> <span class="Comment"># initialize both halves of screen</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># focus on both sides</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> @@ -266,7 +257,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># check cursor column in each</span> run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data <span class="Constant">4</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">recipes:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">4</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> <span class="Constant">6</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span> @@ -279,12 +270,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> edit-multiple-editors [ - $close-trace <span class="Comment"># trace too long</span> + 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> <span class="Comment"># initialize both halves of screen</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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 <span class="Comment"># type one letter in each of them</span> assume-console [ @@ -294,7 +285,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data <span class="Constant">4</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">recipes:offset</span> <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">4</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> <span class="Constant">6</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span> @@ -312,7 +303,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># show the cursor at the right window</span> run [ - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] screen-should-contain [ <span class="Constant"> . run (F4) .</span> @@ -323,12 +314,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> multiple-editors-cover-only-their-own-areas [ - $close-trace <span class="Comment"># trace too long</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">60/width</span>, <span class="Constant">10/height</span> run [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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 ] <span class="Comment"># divider isn't messed up</span> @@ -342,17 +333,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> editor-in-focus-keeps-cursor [ - $close-trace <span class="Comment"># trace too long</span> + 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> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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 <span class="Comment"># initialize programming environment and highlight cursor</span> assume-console <span class="Constant">[]</span> run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] <span class="Comment"># is cursor at the right place?</span> screen-should-contain [ @@ -366,8 +357,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[z]</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] <span class="Comment"># cursor should still be right</span> screen-should-contain [ @@ -379,13 +370,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> backspace-in-sandbox-editor-joins-lines [ - $close-trace <span class="Comment"># trace too long</span> + 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> <span class="Comment"># initialize sandbox side with two lines</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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 screen-should-contain [ <span class="Constant"> . run (F4) .</span> @@ -400,8 +391,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press backspace ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] <span class="Comment"># cursor moves to end of old line</span> screen-should-contain [ @@ -412,10 +403,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="muRecipe">recipe</span> render-all [ +<span class="muRecipe">recipe</span> render-all screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[render all]</span> hide-screen screen <span class="Comment"># top menu</span> @@ -444,13 +434,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus? <span class="Comment">#</span> show-screen screen - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> render-recipes [ +<span class="muRecipe">recipe</span> render-recipes screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render recipes]</span> recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span> <span class="Comment"># render recipes</span> @@ -464,33 +452,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span> row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> clear-screen-from screen, row, left, left, right - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">recipe</span> render-sandbox-side [ +<span class="muRecipe">recipe</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span> left:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span> right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span> row:number, column:number, screen, current-sandbox<span class="Special"> &lt;- </span>render screen, current-sandbox clear-line-delimited screen, column, right row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> - <span class="Comment"># draw solid line after recipes (you'll see why in later layers)</span> + <span class="Comment"># draw solid line after code (you'll see why in later layers)</span> draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal</span> row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> clear-screen-from screen, row, left, left, right - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> update-cursor [ +<span class="muRecipe">recipe</span> update-cursor screen:address:screen, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - recipes:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - current-sandbox:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - sandbox-in-focus?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> sandbox-in-focus? cursor-row:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-row:offset</span> @@ -502,21 +484,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } cursor-column:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-column:offset</span> <span class="Delimiter">}</span> screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="Comment"># row, screen &lt;- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number</span> <span class="Comment"># print a string '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">recipe</span> render-string [ +<span class="muRecipe">recipe</span> render-string screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">5</span>, screen/same-as-ingredient:<span class="Constant">0</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> s column:number<span class="Special"> &lt;- </span>copy left screen<span class="Special"> &lt;- </span>move-cursor screen, row, column screen-height:number<span class="Special"> &lt;- </span>screen-height screen @@ -568,20 +543,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-if</span> was-at-left? row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> <span class="Delimiter">}</span> - move-cursor row, left - <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">5</span>, screen/same-as-ingredient:<span class="Constant">0</span> + move-cursor screen, row, left ] -<span class="Comment"># row, screen &lt;- render-code-string screen:address, s:address:array:character, left:number, right:number, row:number</span> <span class="Comment"># like 'render-string' but with colorization for comments like in the editor</span> -<span class="muRecipe">recipe</span> render-code-string [ +<span class="muRecipe">recipe</span> render-code-string screen:address:screen, s:address:array:character, left:number, right:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> s color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span> column:number<span class="Special"> &lt;- </span>copy left screen<span class="Special"> &lt;- </span>move-cursor screen, row, column @@ -635,8 +604,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-if</span> was-at-left? row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> <span class="Delimiter">}</span> - move-cursor row, left - <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> + move-cursor screen, row, left ] <span class="Comment"># ctrl-l - redraw screen (just in case it printed junk somehow)</span> @@ -667,12 +635,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># ctrl-x - maximize/unmaximize the side with focus</span> <span class="muScenario">scenario</span> maximize-side [ - $close-trace <span class="Comment"># trace too long</span> + 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> <span class="Comment"># initialize both halves of screen</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character screen<span class="Special"> &lt;- </span>render-all screen, <span class="Constant">3</span>:address:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> @@ -685,7 +653,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-x ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># only left side visible</span> screen-should-contain [ @@ -699,7 +667,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-x ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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> @@ -733,11 +701,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> maximize [ +<span class="muRecipe">recipe</span> maximize screen:address:screen, console:address:console, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen, console:address:console [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> hide-screen screen <span class="Comment"># maximize one of the sides</span> maximized?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">maximized?:offset</span> @@ -760,7 +726,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env <span class="Delimiter">}</span> show-screen screen - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">1</span> ] <span class="Comment"># when maximized, wait for any event and simply unmaximize</span> @@ -794,12 +759,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## helpers</span> -<span class="muRecipe">recipe</span> draw-vertical [ +<span class="muRecipe">recipe</span> draw-vertical screen:address:screen, col:number, y:number, bottom:number [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - col:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> style:character, style-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> style-found? diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index 7115ca00..3fdab8a0 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } -.muData { color: #ffff00; } -.Special { color: #ff6060; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } +.Special { color: #ff6060; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.muScenario { color: #00af00; } --> </style> @@ -39,6 +39,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># (non-editable) sandboxes below the editor, showing the result and a maybe</span> <span class="Comment"># few other things.</span> +<span class="muRecipe">recipe!</span> main [ + <span class="Constant">local-scope</span> + open-console + initial-recipe:address:array:character<span class="Special"> &lt;- </span>restore <span class="Constant">[recipes.mu]</span> + initial-sandbox:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> + hide-screen <span class="Constant">0/screen</span> + env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox + env<span class="Special"> &lt;- </span>restore-sandboxes env + render-all <span class="Constant">0/screen</span>, env + event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env + <span class="Comment"># never gets here</span> +] + <span class="muData">container</span> programming-environment-data [ sandbox:address:sandbox-data <span class="Comment"># list of sandboxes, from top to bottom</span> ] @@ -56,19 +69,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> run-and-show-results [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Comment"># recipe editor is empty</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Comment"># sandbox editor contains an instruction without storing outputs</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[divide-with-remainder 11, 3]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors</span> assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># check that screen prints the results</span> screen-should-contain [ @@ -111,7 +124,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># check that screen prints the results</span> screen-should-contain [ @@ -131,8 +144,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># hook into event-loop recipe: read non-unicode keypress from k, process it if</span> -<span class="Comment"># necessary, then go to next level</span> <span class="muRecipe">after</span> <span class="Constant">&lt;global-keypress&gt;</span> [ <span class="Comment"># F4? load all code and run all sandboxes.</span> <span class="Delimiter">{</span> @@ -153,12 +164,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> run-sandboxes [ +<span class="muRecipe">recipe</span> run-sandboxes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -&gt; </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - stop?:boolean, env, screen<span class="Special"> &lt;- </span>update-recipes env, screen - <span class="muControl">reply-if</span> stop?, <span class="Constant">1/errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> + <span class="Constant">load-ingredients</span> + errors-found?:boolean, env, screen<span class="Special"> &lt;- </span>update-recipes env, screen + <span class="muControl">reply-if</span> errors-found? <span class="Comment"># check contents of right editor (sandbox)</span> current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span> <span class="Delimiter">{</span> @@ -175,9 +185,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *next<span class="Special"> &lt;- </span>copy *dest *dest<span class="Special"> &lt;- </span>copy new-sandbox <span class="Comment"># clear sandbox editor</span> - init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">data:offset</span> + init:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">data:offset</span> *init<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167/§</span>, <span class="Constant">0/tail</span> - top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">top-of-screen:offset</span> *top-of-screen<span class="Special"> &lt;- </span>copy *init <span class="Delimiter">}</span> <span class="Comment"># save all sandboxes before running, just in case we die when running</span> @@ -186,49 +196,45 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> curr - update-sandbox curr + curr<span class="Special"> &lt;- </span>update-sandbox curr curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> <span class="Constant">0/no-errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> + errors-found?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> ] <span class="Comment"># copy code from recipe editor, persist, load into mu</span> -<span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">recipe</span> update-recipes [ +<span class="Comment"># replaced in a later layer (whereupon errors-found? will actually be set)</span> +<span class="muRecipe">recipe</span> update-recipes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -&gt; </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span> in:address:array:character<span class="Special"> &lt;- </span>editor-contents recipes - save <span class="Constant">[recipes.mu]</span>, in + save <span class="Constant">[recipes.mu]</span>, in <span class="Comment"># newlayer: persistence</span> reload in - <span class="muControl">reply</span> <span class="Constant">0/no-errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> + errors-found?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">recipe</span> update-sandbox [ +<span class="muRecipe">recipe</span> update-sandbox sandbox:address:sandbox-data<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> - sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span> response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response:offset</span> fake-screen:address:address:screen<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">screen:offset</span> *response, _, *fake-screen<span class="Special"> &lt;- </span>run-interactive data ] -<span class="muRecipe">recipe</span> update-status [ +<span class="muRecipe">recipe</span> update-status screen:address:screen, msg:address:array:character, color:number<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - msg:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0</span>, <span class="Constant">2</span> screen<span class="Special"> &lt;- </span>print-string screen, msg, color, <span class="Constant">238/grey/background</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> save-sandboxes [ +<span class="muRecipe">recipe</span> save-sandboxes env:address:programming-environment-data [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span> <span class="Comment"># first clear previous versions, in case we deleted some sandbox</span> $system <span class="Constant">[rm lesson/[0-9]</span>* &gt;/dev/null <span class="Constant">2</span>&gt;/dev/null] <span class="Comment"># some shells can't handle '&gt;&amp;'</span> @@ -252,10 +258,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe!</span> render-sandbox-side [ +<span class="muRecipe">recipe!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</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> current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span> left:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span> @@ -267,20 +272,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span> row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, sandbox, left, right, row clear-rest-of-screen screen, row, left, left, right - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> render-sandboxes [ +<span class="muRecipe">recipe</span> render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> sandbox, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> sandbox screen-height:number<span class="Special"> &lt;- </span>screen-height screen at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height - <span class="muControl">reply-if</span> at-bottom?:boolean, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> + <span class="muControl">reply-if</span> at-bottom?:boolean <span class="Comment"># render sandbox menu</span> row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> screen<span class="Special"> &lt;- </span>move-cursor screen, row, left @@ -301,7 +301,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } sandbox-response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response:offset</span> <span class="Constant"> &lt;render-sandbox-results&gt;</span> <span class="Delimiter">{</span> - sandbox-screen:address<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">screen:offset</span> + sandbox-screen:address:screen<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">screen:offset</span> empty-screen?:boolean<span class="Special"> &lt;- </span>fake-screen-is-empty? sandbox-screen <span class="muControl">break-if</span> empty-screen? row, screen<span class="Special"> &lt;- </span>render-screen screen, sandbox-screen, left, right, row @@ -314,19 +314,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> <span class="Constant"> +render-sandbox-end</span> at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height - <span class="muControl">reply-if</span> at-bottom?, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> + <span class="muControl">reply-if</span> at-bottom? <span class="Comment"># draw solid line after sandbox</span> draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span> <span class="Comment"># draw next sandbox</span> next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, next-sandbox, left, right, row - <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> ] <span class="Comment"># assumes programming environment has no sandboxes; restores them from previous session</span> -<span class="muRecipe">recipe</span> restore-sandboxes [ +<span class="muRecipe">recipe</span> restore-sandboxes env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>env:address:programming-environment-data [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># read all scenarios, pushing them to end of a list of scenarios</span> suffix:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[.out]</span> idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> @@ -352,29 +351,23 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } curr<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">next-sandbox:offset</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> env/same-as-ingredient:<span class="Constant">0</span> ] -<span class="Comment"># row, screen &lt;- render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number</span> <span class="Comment"># print the fake sandbox screen to 'screen' with appropriate delimiters</span> <span class="Comment"># leave cursor at start of next line</span> -<span class="muRecipe">recipe</span> render-screen [ +<span class="muRecipe">recipe</span> render-screen screen:address:screen, sandbox-screen:address:screen, left:number, right:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - s:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">reply-unless</span> sandbox-screen <span class="Comment"># print 'screen:'</span> header:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[screen:]</span> row<span class="Special"> &lt;- </span>render-string screen, header, left, right, <span class="Constant">245/grey</span>, row screen<span class="Special"> &lt;- </span>move-cursor screen, row, left - <span class="Comment"># start printing s</span> + <span class="Comment"># start printing sandbox-screen</span> column:number<span class="Special"> &lt;- </span>copy left - s-width:number<span class="Special"> &lt;- </span>screen-width s - s-height:number<span class="Special"> &lt;- </span>screen-height s - buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *s, <span class="Constant">data:offset</span> + s-width:number<span class="Special"> &lt;- </span>screen-width sandbox-screen + s-height:number<span class="Special"> &lt;- </span>screen-height sandbox-screen + buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *sandbox-screen, <span class="Constant">data:offset</span> stop-printing:number<span class="Special"> &lt;- </span>add left, s-width, <span class="Constant">3</span> max-column:number<span class="Special"> &lt;- </span>min stop-printing, right i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> @@ -424,36 +417,33 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span> ] <span class="muScenario">scenario</span> run-updates-results [ - $close-trace <span class="Comment"># trace too long</span> + 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">12/height</span> <span class="Comment"># define a recipe (no indent for the 'add' line below so column numbers are more obvious)</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant">z:number &lt;- add 2, 2</span> +<span class="Constant">reply z</span> <span class="Constant">]</span>] <span class="Comment"># sandbox editor contains an instruction without storing outputs</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors</span> assume-console [ press F4 ] - run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - ] - <span class="Comment"># check that screen prints the results</span> + 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"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> .z:number &lt;- add 2, 2 ┊ x.</span> - <span class="Constant"> .] ┊foo .</span> - <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .</span> - <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .reply z ┊foo .</span> + <span class="Constant"> .] ┊4 .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] <span class="Comment"># make a change (incrementing one of the args to 'add'), then rerun</span> @@ -464,7 +454,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># check that screen updates the result on the right</span> screen-should-contain [ @@ -472,27 +462,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . ┊ .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> .z:number &lt;- add 2, 3 ┊ x.</span> - <span class="Constant"> .] ┊foo .</span> - <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊5 .</span> - <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .reply z ┊foo .</span> + <span class="Constant"> .] ┊5 .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> run-instruction-manages-screen-per-sandbox [ - $close-trace <span class="Comment"># trace too long</span> + 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">20/height</span> <span class="Comment"># left editor is empty</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an instruction</span> - <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen, 4]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editor</span> assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># check that it prints a little toy screen</span> screen-should-contain [ @@ -500,7 +490,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ x.</span> - <span class="Constant"> . ┊print-integer screen:address, 4 .</span> + <span class="Constant"> . ┊print-integer screen, 4 .</span> <span class="Constant"> . ┊screen: .</span> <span class="Constant"> . ┊ .4 . .</span> <span class="Constant"> . ┊ . . .</span> @@ -512,11 +502,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="muRecipe">recipe</span> editor-contents [ +<span class="muRecipe">recipe</span> editor-contents editor:address:editor-data<span class="muRecipe"> -&gt; </span>result:address:array:character [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> buf:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">80</span> - curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + curr:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> <span class="Comment"># skip § sentinel</span> assert curr, <span class="Constant">[editor without data is illegal; must have at least a sentinel]</span> curr<span class="Special"> &lt;- </span>next-duplex curr @@ -528,20 +518,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } curr<span class="Special"> &lt;- </span>next-duplex curr <span class="muControl">loop</span> <span class="Delimiter">}</span> - result:address:array:character<span class="Special"> &lt;- </span>buffer-to-array buf - <span class="muControl">reply</span> result + result<span class="Special"> &lt;- </span>buffer-to-array buf ] <span class="muScenario">scenario</span> editor-provides-edited-contents [ 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"> &lt;- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">2</span> type <span class="Constant">[def]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Constant">3</span>:address:array:character<span class="Special"> &lt;- </span>editor-contents <span class="Constant">2</span>:address:editor-data <span class="Constant">4</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:character ] diff --git a/html/edit/006-sandbox-edit.mu.html b/html/edit/006-sandbox-edit.mu.html index e5c2d430..a1e3bb2f 100644 --- a/html/edit/006-sandbox-edit.mu.html +++ b/html/edit/006-sandbox-edit.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } +.muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .Special { color: #ff6060; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -35,25 +35,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## editing sandboxes after they've been created</span> <span class="muScenario">scenario</span> clicking-on-a-sandbox-moves-it-to-editor [ - $close-trace <span class="Comment"># trace too long</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span> <span class="Comment"># basic recipe</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> -<span class="Constant"> add 2, 2</span> +<span class="Constant"> reply 4</span> <span class="Constant">]</span>] <span class="Comment"># run it</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> - <span class="Constant"> . add 2, 2 ┊ x.</span> + <span class="Constant"> . reply 4 ┊ x.</span> <span class="Constant"> .] ┊foo .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━.</span> @@ -64,14 +64,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">3</span>, <span class="Constant">30</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># it pops back into editor</span> screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊foo .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> - <span class="Constant"> . add 2, 2 ┊ .</span> + <span class="Constant"> . reply 4 ┊ .</span> <span class="Constant"> .] ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> @@ -82,13 +82,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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"> . ┊0foo .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> - <span class="Constant"> . add 2, 2 ┊ .</span> + <span class="Constant"> . reply 4 ┊ .</span> <span class="Constant"> .] ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> @@ -97,8 +97,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [ - <span class="Comment"># right side of screen and below sandbox editor? pop appropriate sandbox</span> - <span class="Comment"># contents back into sandbox editor provided it's empty</span> + <span class="Comment"># below sandbox editor? pop appropriate sandbox contents back into sandbox editor</span> <span class="Delimiter">{</span> sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span> click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span> @@ -111,7 +110,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins <span class="muControl">break-unless</span> below-sandbox-editor? empty-sandbox-editor?:boolean<span class="Special"> &lt;- </span>empty-editor? current-sandbox - <span class="muControl">break-unless</span> empty-sandbox-editor? <span class="Comment"># make the user hit F4 before editing a new sandbox</span> + <span class="muControl">break-unless</span> empty-sandbox-editor? <span class="Comment"># don't clobber existing contents</span> <span class="Comment"># identify the sandbox to edit and remove it from the sandbox list</span> sandbox:address:sandbox-data<span class="Special"> &lt;- </span>extract-sandbox env, click-row text:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span> @@ -124,19 +123,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> empty-editor? [ +<span class="muRecipe">recipe</span> empty-editor? editor:address:editor-data<span class="muRecipe"> -&gt; </span>result:boolean [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - head:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> - first:address:duplex-list<span class="Special"> &lt;- </span>next-duplex head - result:boolean<span class="Special"> &lt;- </span>not first - <span class="muControl">reply</span> result + <span class="Constant">load-ingredients</span> + head:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> + first:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex head + result<span class="Special"> &lt;- </span>not first ] -<span class="muRecipe">recipe</span> extract-sandbox [ +<span class="muRecipe">recipe</span> extract-sandbox env:address:programming-environment-data, click-row:number<span class="muRecipe"> -&gt; </span>result:address:sandbox-data [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span> sandbox:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span> start:number<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">starting-row-on-screen:offset</span> @@ -153,7 +150,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># snip sandbox out of its list</span> - result:address:sandbox-data<span class="Special"> &lt;- </span>copy *sandbox + result<span class="Special"> &lt;- </span>copy *sandbox *sandbox<span class="Special"> &lt;- </span>copy next-sandbox <span class="Comment"># position cursor in sandbox editor</span> sandbox-in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span> @@ -162,26 +159,24 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> sandbox-with-print-can-be-edited [ - $close-trace <span class="Comment"># trace too long</span> + 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">20/height</span> <span class="Comment"># left editor is empty</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an instruction</span> - <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen, 4]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the sandbox</span> assume-console [ press F4 ] - run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - ] + 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"> . ┊ x.</span> - <span class="Constant"> . ┊print-integer screen:address, 4 .</span> + <span class="Constant"> . ┊print-integer screen, 4 .</span> <span class="Constant"> . ┊screen: .</span> <span class="Constant"> . ┊ .4 . .</span> <span class="Constant"> . ┊ . . .</span> @@ -196,11 +191,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">3</span>, <span class="Constant">70</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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"> . ┊print-integer screen:address, 4 .</span> + <span class="Constant"> . ┊print-integer screen, 4 .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> . ┊ .</span> diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html index 5f3cdfcf..f563b266 100644 --- a/html/edit/007-sandbox-delete.mu.html +++ b/html/edit/007-sandbox-delete.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } +.muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .Special { color: #ff6060; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -35,11 +35,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## deleting sandboxes</span> <span class="muScenario">scenario</span> deleting-sandboxes [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run a few commands</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">80</span> @@ -48,9 +48,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[add 2, 2]</span> press F4 ] - run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - ] + 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> @@ -71,7 +69,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">7</span>, <span class="Constant">99</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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> @@ -89,7 +87,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">3</span>, <span class="Constant">99</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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> @@ -113,11 +111,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="Comment"># was-deleted?:boolean &lt;- delete-sandbox t:touch-event, env:address:programming-environment-data</span> -<span class="muRecipe">recipe</span> delete-sandbox [ +<span class="muRecipe">recipe</span> delete-sandbox t:touch-event, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>was-delete?:boolean [ <span class="Constant">local-scope</span> - t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> click-column:number<span class="Special"> &lt;- </span>get t, <span class="Constant">column:offset</span> current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span> right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span> diff --git a/html/edit/008-sandbox-test.mu.html b/html/edit/008-sandbox-test.mu.html index 0cdd6a08..08b62ddc 100644 --- a/html/edit/008-sandbox-test.mu.html +++ b/html/edit/008-sandbox-test.mu.html @@ -13,14 +13,14 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } +.muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .Special { color: #ff6060; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -35,25 +35,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## clicking on sandbox results to 'fix' them and turn sandboxes into tests</span> <span class="muScenario">scenario</span> sandbox-click-on-result-toggles-color-to-green [ - $close-trace <span class="Comment"># trace too long</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span> <span class="Comment"># basic recipe</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> -<span class="Constant"> add 2, 2</span> +<span class="Constant"> reply 4</span> <span class="Constant">]</span>] <span class="Comment"># run it</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> - <span class="Constant"> . add 2, 2 ┊ x.</span> + <span class="Constant"> . reply 4 ┊ x.</span> <span class="Constant"> .] ┊foo .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━.</span> @@ -64,7 +64,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">5</span>, <span class="Constant">21</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># color toggles to green</span> screen-should-contain-in-color <span class="Constant">2/green</span>, [ @@ -79,19 +79,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># cursor should remain unmoved</span> run [ - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> .␣ ┊ .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> - <span class="Constant"> . add 2, 2 ┊ x.</span> + <span class="Constant"> . reply 4 ┊ x.</span> <span class="Constant"> .] ┊foo .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] - <span class="Comment"># now change the second arg of the 'add'</span> + <span class="Comment"># now change the result</span> <span class="Comment"># then rerun</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">11</span> <span class="Comment"># cursor to end of line</span> @@ -100,7 +100,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># result turns red</span> screen-should-contain-in-color <span class="Constant">1/red</span>, [ @@ -109,7 +109,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . .</span> <span class="Constant"> . .</span> <span class="Constant"> . .</span> - <span class="Constant"> . 5 .</span> + <span class="Constant"> . 3 .</span> <span class="Constant"> . .</span> <span class="Constant"> . .</span> ] @@ -117,7 +117,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># clicks on sandbox responses save it as 'expected'</span> <span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [ - <span class="Comment"># right side of screen? check if it's inside the output of any sandbox</span> + <span class="Comment"># check if it's inside the output of any sandbox</span> <span class="Delimiter">{</span> sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span> click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span> @@ -144,10 +144,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> find-click-in-sandbox-output [ +<span class="muRecipe">recipe</span> find-click-in-sandbox-output env:address:programming-environment-data, click-row:number<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span> sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span> start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span> @@ -171,9 +170,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> sandbox ] -<span class="muRecipe">recipe</span> toggle-expected-response [ +<span class="muRecipe">recipe</span> toggle-expected-response sandbox:address:sandbox-data<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> - sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> expected-response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">expected-response:offset</span> <span class="Delimiter">{</span> <span class="Comment"># if expected-response is set, reset</span> @@ -184,7 +183,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># if not, current response is the expected response</span> response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response:offset</span> *expected-response<span class="Special"> &lt;- </span>copy response - <span class="muControl">reply</span> sandbox/same-as-ingredient:<span class="Constant">0</span> ] <span class="Comment"># when rendering a sandbox, color it in red/green if expected response exists</span> diff --git a/html/edit/009-sandbox-trace.mu.html b/html/edit/009-sandbox-trace.mu.html index b73fbee6..071f62af 100644 --- a/html/edit/009-sandbox-trace.mu.html +++ b/html/edit/009-sandbox-trace.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } +.muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .muData { color: #ffff00; } .Special { color: #ff6060; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -36,7 +36,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## clicking on the code typed into a sandbox toggles its trace</span> <span class="muScenario">scenario</span> sandbox-click-on-code-toggles-app-trace [ - $close-trace <span class="Comment"># trace too long</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span> <span class="Comment"># basic recipe</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> @@ -48,8 +48,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } assume-console [ press F4 ] - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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> @@ -59,13 +59,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] - <span class="Comment"># click on the 'foo' line in the sandbox</span> + <span class="Comment"># click on the code in the sandbox</span> assume-console [ left-click <span class="Constant">4</span>, <span class="Constant">21</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] <span class="Comment"># trace now printed and cursor shouldn't have budged</span> screen-should-contain [ @@ -93,8 +93,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-click <span class="Constant">4</span>, <span class="Constant">25</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data - print-character screen:address, <span class="Constant">9251/␣/cursor</span> + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + print-character screen:address:screen, <span class="Constant">9251/␣/cursor</span> ] <span class="Comment"># trace hidden again</span> screen-should-contain [ @@ -109,45 +109,45 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> sandbox-shows-app-trace-and-result [ - $close-trace <span class="Comment"># trace too long</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span> <span class="Comment"># basic recipe</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> stash [abc]</span> - add <span class="Constant">2</span>, <span class="Constant">2</span> + <span class="muControl">reply</span> <span class="Constant">4</span> ]] <span class="Comment"># run it</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </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"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . stash [abc] ┊ x.</span> - <span class="Constant"> . add 2, 2 ┊foo .</span> + <span class="Constant"> . reply 4 ┊foo .</span> <span class="Constant"> .] ┊4 .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] - <span class="Comment"># click on the 'foo' line in the sandbox</span> + <span class="Comment"># click on the code in the sandbox</span> assume-console [ left-click <span class="Constant">4</span>, <span class="Constant">21</span> ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] - <span class="Comment"># trace now printed</span> + <span class="Comment"># trace now printed above result</span> screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . stash [abc] ┊ x.</span> - <span class="Constant"> . add 2, 2 ┊foo .</span> + <span class="Constant"> . reply 4 ┊foo .</span> <span class="Constant"> .] ┊abc .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━.</span> @@ -161,9 +161,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">recipe!</span> update-sandbox [ +<span class="muRecipe">recipe!</span> update-sandbox sandbox:address:sandbox-data<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> - sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span> response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response:offset</span> trace:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">trace:offset</span> @@ -173,7 +173,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># clicks on sandbox code toggle its display-trace? flag</span> <span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [ - <span class="Comment"># right side of screen? check if it's inside the code of any sandbox</span> + <span class="Comment"># check if it's inside the code of any sandbox</span> <span class="Delimiter">{</span> sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span> click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span> @@ -200,12 +200,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> find-click-in-sandbox-code [ +<span class="muRecipe">recipe</span> find-click-in-sandbox-code env:address:programming-environment-data, click-row:number<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span> - sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span> + sandbox<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span> start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span> clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span> @@ -241,6 +240,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> sandbox-trace <span class="Comment"># nothing to print; move on</span> row, screen<span class="Special"> &lt;- </span>render-string, screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row <span class="Delimiter">}</span> +<span class="Constant"> &lt;render-sandbox-trace-done&gt;</span> ] </pre> </body> diff --git a/html/edit/010-warnings.mu.html b/html/edit/010-warnings.mu.html index ca9008b7..335bfb42 100644 --- a/html/edit/010-warnings.mu.html +++ b/html/edit/010-warnings.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .Special { color: #ff6060; } -.muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.muScenario { color: #00af00; } --> </style> @@ -40,10 +40,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># copy code from recipe editor, persist, load into mu, save any warnings</span> -<span class="muRecipe">recipe!</span> update-recipes [ +<span class="muRecipe">recipe!</span> update-recipes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -&gt; </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> - env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span> in:address:array:character<span class="Special"> &lt;- </span>editor-contents recipes save <span class="Constant">[recipes.mu]</span>, in @@ -54,9 +53,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> *recipe-warnings status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[errors found]</span> update-status screen, status, <span class="Constant">1/red</span> - <span class="muControl">reply</span> <span class="Constant">1/errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> + errors-found?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> <span class="Delimiter">}</span> - <span class="muControl">reply</span> <span class="Constant">0/no-errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> + errors-found?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span> ] <span class="muRecipe">before</span> <span class="Constant">&lt;render-components-end&gt;</span> [ @@ -81,9 +81,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } warnings:address:array:character ] -<span class="muRecipe">recipe!</span> update-sandbox [ +<span class="muRecipe">recipe!</span> update-sandbox sandbox:address:sandbox-data<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> - sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span> response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response:offset</span> warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">warnings:offset</span> @@ -98,30 +98,32 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">after</span> <span class="Constant">&lt;render-sandbox-results&gt;</span> [ +<span class="Comment"># make sure we render any trace</span> +<span class="muRecipe">after</span> <span class="Constant">&lt;render-sandbox-trace-done&gt;</span> [ <span class="Delimiter">{</span> sandbox-warnings:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">warnings:offset</span> <span class="muControl">break-unless</span> sandbox-warnings *response-starting-row<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># no response</span> row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-warnings, 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> ] <span class="muScenario">scenario</span> run-shows-warnings-in-get [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> get 123:number, foo:offset</span> <span class="Constant">]</span>] <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] screen-should-contain [ <span class="Constant"> . errors found run (F4) .</span> @@ -129,7 +131,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . get 123:number, foo:offset ┊ .</span> <span class="Constant"> .] ┊ .</span> - <span class="Constant"> .unknown element foo in container number ┊ .</span> + <span class="Constant"> .foo: unknown element foo in container number ┊ .</span> + <span class="Constant"> .foo: first ingredient of 'get' should be a contai↩┊ .</span> + <span class="Constant"> .ner, but got 123:number ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> ] @@ -139,25 +143,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . .</span> <span class="Constant"> . .</span> <span class="Constant"> . .</span> - <span class="Constant"> .unknown element foo in container number .</span> + <span class="Constant"> .foo: unknown element foo in container number .</span> + <span class="Constant"> .foo: first ingredient of 'get' should be a contai .</span> + <span class="Constant"> .ner, but got 123:number .</span> <span class="Constant"> . .</span> ] ] <span class="muScenario">scenario</span> run-shows-missing-type-warnings [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> x &lt;- copy 0</span> <span class="Constant">]</span>] <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] screen-should-contain [ <span class="Constant"> . errors found run (F4) .</span> @@ -165,14 +171,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . x &lt;- copy 0 ┊ .</span> <span class="Constant"> .] ┊ .</span> - <span class="Constant"> .missing type in 'x &lt;- copy 0' ┊ .</span> - <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> - <span class="Constant"> . ┊ .</span> + <span class="Constant"> .foo: missing type for x in 'x &lt;- copy 0' ┊ .</span> ] ] <span class="muScenario">scenario</span> run-shows-unbalanced-bracket-warnings [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Comment"># recipe is incomplete (unbalanced '[')</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> @@ -181,12 +185,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">]</span> string-replace <span class="Constant">1</span>:address:array:character, <span class="Constant">171/«</span>, <span class="Constant">91</span> <span class="Comment"># '['</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] screen-should-contain [ <span class="Constant"> . errors found run (F4) .</span> @@ -201,7 +205,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muScenario">scenario</span> run-shows-get-on-non-container-warnings [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> @@ -209,28 +213,29 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> get x:address:point, 1:offset</span> <span class="Constant">]</span>] <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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"> . errors found run (F4) .</span> + <span class="Constant"> . ┊foo .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> - <span class="Constant"> . x:address:point &lt;- new point:type ┊ x.</span> - <span class="Constant"> . get x:address:point, 1:offset ┊foo .</span> - <span class="Constant"> .] ┊foo: first ingredient of 'get' should be a conta↩.</span> - <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊iner, but got x:address:point .</span> - <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . x:address:point &lt;- new point:type ┊ .</span> + <span class="Constant"> . get x:address:point, 1:offset ┊ .</span> + <span class="Constant"> .] ┊ .</span> + <span class="Constant"> .foo: first ingredient of 'get' should be a contai↩┊ .</span> + <span class="Constant"> .ner, but got x:address:point ┊ .</span> + <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> run-shows-non-literal-get-argument-warnings [ - $close-trace <span class="Comment"># trace too long</span> + 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">15/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> @@ -239,12 +244,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> get *y:address:point, x:number</span> <span class="Constant">]</span>] <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] screen-should-contain [ <span class="Constant"> . errors found run (F4) .</span> @@ -256,13 +261,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> .] ┊ .</span> <span class="Constant"> .foo: expected ingredient 1 of 'get' to have type ↩┊ .</span> <span class="Constant"> .'offset'; got x:number ┊ .</span> + <span class="Constant"> .foo: second ingredient of 'get' should have type ↩┊ .</span> + <span class="Constant"> .'offset', but got x:number ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> run-shows-warnings-everytime [ - $close-trace <span class="Comment"># trace too long</span> + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> <span class="Comment"># try to run a file with an error</span> assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> @@ -270,12 +277,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> x:number &lt;- copy y:number</span> <span class="Constant">]</span>] <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] screen-should-contain [ <span class="Constant"> . errors found run (F4) .</span> @@ -283,7 +290,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . x:number &lt;- copy y:number ┊ .</span> <span class="Constant"> .] ┊ .</span> - <span class="Constant"> .use before set: y in foo ┊ .</span> + <span class="Constant"> .foo: use before set: y ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> ] @@ -292,7 +299,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] screen-should-contain [ <span class="Constant"> . errors found run (F4) .</span> @@ -300,26 +307,26 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . x:number &lt;- copy y:number ┊ .</span> <span class="Constant"> .] ┊ .</span> - <span class="Constant"> .use before set: y in foo ┊ .</span> + <span class="Constant"> .foo: use before set: y ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> run-instruction-and-print-warnings [ - $close-trace <span class="Comment"># trace too long</span> + 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="Comment"># left editor is empty</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an illegal instruction</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors</span> assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># check that screen prints error message in red</span> screen-should-contain [ @@ -329,6 +336,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . ┊ x.</span> <span class="Constant"> . ┊get 1234:number, foo:offset .</span> <span class="Constant"> . ┊unknown element foo in container number .</span> + <span class="Constant"> . ┊first ingredient of 'get' should be a container,↩.</span> + <span class="Constant"> . ┊ but got 1234:number .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] @@ -349,6 +358,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . .</span> <span class="Constant"> . .</span> <span class="Constant"> . unknown element foo in container number .</span> + <span class="Constant"> . first ingredient of 'get' should be a container, .</span> + <span class="Constant"> . but got 1234:number .</span> <span class="Constant"> . .</span> ] screen-should-contain-in-color <span class="Constant">245/grey</span>, [ @@ -358,26 +369,28 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . ┊ x.</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊ ↩.</span> + <span class="Constant"> . ┊ .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> run-instruction-and-print-warnings-only-once [ - $close-trace <span class="Comment"># trace too long</span> + 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="Comment"># left editor is empty</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an illegal instruction</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors multiple times</span> assume-console [ press F4 press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># check that screen prints error message just once</span> screen-should-contain [ @@ -387,13 +400,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . ┊ x.</span> <span class="Constant"> . ┊get 1234:number, foo:offset .</span> <span class="Constant"> . ┊unknown element foo in container number .</span> + <span class="Constant"> . ┊first ingredient of 'get' should be a container,↩.</span> + <span class="Constant"> . ┊ but got 1234:number .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> sandbox-can-handle-infinite-loop [ - $close-trace <span class="Comment"># trace too long</span> + 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">20/height</span> <span class="Comment"># left editor is empty</span> <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[recipe foo [</span> @@ -403,13 +418,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">]</span>] <span class="Comment"># right editor contains an instruction</span> <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the sandbox</span> assume-console [ press F4 ] run [ - event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data + 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> @@ -422,6 +437,55 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant"> . ┊ .</span> ] ] + +<span class="muScenario">scenario</span> sandbox-with-warnings-shows-trace [ + 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="Comment"># generate a stash and a warning</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[recipe foo [</span> +<span class="Constant">local-scope</span> +<span class="Constant">a:number &lt;- next-ingredient</span> +<span class="Constant">b:number &lt;- next-ingredient</span> +<span class="Constant">stash [dividing by]</span>, b +_, c:number<span class="Special"> &lt;- </span>divide-with-remainder a, b +<span class="muControl">reply</span> b +]] + <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo 4, 0]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Comment"># run</span> + assume-console [ + press F4 + ] + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + <span class="Comment"># screen prints error message</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> .recipe foo \\\[ ┊ .</span> + <span class="Constant"> .local-scope ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .a:number &lt;- next-ingredient ┊ x.</span> + <span class="Constant"> .b:number &lt;- next-ingredient ┊foo 4, 0 .</span> + <span class="Constant"> .stash [dividing by], b ┊foo: divide by zero in '_, c:number &lt;- divide-wi↩.</span> + <span class="Constant"> ._, c:number &lt;- divide-with-remainder a, b ┊th-remainder a, b' .</span> + ] + <span class="Comment"># click on the call in the sandbox</span> + assume-console [ + left-click <span class="Constant">4</span>, <span class="Constant">55</span> + ] + run [ + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + ] + <span class="Comment"># screen should expand trace</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> .recipe foo \\\[ ┊ .</span> + <span class="Constant"> .local-scope ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .a:number &lt;- next-ingredient ┊ x.</span> + <span class="Constant"> .b:number &lt;- next-ingredient ┊foo 4, 0 .</span> + <span class="Constant"> .stash [dividing by], b ┊dividing by 0 .</span> + <span class="Constant"> ._, c:number &lt;- divide-with-remainder a, b ┊foo: divide by zero in '_, c:number &lt;- divide-wi↩.</span> + <span class="Constant"> .reply b ┊th-remainder a, b' .</span> + ] +] </pre> </body> </html> diff --git a/html/edit/011-editor-undo.mu.html b/html/edit/011-editor-undo.mu.html index 37417b7f..b50f0063 100644 --- a/html/edit/011-editor-undo.mu.html +++ b/html/edit/011-editor-undo.mu.html @@ -13,15 +13,15 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } -.muData { color: #ffff00; } .Special { color: #ff6060; } -.muScenario { color: #00af00; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.muScenario { color: #00af00; } --> </style> @@ -100,11 +100,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> undo?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">26/ctrl-z</span> <span class="muControl">break-unless</span> undo? - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> <span class="muControl">break-unless</span> *undo op:address:operation<span class="Special"> &lt;- </span>first *undo *undo<span class="Special"> &lt;- </span>rest *undo - redo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span> + redo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span> *redo<span class="Special"> &lt;- </span>push op, *redo <span class="Constant"> &lt;handle-undo&gt;</span> <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> @@ -116,11 +116,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> redo?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">25/ctrl-y</span> <span class="muControl">break-unless</span> redo? - redo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span> + redo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span> <span class="muControl">break-unless</span> *redo op:address:operation<span class="Special"> &lt;- </span>first *redo *redo<span class="Special"> &lt;- </span>rest *redo - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> *undo<span class="Special"> &lt;- </span>push op, *undo <span class="Constant"> &lt;handle-redo&gt;</span> <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> @@ -133,18 +133,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor and type a character</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[0]</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># character should be gone</span> screen-should-contain [ @@ -158,7 +158,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -170,12 +170,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># save operation to undo</span> <span class="muRecipe">after</span> <span class="Constant">&lt;insert-character-begin&gt;</span> [ - top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - cursor-before:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor + top-before:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-before:address:duplex-list:character<span class="Special"> &lt;- </span>copy *before-cursor ] <span class="muRecipe">before</span> <span class="Constant">&lt;insert-character-end&gt;</span> [ - top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> <span class="Delimiter">{</span> <span class="Comment"># if previous operation was an insert, coalesce this operation with it</span> <span class="muControl">break-unless</span> *undo @@ -184,19 +184,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">break-unless</span> typing previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *typing, <span class="Constant">tag:offset</span> <span class="muControl">break-unless</span> previous-coalesce-tag - insert-until:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">insert-until:offset</span> + insert-until:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">insert-until:offset</span> *insert-until<span class="Special"> &lt;- </span>next-duplex *before-cursor after-row:address:number<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-row:offset</span> *after-row<span class="Special"> &lt;- </span>copy *cursor-row after-column:address:number<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-column:offset</span> *after-column<span class="Special"> &lt;- </span>copy *cursor-column - after-top:address:number<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-top-of-screen:offset</span> + after-top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-top-of-screen:offset</span> *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="muControl">break</span> <span class="Constant">+done-adding-insert-operation:label</span> <span class="Delimiter">}</span> <span class="Comment"># if not, create a new operation</span> - insert-from:address:duplex-list<span class="Special"> &lt;- </span>next-duplex cursor-before - insert-to:address:duplex-list<span class="Special"> &lt;- </span>next-duplex insert-from + insert-from:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex cursor-before + insert-to:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex insert-from op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span> *op<span class="Special"> &lt;- </span>merge <span class="Constant">0/insert-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, insert-from, insert-to, <span class="Constant">1/coalesce</span> editor<span class="Special"> &lt;- </span>add-operation editor, op @@ -207,14 +207,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">after</span> <span class="Constant">&lt;insert-enter-begin&gt;</span> [ cursor-row-before:number<span class="Special"> &lt;- </span>copy *cursor-row cursor-column-before:number<span class="Special"> &lt;- </span>copy *cursor-column - top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - cursor-before:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor + top-before:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-before:address:duplex-list:character<span class="Special"> &lt;- </span>copy *before-cursor ] <span class="muRecipe">before</span> <span class="Constant">&lt;insert-enter-end&gt;</span> [ - top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-after:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Comment"># never coalesce</span> - insert-from:address:duplex-list<span class="Special"> &lt;- </span>next-duplex cursor-before - insert-to:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + insert-from:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex cursor-before + insert-to:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span> *op<span class="Special"> &lt;- </span>merge <span class="Constant">0/insert-operation</span>, cursor-row-before, cursor-column-before, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, insert-from, insert-to, <span class="Constant">0/never-coalesce</span> editor<span class="Special"> &lt;- </span>add-operation editor, op @@ -224,10 +224,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># redo stack, because it's now obsolete.</span> <span class="Comment"># Beware: since we're counting cursor moves as operations, this means just</span> <span class="Comment"># moving the cursor can lose work on the undo stack.</span> -<span class="muRecipe">recipe</span> add-operation [ +<span class="muRecipe">recipe</span> add-operation editor:address:editor-data, op:address:operation<span class="muRecipe"> -&gt; </span>editor:address:editor-data [ <span class="Constant">local-scope</span> - editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> - op:address:operation<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> + <span class="Constant">load-ingredients</span> undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> *undo<span class="Special"> &lt;- </span>push op *undo redo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span> @@ -239,14 +238,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> typing:address:insert-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">typing:variant</span> <span class="muControl">break-unless</span> typing - start:address:duplex-list<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-from:offset</span> - end:address:duplex-list<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-until:offset</span> + start:address:duplex-list:character<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-from:offset</span> + end:address:duplex-list:character<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-until:offset</span> <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span> *before-cursor<span class="Special"> &lt;- </span>prev-duplex start remove-duplex-between *before-cursor, end *cursor-row<span class="Special"> &lt;- </span>get *typing, <span class="Constant">before-row:offset</span> *cursor-column<span class="Special"> &lt;- </span>get *typing, <span class="Constant">before-column:offset</span> - top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *top<span class="Special"> &lt;- </span>get *typing, <span class="Constant">before-top-of-screen:offset</span> <span class="Delimiter">}</span> ] @@ -255,18 +254,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor and type multiple characters</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[012]</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># all characters must be gone</span> screen-should-contain [ @@ -281,13 +280,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor with some text</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"> &lt;- </span>new <span class="Constant">[a]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># type some characters</span> assume-console [ type <span class="Constant">[012]</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .012a .</span> @@ -299,7 +298,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># back to original text</span> screen-should-contain [ @@ -313,7 +312,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[3]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -327,14 +326,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor with some text</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"> &lt;- </span>new <span class="Constant">[ abc]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># new line</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">8</span> press enter ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . abc .</span> @@ -354,7 +353,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> @@ -374,7 +373,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -390,13 +389,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor, type something, undo</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"> &lt;- </span>new <span class="Constant">[a]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[012]</span> press ctrl-z ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -408,7 +407,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># all characters must be back</span> screen-should-contain [ @@ -422,7 +421,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[3]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -436,13 +435,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> typing:address:insert-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">typing:variant</span> <span class="muControl">break-unless</span> typing - insert-from:address:duplex-list<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-from:offset</span> <span class="Comment"># ignore insert-to because it's already been spliced away</span> + insert-from:address:duplex-list:character<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-from:offset</span> <span class="Comment"># ignore insert-to because it's already been spliced away</span> <span class="Comment"># assert insert-to matches next-duplex(*before-cursor)</span> insert-duplex-range *before-cursor, insert-from <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span> *cursor-row<span class="Special"> &lt;- </span>get *typing, <span class="Constant">after-row:offset</span> *cursor-column<span class="Special"> &lt;- </span>get *typing, <span class="Constant">after-column:offset</span> - top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *top<span class="Special"> &lt;- </span>get *typing, <span class="Constant">after-top-of-screen:offset</span> <span class="Delimiter">}</span> ] @@ -451,13 +450,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor, type something, undo</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[012]</span> press ctrl-z ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . .</span> @@ -469,7 +468,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># all characters must be back</span> screen-should-contain [ @@ -483,7 +482,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[3]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -499,18 +498,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[1]</span> press ctrl-z ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># do some more work</span> assume-console [ type <span class="Constant">[0]</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .0abc .</span> @@ -523,7 +522,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># nothing should happen</span> screen-should-contain [ @@ -539,7 +538,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># insert some text and tabs, hit enter, some more text and tabs</span> assume-console [ @@ -551,7 +550,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press tab type <span class="Constant">[efg]</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ab cd .</span> @@ -570,7 +569,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># typing in second line deleted, but not indent</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -591,7 +590,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># indent and newline deleted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -611,7 +610,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># empty screen</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -631,7 +630,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># first line inserted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -651,7 +650,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># newline and indent inserted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -672,7 +671,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># indent and newline deleted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -698,19 +697,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">1</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -724,7 +723,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -738,17 +737,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">after</span> <span class="Constant">&lt;move-cursor-begin&gt;</span> [ before-cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span> before-cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span> - before-top-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + before-top-of-screen:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant">&lt;move-cursor-end&gt;</span> [ after-cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span> after-cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span> - after-top-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + after-top-of-screen:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> undo-coalesce-tag <span class="Comment"># if previous operation was also a move, and also had the same coalesce</span> <span class="Comment"># tag, coalesce with it</span> - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> <span class="muControl">break-unless</span> *undo op:address:operation<span class="Special"> &lt;- </span>first *undo move:address:move-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">move:variant</span> @@ -760,7 +759,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *after-row<span class="Special"> &lt;- </span>copy after-cursor-row after-column:address:number<span class="Special"> &lt;- </span>get-address *move, <span class="Constant">after-column:offset</span> *after-column<span class="Special"> &lt;- </span>copy after-cursor-column - after-top:address:number<span class="Special"> &lt;- </span>get-address *move, <span class="Constant">after-top-of-screen:offset</span> + after-top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *move, <span class="Constant">after-top-of-screen:offset</span> *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="muControl">break</span> <span class="Constant">+done-adding-move-operation:label</span> <span class="Delimiter">}</span> @@ -775,7 +774,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } move:address:move-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">move:variant</span> <span class="muControl">break-unless</span> move <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span> - top:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *cursor-row<span class="Special"> &lt;- </span>get *move, <span class="Constant">before-row:offset</span> *cursor-column<span class="Special"> &lt;- </span>get *move, <span class="Constant">before-column:offset</span> *top<span class="Special"> &lt;- </span>get *move, <span class="Constant">before-top-of-screen:offset</span> @@ -789,13 +788,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdefgh]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </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"># position cursor at end of screen and try to move right</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">3</span> press right-arrow ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> <span class="Comment"># screen scrolls</span> @@ -814,7 +813,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -835,7 +834,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -851,20 +850,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">1</span> press left-arrow ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -878,7 +877,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -895,14 +894,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">1</span> press up-arrow ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ @@ -914,7 +913,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -928,7 +927,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -945,20 +944,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">1</span> press down-arrow ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -972,7 +971,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -992,19 +991,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># scroll the page</span> assume-console [ press ctrl-f ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1027,19 +1026,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># scroll the page</span> assume-console [ press page-down ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1062,20 +1061,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># scroll the page down and up</span> assume-console [ press page-down press ctrl-b ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1098,20 +1097,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># scroll the page down and up</span> assume-console [ press page-down press page-up ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1131,20 +1130,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor, then to start of line</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">1</span> press ctrl-a ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1158,7 +1157,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1175,20 +1174,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor, then to start of line</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">1</span> press home ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1202,7 +1201,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1219,20 +1218,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor, then to start of line</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">1</span> press ctrl-e ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1246,7 +1245,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1263,20 +1262,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor, then to start of line</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">1</span> press end ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># undo</span> assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1290,7 +1289,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1305,14 +1304,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor, type some text, move the cursor, type some more text</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ type <span class="Constant">[abc]</span> left-click <span class="Constant">1</span>, <span class="Constant">1</span> type <span class="Constant">[d]</span> ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> screen-should-contain [ @@ -1330,7 +1329,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1350,7 +1349,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1370,7 +1369,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1390,7 +1389,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1410,7 +1409,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1430,7 +1429,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1453,7 +1452,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># move the cursor</span> assume-console [ @@ -1462,7 +1461,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press right-arrow press up-arrow ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ @@ -1474,7 +1473,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1488,7 +1487,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1507,19 +1506,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">1</span> press ctrl-z ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data <span class="Comment"># redo</span> assume-console [ press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] @@ -1533,7 +1532,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1551,7 +1550,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span> *cursor-row<span class="Special"> &lt;- </span>get *move, <span class="Constant">after-row:offset</span> *cursor-column<span class="Special"> &lt;- </span>get *move, <span class="Constant">after-column:offset</span> - top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *top<span class="Special"> &lt;- </span>get *move, <span class="Constant">after-top-of-screen:offset</span> <span class="Delimiter">}</span> ] @@ -1562,7 +1561,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># insert some text and hit backspace</span> assume-console [ @@ -1570,7 +1569,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press backspace press backspace ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -1588,7 +1587,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> @@ -1607,7 +1606,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> @@ -1625,13 +1624,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># save operation to undo</span> <span class="muRecipe">after</span> <span class="Constant">&lt;backspace-character-begin&gt;</span> [ - top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant">&lt;backspace-character-end&gt;</span> [ <span class="Delimiter">{</span> <span class="muControl">break-unless</span> backspaced-cell <span class="Comment"># backspace failed; don't add an undo operation</span> - top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> <span class="Delimiter">{</span> <span class="Comment"># if previous operation was an insert, coalesce this operation with it</span> <span class="muControl">break-unless</span> *undo @@ -1641,22 +1640,22 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">tag:offset</span> coalesce?:boolean<span class="Special"> &lt;- </span>equal previous-coalesce-tag, <span class="Constant">1/coalesce-backspace</span> <span class="muControl">break-unless</span> coalesce? - delete-from:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">delete-from:offset</span> + delete-from:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">delete-from:offset</span> *delete-from<span class="Special"> &lt;- </span>copy *before-cursor - backspaced-so-far:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span> + backspaced-so-far:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span> insert-duplex-range backspaced-cell, *backspaced-so-far *backspaced-so-far<span class="Special"> &lt;- </span>copy backspaced-cell after-row:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-row:offset</span> *after-row<span class="Special"> &lt;- </span>copy *cursor-row after-column:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-column:offset</span> *after-column<span class="Special"> &lt;- </span>copy *cursor-column - after-top:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span> + after-top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span> *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="muControl">break</span> <span class="Constant">+done-adding-backspace-operation:label</span> <span class="Delimiter">}</span> <span class="Comment"># if not, create a new operation</span> op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span> - deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + deleted-until:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, backspaced-cell/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">1/coalesce-backspace</span> editor<span class="Special"> &lt;- </span>add-operation editor, op <span class="Constant"> +done-adding-backspace-operation</span> @@ -1667,17 +1666,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> deletion:address:delete-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">delete:variant</span> <span class="muControl">break-unless</span> deletion - start2:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">data:offset</span> - anchor:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-from:offset</span> + start2:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">data:offset</span> + anchor:address:duplex-list:character<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-from:offset</span> <span class="muControl">break-unless</span> anchor - deleted:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">deleted-text:offset</span> - old-cursor:address:duplex-list<span class="Special"> &lt;- </span>last-duplex deleted + deleted:address:duplex-list:character<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">deleted-text:offset</span> + old-cursor:address:duplex-list:character<span class="Special"> &lt;- </span>last-duplex deleted insert-duplex-range anchor, deleted <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span> *before-cursor<span class="Special"> &lt;- </span>copy old-cursor *cursor-row<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">before-row:offset</span> *cursor-column<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">before-column:offset</span> - top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *top<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">before-top-of-screen:offset</span> <span class="Delimiter">}</span> ] @@ -1686,13 +1685,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> deletion:address:delete-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">delete:variant</span> <span class="muControl">break-unless</span> deletion - start:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-from:offset</span> - end:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-until:offset</span> + start:address:duplex-list:character<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-from:offset</span> + end:address:duplex-list:character<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-until:offset</span> remove-duplex-between start, end <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span> *cursor-row<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">after-row:offset</span> *cursor-column<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">after-column:offset</span> - top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> *top<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">after-top-of-screen:offset</span> <span class="Delimiter">}</span> ] @@ -1703,7 +1702,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># create an editor</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"> &lt;- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># insert some text and hit delete and backspace a few times</span> assume-console [ @@ -1714,7 +1713,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press delete press delete ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .af .</span> @@ -1732,7 +1731,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> @@ -1751,7 +1750,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> @@ -1770,7 +1769,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + 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"> &lt;- </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"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> @@ -1789,7 +1788,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># first line inserted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -1809,7 +1808,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># first line inserted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -1829,7 +1828,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># first line inserted</span> <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> @@ -1847,13 +1846,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muRecipe">after</span> <span class="Constant">&lt;delete-character-begin&gt;</span> [ - top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant">&lt;delete-character-end&gt;</span> [ <span class="Delimiter">{</span> <span class="muControl">break-unless</span> deleted-cell <span class="Comment"># delete failed; don't add an undo operation</span> - top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> <span class="Delimiter">{</span> <span class="Comment"># if previous operation was an insert, coalesce this operation with it</span> <span class="muControl">break-unless</span> *undo @@ -1863,21 +1862,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">tag:offset</span> coalesce?:boolean<span class="Special"> &lt;- </span>equal previous-coalesce-tag, <span class="Constant">2/coalesce-delete</span> <span class="muControl">break-unless</span> coalesce? - delete-until:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">delete-until:offset</span> + delete-until:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">delete-until:offset</span> *delete-until<span class="Special"> &lt;- </span>next-duplex *before-cursor - deleted-so-far:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span> + deleted-so-far:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span> *deleted-so-far<span class="Special"> &lt;- </span>append-duplex *deleted-so-far, deleted-cell after-row:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-row:offset</span> *after-row<span class="Special"> &lt;- </span>copy *cursor-row after-column:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-column:offset</span> *after-column<span class="Special"> &lt;- </span>copy *cursor-column - after-top:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span> + after-top:address:address:duplex-list:character<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span> *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="muControl">break</span> <span class="Constant">+done-adding-delete-operation:label</span> <span class="Delimiter">}</span> <span class="Comment"># if not, create a new operation</span> op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span> - deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + deleted-until:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, deleted-cell/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">2/coalesce-delete</span> editor<span class="Special"> &lt;- </span>add-operation editor, op <span class="Constant"> +done-adding-delete-operation</span> @@ -1891,14 +1890,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># insert some text and hit delete and backspace a few times</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> press ctrl-k ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -1917,7 +1916,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1937,7 +1936,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># first line inserted</span> screen-should-contain [ @@ -1958,7 +1957,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -1970,15 +1969,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muRecipe">after</span> <span class="Constant">&lt;delete-to-end-of-line-begin&gt;</span> [ - top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant">&lt;delete-to-end-of-line-end&gt;</span> [ <span class="Delimiter">{</span> <span class="muControl">break-unless</span> deleted-cells <span class="Comment"># delete failed; don't add an undo operation</span> - top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span> - deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + deleted-until:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, deleted-cells/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">0/never-coalesce</span> editor<span class="Special"> &lt;- </span>add-operation editor, op <span class="Constant"> +done-adding-delete-operation</span> @@ -1992,14 +1991,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } 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"> &lt;- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># insert some text and hit delete and backspace a few times</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">2</span> press ctrl-u ] - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .c .</span> @@ -2018,7 +2017,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-z ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2038,7 +2037,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } press ctrl-y ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] <span class="Comment"># first line inserted</span> screen-should-contain [ @@ -2059,7 +2058,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data ] screen-should-contain [ <span class="Constant"> . .</span> @@ -2071,21 +2070,42 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muRecipe">after</span> <span class="Constant">&lt;delete-to-start-of-line-begin&gt;</span> [ - top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant">&lt;delete-to-start-of-line-end&gt;</span> [ <span class="Delimiter">{</span> <span class="muControl">break-unless</span> deleted-cells <span class="Comment"># delete failed; don't add an undo operation</span> - top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span> op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span> - deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor + deleted-until:address:duplex-list:character<span class="Special"> &lt;- </span>next-duplex *before-cursor *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, deleted-cells/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">0/never-coalesce</span> editor<span class="Special"> &lt;- </span>add-operation editor, op <span class="Constant"> +done-adding-delete-operation</span> <span class="Delimiter">}</span> ] +<span class="muScenario">scenario</span> editor-can-undo-and-redo-ctrl-u-2 [ + <span class="Comment"># create an editor</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"> &lt;- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data + <span class="Comment"># insert some text and hit delete and backspace a few times</span> + assume-console [ + type <span class="Constant">[abc]</span> + press ctrl-u + press ctrl-z + ] + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] +] + <span class="Comment"># todo:</span> <span class="Comment"># operations for recipe side and each sandbox-data</span> <span class="Comment"># undo delete sandbox as a separate primitive on the status bar</span> diff --git a/html/factorial.mu.html b/html/factorial.mu.html index d3837c22..31ac9c26 100644 --- a/html/factorial.mu.html +++ b/html/factorial.mu.html @@ -13,13 +13,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> diff --git a/html/fork.mu.html b/html/fork.mu.html index 09d02860..69dc4e30 100644 --- a/html/fork.mu.html +++ b/html/fork.mu.html @@ -13,11 +13,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> diff --git a/html/static_dispatch.mu.html b/html/static_dispatch.mu.html new file mode 100644 index 00000000..c3ed60ef --- /dev/null +++ b/html/static_dispatch.mu.html @@ -0,0 +1,55 @@ +<!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 - static_dispatch.mu</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<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-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.muRecipe { color: #ff8700; } +.Comment { color: #9090ff; } +.Constant { color: #00a0a0; } +.Special { color: #ff6060; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="muRecipe">recipe</span> test a:number<span class="muRecipe"> -&gt; </span>b:number [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + b<span class="Special"> &lt;- </span>add a, <span class="Constant">1</span> +] + +<span class="muRecipe">recipe</span> test a:number, b:number<span class="muRecipe"> -&gt; </span>c:number [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + c<span class="Special"> &lt;- </span>add a, b +] + +<span class="muRecipe">recipe</span> main [ + <span class="Constant">local-scope</span> + a:number<span class="Special"> &lt;- </span>test <span class="Constant">3</span> <span class="Comment"># selects single-ingredient version</span> + $print a, <span class="Constant">10/newline</span> + b:number<span class="Special"> &lt;- </span>test <span class="Constant">3</span>, <span class="Constant">4</span> <span class="Comment"># selects double-ingredient version</span> + $print b, <span class="Constant">10/newline</span> + c:number<span class="Special"> &lt;- </span>test <span class="Constant">3</span>, <span class="Constant">4</span>, <span class="Constant">5</span> <span class="Comment"># prefers double- to single-ingredient version</span> + $print c, <span class="Constant">10/newline</span> +] +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/tangle.mu.html b/html/tangle.mu.html index e3dba023..118b2386 100644 --- a/html/tangle.mu.html +++ b/html/tangle.mu.html @@ -13,12 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } +.muControl { color: #c0a020; } .muRecipe { color: #ff8700; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #ff6060; } .Delimiter { color: #a04060; } -.muControl { color: #c0a020; } --> </style> @@ -42,19 +42,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">local-scope</span> n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> -<span class="Constant"> +base-case</span> +<span class="Constant"> &lt;base-case&gt;</span> <span class="Delimiter">}</span> -<span class="Constant"> +recursive-case</span> +<span class="Constant"> &lt;recursive-case&gt;</span> ] -<span class="muRecipe">after</span> +base-case [ +<span class="muRecipe">after</span> <span class="Constant">&lt;base-case&gt;</span> [ <span class="Comment"># if n=0 return 1</span> zero?:boolean<span class="Special"> &lt;- </span>equal n, <span class="Constant">0</span> <span class="muControl">break-unless</span> zero? <span class="muControl">reply</span> <span class="Constant">1</span> ] -<span class="muRecipe">after</span> +recursive-case [ +<span class="muRecipe">after</span> <span class="Constant">&lt;recursive-case&gt;</span> [ <span class="Comment"># return n * factorial(n - 1)</span> x:number<span class="Special"> &lt;- </span>subtract n, <span class="Constant">1</span> subresult:number<span class="Special"> &lt;- </span>factorial x