diff options
64 files changed, 4952 insertions, 4971 deletions
diff --git a/html/010vm.cc.html b/html/010vm.cc.html index 5cf2cb71..56370c5d 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -158,8 +158,8 @@ type_ordinal Next_type_ordinal = <span class="Constant">1</span><span class="Del Next_type_ordinal = <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// Mu Types Initialization</span> type_ordinal number = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> - put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">));</span> <span class="Comment">// wildcard type: either a pointer or a scalar</span> get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> number<span class="Delimiter">).</span>name = <span class="Constant">"number"</span><span class="Delimiter">;</span> + put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">,</span> number<span class="Delimiter">);</span> <span class="Comment">// synonym of number to indicate we only care about its size</span> type_ordinal address = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> address<span class="Delimiter">).</span>name = <span class="Constant">"address"</span><span class="Delimiter">;</span> type_ordinal boolean = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"boolean"</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> @@ -203,10 +203,9 @@ atexit<span class="Delimiter">(</span>teardown_types<span class="Delimiter">);</ <span class="Normal">struct</span> type_info <span class="Delimiter">{</span> string name<span class="Delimiter">;</span> kind_of_type kind<span class="Delimiter">;</span> - <span class="Normal">int</span> size<span class="Delimiter">;</span> <span class="Comment">// only if type is not primitive; primitives and addresses have size 1 (except arrays are dynamic)</span> vector<reagent> elements<span class="Delimiter">;</span> <span class="Comment">// End type_info Fields</span> - type_info<span class="Delimiter">()</span> :kind<span class="Delimiter">(</span>PRIMITIVE<span class="Delimiter">),</span> size<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + type_info<span class="Delimiter">()</span> :kind<span class="Delimiter">(</span>PRIMITIVE<span class="Delimiter">)</span> <span class="Delimiter">{}</span> <span class="Delimiter">};</span> <span class="Normal">enum</span> primitive_recipes <span class="Delimiter">{</span> @@ -237,7 +236,7 @@ assert<span class="Delimiter">(</span>MAX_PRIMITIVE_RECIPES < <span class="Co Next_recipe_ordinal = <span class="Constant">200</span><span class="Delimiter">;</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"main"</span><span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> <span class="Comment">// End Load Recipes</span> -<span class="Delimiter">:(before "End Test Run Initialization")</span> +<span class="Delimiter">:(before "End Commandline Parsing")</span> assert<span class="Delimiter">(</span>Next_recipe_ordinal < <span class="Constant">1000</span><span class="Delimiter">);</span> <span class="Comment">// recipes being tested didn't overflow into test space</span> <span class="Delimiter">:(before "End Setup")</span> Next_recipe_ordinal = <span class="Constant">1000</span><span class="Delimiter">;</span> <span class="Comment">// consistent new numbers for each test</span> diff --git a/html/012transform.cc.html b/html/012transform.cc.html index 7d46535e..3d6c6974 100644 --- a/html/012transform.cc.html +++ b/html/012transform.cc.html @@ -85,7 +85,7 @@ vector<transform_fn> Transform<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="CommentedCode">//? cerr << "wrapping up transform\n";</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 All</span> + <span class="Comment">// End transform_all</span> <span class="Delimiter">}</span> <span class="Normal">void</span> parse_int_reagents<span class="Delimiter">()</span> <span class="Delimiter">{</span> diff --git a/html/020run.cc.html b/html/020run.cc.html index a31b6dcd..9e3ad44c 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -72,7 +72,7 @@ def main [ <span class="Delimiter">:(before "End Types")</span> <span class="Comment">// Book-keeping while running a recipe.</span> -<span class="Comment">//: Later layers will change this.</span> +<span class="Comment">//: Later layers will replace this to support running multiple routines at once.</span> <span class="Normal">struct</span> routine <span class="Delimiter">{</span> recipe_ordinal running_recipe<span class="Delimiter">;</span> <span class="Normal">int</span> running_step_index<span class="Delimiter">;</span> @@ -133,6 +133,7 @@ map<string<span class="Delimiter">,</span> <span class="Normal">int</span>> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// End of Instruction</span> + <span class="Normal">finish_instruction</span>:<span class="Delimiter">;</span> ++current_step_index<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">stop_running_current_routine</span>:<span class="Delimiter">;</span> @@ -194,7 +195,6 @@ load_file_or_directory<span class="Delimiter">(</span><span class="Constant">&qu argc--<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"main"</span><span class="Delimiter">));</span> - <span class="Comment">// End Loading .mu Files</span> <span class="Delimiter">}</span> transform_all<span class="Delimiter">();</span> save_snapshots<span class="Delimiter">();</span> diff --git a/html/021check_instruction.cc.html b/html/021check_instruction.cc.html index 580a32f6..7771ea55 100644 --- a/html/021check_instruction.cc.html +++ b/html/021check_instruction.cc.html @@ -191,10 +191,23 @@ $error: <span class="Constant">0</span> <span class="Normal">bool</span> types_strictly_match<span class="Delimiter">(</span>type_tree* to<span class="Delimiter">,</span> type_tree* from<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!to<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!from<span class="Delimiter">)</span> <span class="Identifier">return</span> to<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>from<span class="Delimiter">-></span>value == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">return</span> from<span class="Delimiter">-></span>name == to<span class="Delimiter">-></span>name<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>to<span class="Delimiter">-></span>value != from<span class="Delimiter">-></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_strictly_match<span class="Delimiter">(</span>to<span class="Delimiter">-></span>left<span class="Delimiter">,</span> from<span class="Delimiter">-></span>left<span class="Delimiter">)</span> && types_strictly_match<span class="Delimiter">(</span>to<span class="Delimiter">-></span>right<span class="Delimiter">,</span> from<span class="Delimiter">-></span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Normal">void</span> test_unknown_type_does_not_match_unknown_type<span class="Delimiter">()</span> <span class="Delimiter">{</span> + reagent a<span class="Delimiter">(</span><span class="Constant">"a:foo"</span><span class="Delimiter">);</span> + reagent b<span class="Delimiter">(</span><span class="Constant">"b:bar"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!types_strictly_match<span class="Delimiter">(</span>a<span class="Delimiter">,</span> b<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> test_unknown_type_matches_itself<span class="Delimiter">()</span> <span class="Delimiter">{</span> + reagent a<span class="Delimiter">(</span><span class="Constant">"a:foo"</span><span class="Delimiter">);</span> + reagent b<span class="Delimiter">(</span><span class="Constant">"b:foo"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>types_strictly_match<span class="Delimiter">(</span>a<span class="Delimiter">,</span> b<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + <span class="Normal">bool</span> is_unsafe<span class="Delimiter">(</span><span class="Normal">const</span> reagent& 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">"unsafe"</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> diff --git a/html/034call.cc.html b/html/026call.cc.html index 17a302a6..229f0fc8 100644 --- a/html/034call.cc.html +++ b/html/026call.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 034call.cc</title> +<title>Mu - 026call.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> diff --git a/html/035call_ingredient.cc.html b/html/027call_ingredient.cc.html index d9f7cee3..38bc3c1d 100644 --- a/html/035call_ingredient.cc.html +++ b/html/027call_ingredient.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 035call_ingredient.cc</title> +<title>Mu - 027call_ingredient.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -65,7 +65,7 @@ next_ingredient_to_process = <span class="Constant">0</span><span class="Delimit <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> 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> + <span class="Comment">// End Compute Call Ingredient</span> current_call<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -86,7 +86,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> <span class="Normal">if</span> <span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>next_ingredient_to_process < 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> + <span class="Comment">// End Preprocess NEXT_INGREDIENT product</span> <span class="Normal">if</span> <span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">()</span> == <span class="Constant">"main"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// no ingredient types since the call might be implicit; assume ingredients are always strings</span> <span class="Comment">// todo: how to test this?</span> @@ -203,6 +203,18 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + +<span class="Comment">//: a particularly common array type is the string, or address:array:character</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> is_mu_string<span class="Delimiter">(</span><span class="Normal">const</span> reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>type + && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> + && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right + && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> + && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right + && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">)</span> + && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right == <span class="Constant">NULL</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/036call_reply.cc.html b/html/028call_reply.cc.html index 4302e313..39ecff7c 100644 --- a/html/036call_reply.cc.html +++ b/html/028call_reply.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 036call_reply.cc</title> +<title>Mu - 028call_reply.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -79,20 +79,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<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="Comment">//: Products can include containers and exclusive containers, addresses and arrays.</span> -<span class="Delimiter">:(scenario reply_container)</span> -def main [ - <span class="Constant">3</span>:point<span class="Special"> <- </span>f <span class="Constant">2</span> -] -def f [ - <span class="Constant">12</span>:number<span class="Special"> <- </span>next-ingredient - <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Identifier">return</span> <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="Comment">//: Types in reply instructions are checked ahead of time.</span> <span class="Delimiter">:(before "End Checks")</span> @@ -117,9 +103,8 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Delimiter">}</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <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> + <span class="Comment">// End Check REPLY Copy(lhs, rhs)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>rhs<span class="Delimiter">,</span> lhs<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << reply_inst<span class="Delimiter">.</span>name << <span class="Constant">" ingredient "</span> << lhs<span class="Delimiter">.</span>original_string << <span class="Constant">" can't be saved in "</span> << rhs<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> raise << to_string<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" vs "</span> << to_string<span class="Delimiter">(</span>rhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> diff --git a/html/029tools.cc.html b/html/029tools.cc.html index fa165415..82884f6b 100644 --- a/html/029tools.cc.html +++ b/html/029tools.cc.html @@ -361,6 +361,24 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span LOG << out<span class="Delimiter">.</span>str<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + +<span class="Comment">//: set a variable from within mu code</span> +<span class="Comment">//: useful for selectively tracing or printing after some point</span> +<span class="Delimiter">:(before "End Globals")</span> +<span class="Normal">bool</span> Foo = <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_FOO<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$foo"</span><span class="Delimiter">,</span> _FOO<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> _FOO: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> _FOO: <span class="Delimiter">{</span> + Foo = <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/030container.cc.html b/html/030container.cc.html index 1ab7d9ed..311631ea 100644 --- a/html/030container.cc.html +++ b/html/030container.cc.html @@ -14,6 +14,7 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 12pt; font-size: 1em; } .Constant { color: #00a0a0; } +.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .traceContains { color: #008000; } .SalientComment { color: #00ffff; } @@ -39,7 +40,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">:(before "End Mu Types Initialization")</span> <span class="Comment">//: We'll use this container as a running example, with two number elements.</span> type_ordinal point = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"point"</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_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">);</span> <span class="Comment">// initialize</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">"point"</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>reagent<span class="Delimiter">(</span><span class="Constant">"x:number"</span><span class="Delimiter">));</span> @@ -72,7 +73,7 @@ def main [ <span class="Comment">// A more complex container, containing another container as one of its</span> <span class="Comment">// elements.</span> type_ordinal point_number = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"point-number"</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_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">);</span> <span class="Comment">// initialize</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">"point-number"</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>reagent<span class="Delimiter">(</span><span class="Constant">"xy:point"</span><span class="Delimiter">));</span> @@ -87,6 +88,20 @@ def main [ ] <span class="traceContains">+mem: storing 36 in location 17</span> +<span class="Comment">//: products of recipes can include containers</span> +<span class="Delimiter">:(scenario reply_container)</span> +def main [ + <span class="Constant">3</span>:point<span class="Special"> <- </span>f <span class="Constant">2</span> +] +def f [ + <span class="Constant">12</span>:number<span class="Special"> <- </span>next-ingredient + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Identifier">return</span> <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="Comment">//: Containers can be checked for equality with a single instruction just like</span> <span class="Comment">//: numbers, no matter how large they are.</span> @@ -216,24 +231,23 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">int</span> 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> <span class="Normal">if</span> <span class="Delimiter">(</span>offset < <span class="Constant">0</span> || offset >= 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> <span class="Normal">int</span> src = base_address<span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// End GET field Cases</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> src += size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> i<span class="Delimiter">));</span> - <span class="Delimiter">}</span> trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src << 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> - trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"its type is "</span> << names_to_string<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << 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> + reagent element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> offset<span class="Delimiter">);</span> + element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"its type is "</span> << names_to_string<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + <span class="Comment">// Read element</span> + products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>element<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -<span class="Normal">const</span> reagent element_type<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_base<span class="Delimiter">,</span> <span class="Normal">int</span> offset_value<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">const</span> reagent element_type<span class="Delimiter">(</span><span class="Normal">const</span> reagent& base<span class="Delimiter">,</span> <span class="Normal">int</span> offset_value<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>offset_value >= <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">-></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">-></span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">);</span> reagent element = info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset_value<span class="Delimiter">);</span> <span class="Comment">// End element_type Special-cases</span> @@ -289,36 +303,39 @@ def main [ ] <span class="Comment"># just don't die</span> -<span class="SalientComment">//:: To write to elements of containers, you need their address.</span> +<span class="SalientComment">//:: To write to elements of containers, use 'put'.</span> -<span class="Delimiter">:(scenario get_address)</span> +<span class="Delimiter">:(scenario put)</span> def main [ <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">15</span>:address:number<span class="Special"> <- </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> + $clear-trace + <span class="Constant">12</span>:point<span class="Special"> <- </span>put <span class="Constant">12</span>:point<span class="Delimiter">,</span> <span class="Constant">1</span>:offset<span class="Delimiter">,</span> <span class="Constant">36</span> ] -<span class="traceContains">+mem: storing 13 in location 15</span> +<span class="traceContains">+mem: storing 36 in location 13</span> +<span class="traceAbsent">-mem: storing 34 in location 12</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -GET_ADDRESS<span class="Delimiter">,</span> +PUT<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"get-address"</span><span class="Delimiter">,</span> GET_ADDRESS<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"put"</span><span class="Delimiter">,</span> PUT<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> GET_ADDRESS: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'get-address' expects exactly 2 ingredients in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> +<span class="Normal">case</span> PUT: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">3</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'put' expects exactly 3 ingredients in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> 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> + <span class="Comment">// Update PUT base in Check</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'get-address' should be a container, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'put' should be a container, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << 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">-></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> + <span class="Comment">// Update PUT offset in Check</span> <span class="Normal">if</span> <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 << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'get' should have type 'offset', but got "</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>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'put' should have type 'offset', but got "</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>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">int</span> offset_value = <span class="Constant">0</span><span class="Delimiter">;</span> @@ -332,22 +349,18 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">else</span> <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& value = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</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 = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"address"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">),</span> element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'get-address "</span> << base<span class="Delimiter">.</span>original_string << <span class="Constant">", "</span> << offset<span class="Delimiter">.</span>original_string << <span class="Constant">"' should write to "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" but "</span> << product<span class="Delimiter">.</span>name << <span class="Constant">" has type "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>product<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'put "</span> << base<span class="Delimiter">.</span>original_string << <span class="Constant">", "</span> << offset<span class="Delimiter">.</span>original_string << <span class="Constant">"' should store "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" but "</span> << value<span class="Delimiter">.</span>name << <span class="Constant">" has type "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>value<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> GET_ADDRESS: <span class="Delimiter">{</span> +<span class="Normal">case</span> PUT: <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> + <span class="Comment">// Update PUT base in Run</span> <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to access location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> @@ -356,50 +369,19 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">;</span> <span class="Normal">int</span> 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> <span class="Normal">if</span> <span class="Delimiter">(</span>offset < <span class="Constant">0</span> || offset >= 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> - <span class="Normal">int</span> result = base_address<span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// End GET_ADDRESS field Cases</span> - result += size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> i<span class="Delimiter">));</span> + <span class="Normal">int</span> address = base_address<span class="Delimiter">;</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> + address += size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> i<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy to is "</span> << address << end<span class="Delimiter">();</span> + <span class="Comment">// optimization: directly write the element rather than updating 'product'</span> + <span class="Comment">// and writing the entire container</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><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">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << no_scientific<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> << <span class="Constant">" in location "</span> << address+i << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+i<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> - trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << result << 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="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(scenario get_address_out_of_bounds)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">14</span>:number<span class="Special"> <- </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">+error: main: invalid offset 2 for point-number</span> - -<span class="Delimiter">:(scenario get_address_out_of_bounds_2)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">14</span>:number<span class="Special"> <- </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">+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> -container boolbool [ - <span class="Normal">x</span>:boolean - <span class="Normal">y</span>:boolean -] -def main [ - <span class="Constant">12</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">1</span> - <span class="Constant">13</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Constant">15</span>:boolean<span class="Special"> <- </span>get-address <span class="Constant">12</span>:boolbool<span class="Delimiter">,</span> <span class="Constant">1</span>:offset -] -<span class="traceContains">+error: main: 'get-address 12:boolbool, 1:offset' should write to (address boolean) but 15 has type boolean</span> - <span class="SalientComment">//:: Allow containers to be defined in mu code.</span> <span class="Delimiter">:(scenarios load)</span> @@ -463,7 +445,6 @@ container bar [ trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">" element: "</span> << to_string<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">())</span> << end<span class="Delimiter">();</span> <span class="Comment">// End Load Container Element Definition</span> <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> <span class="Normal">void</span> replace_unknown_types_with_unique_ordinals<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> <span class="Normal">const</span> type_info& info<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -590,7 +571,7 @@ container foo [ <span class="traceContains">+parse: element: {x: "number"}</span> <span class="traceContains">+parse: element: {y: "number"}</span> -<span class="Delimiter">:(before "End Transform All")</span> +<span class="Delimiter">:(before "End transform_all")</span> check_container_field_types<span class="Delimiter">();</span> <span class="Delimiter">:(code)</span> @@ -702,6 +683,14 @@ def main [ ] <span class="traceContains">+error: main: too few ingredients in '1:point-number <- merge 3, 4'</span> +<span class="Delimiter">:(scenario merge_check_reflexive)</span> +<span class="Special">% Hide_errors = true;</span> +def main [ + <span class="Constant">1</span>:point<span class="Special"> <- </span>merge <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> + <span class="Constant">2</span>:point<span class="Special"> <- </span>merge <span class="Constant">1</span>:point +] +$error: <span class="Constant">0</span> + <span class="Comment">//: Since a container can be merged in several ways, we need to be able to</span> <span class="Comment">//: backtrack through different possibilities. Later we'll allow creating</span> <span class="Comment">//: exclusive containers which contain just one of rather than all of their</span> @@ -763,6 +752,9 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa type_info& container_info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> <span class="Normal">switch</span> <span class="Delimiter">(</span>container_info<span class="Delimiter">.</span>kind<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">case</span> CONTAINER: <span class="Delimiter">{</span> + <span class="Comment">// degenerate case: merge with the same type always succeeds</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>state<span class="Delimiter">.</span>data<span class="Delimiter">.</span>top<span class="Delimiter">().</span>container_element_index == <span class="Constant">0</span> && types_coercible<span class="Delimiter">(</span>container<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">)))</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> reagent expected_ingredient = element_type<span class="Delimiter">(</span>container<span class="Delimiter">,</span> state<span class="Delimiter">.</span>data<span class="Delimiter">.</span>top<span class="Delimiter">().</span>container_element_index<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"checking container "</span> << to_string<span class="Delimiter">(</span>container<span class="Delimiter">)</span> << <span class="Constant">" || "</span> << to_string<span class="Delimiter">(</span>expected_ingredient<span class="Delimiter">)</span> << <span class="Constant">" vs ingredient "</span> << ingredient_index << end<span class="Delimiter">();</span> <span class="Comment">// if the current element is the ingredient we expect, move on to the next element/ingredient</span> @@ -790,8 +782,8 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Normal">default</span>: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>container<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"incorrect type of ingredient "</span> << ingredient_index << <span class="Constant">" in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - cerr << <span class="Constant">" expected "</span> << debug_string<span class="Delimiter">(</span>container<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> - cerr << <span class="Constant">" got "</span> << debug_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + raise << <span class="Constant">" (expected "</span> << debug_string<span class="Delimiter">(</span>container<span class="Delimiter">)</span> << <span class="Constant">")</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << <span class="Constant">" (got "</span> << debug_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">))</span> << <span class="Constant">")</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> ++ingredient_index<span class="Delimiter">;</span> diff --git a/html/031address.cc.html b/html/031address.cc.html deleted file mode 100644 index 12b53a7b..00000000 --- a/html/031address.cc.html +++ /dev/null @@ -1,279 +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 - 031address.cc</title> -<meta name="Generator" content="Vim/7.4"> -<meta name="plugin-version" content="vim7.4_v2"> -<meta name="syntax" content="cpp"> -<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> -<meta name="colorscheme" content="minimal"> -<style type="text/css"> -<!-- -pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } -body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } -* { font-size: 12pt; font-size: 1em; } -.Constant { color: #00a0a0; } -.traceAbsent { color: #c00000; } -.cSpecial { color: #008000; } -.traceContains { color: #008000; } -.SalientComment { color: #00ffff; } -.Comment { color: #9090ff; } -.Delimiter { color: #800080; } -.Special { color: #c00000; } -.Identifier { color: #fcb165; } -.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } ---> -</style> - -<script type='text/javascript'> -<!-- - ---> -</script> -</head> -<body> -<pre id='vimCodeElement'> -<span class="Comment">//: Instructions can read from addresses pointing at other locations using the</span> -<span class="Comment">//: 'lookup' property.</span> - -<span class="Delimiter">:(scenario copy_indirect)</span> -def main [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">2</span>/unsafe - <span class="Constant">2</span>:number<span class="Special"> <- </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"> <- </span>copy <span class="Constant">1</span>:address:number/lookup -] -<span class="traceContains">+mem: storing 34 in location 3</span> - -<span class="Delimiter">:(before "End Preprocess read_memory(x)")</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> -def main [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">2</span>/unsafe - <span class="Constant">1</span>:address:number/lookup<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -<span class="traceContains">+mem: storing 34 in location 2</span> - -<span class="Delimiter">:(before "End Preprocess write_memory(x)")</span> -canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"can't write to location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: writes to address 0 always loudly fail</span> -<span class="Delimiter">:(scenario store_to_0_fails)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Constant">1</span>:address:number/lookup<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -<span class="traceAbsent">-mem: storing 34 in location 0</span> -<span class="traceContains">+error: can't write to location 0 in '1:address:number/lookup <- copy 34'</span> - -<span class="Delimiter">:(code)</span> -<span class="Normal">void</span> canonize<span class="Delimiter">(</span>reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <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> - <span class="Normal">while</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">))</span> - lookup_memory<span class="Delimiter">(</span>x<span class="Delimiter">);</span> -<span class="Delimiter">}</span> - -<span class="Normal">void</span> lookup_memory<span class="Delimiter">(</span>reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to /lookup "</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">" but it isn't an address</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Comment">// compute value</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to /lookup 0</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"location "</span> << x<span class="Delimiter">.</span>value << <span class="Constant">" is "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">))</span> << 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_from_type<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - <span class="Comment">// End Drop Address In lookup_memory(x)</span> - drop_one_lookup<span class="Delimiter">(</span>x<span class="Delimiter">);</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario canonize_non_pointer_fails_without_crashing)</span> -<span class="Special">% Hide_errors = true;</span> -def foo [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset -] -<span class="Comment"># don't crash</span> - -<span class="Delimiter">:(after "bool types_strictly_match(reagent to, reagent from)")</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>to<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>from<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(after "bool is_mu_array(reagent r)")</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(after "bool is_mu_address(reagent r)")</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(after "bool is_mu_number(reagent r)")</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span class="Delimiter">:(after "bool is_mu_boolean(reagent r)")</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(after "Update product While Type-checking Merge")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - -<span class="Delimiter">:(code)</span> -<span class="Normal">bool</span> canonize_type<span class="Delimiter">(</span>reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">while</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type || r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"can't lookup non-address: "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">)</span> << <span class="Constant">": "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - drop_from_type<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - <span class="Comment">// End Drop Address In canonize_type(r)</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> - -<span class="Normal">void</span> drop_from_type<span class="Delimiter">(</span>reagent& r<span class="Delimiter">,</span> string expected_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"can't drop "</span> << expected_type << <span class="Constant">" from "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name != expected_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"can't drop2 "</span> << expected_type << <span class="Constant">" from "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><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">-></span>right<span class="Delimiter">;</span> - tmp<span class="Delimiter">-></span>right = <span class="Constant">NULL</span><span class="Delimiter">;</span> - <span class="Normal">delete</span> tmp<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Normal">void</span> drop_one_lookup<span class="Delimiter">(</span>reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">for</span> <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> string_tree*> >::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> - <span class="Normal">if</span> <span class="Delimiter">(</span>p<span class="Delimiter">-></span>first == <span class="Constant">"lookup"</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> - 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> -<span class="Delimiter">:(scenario get_indirect)</span> -def main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">2</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">4</span>:number<span class="Special"> <- </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 4</span> - -<span class="Delimiter">:(scenario get_indirect2)</span> -def main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">2</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">4</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">5</span>/unsafe - *<span class="Constant">4</span>:address:number<span class="Special"> <- </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> -def main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">2</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get <span class="Constant">1</span>:address:point/lookup/foo<span class="Delimiter">,</span> <span class="Constant">0</span>:offset -] -<span class="traceContains">+mem: storing 34 in location 4</span> - -<span class="Delimiter">:(after "Update GET base in Check")</span> -<span class="Normal">if</span> <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 "Update GET product in Check")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">:(after "Update GET base in Run")</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> -def main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">2</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">4</span>:address:number<span class="Special"> <- </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 "Update GET_ADDRESS base in Check")</span> -<span class="Normal">if</span> <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 "Update GET_ADDRESS product in Check")</span> -<span class="Normal">if</span> <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 "Update GET_ADDRESS base in Run")</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> -def main [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">2</span>/unsafe - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:number -] -<span class="traceContains">+parse: ingredient: {1: ("address" "number"), "lookup": ()}</span> -<span class="traceContains">+mem: storing 34 in location 3</span> - -<span class="Delimiter">:(before "End Parsing reagent")</span> -<span class="Delimiter">{</span> - <span class="Normal">while</span> <span class="Delimiter">(</span>!name<span class="Delimiter">.</span>empty<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> - 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<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise << <span class="Constant">"illegal name "</span> << original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> -<span class="Delimiter">}</span> - -<span class="SalientComment">//:: helpers for debugging</span> - -<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -_DUMP<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$dump"</span><span class="Delimiter">,</span> _DUMP<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> _DUMP: <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 << maybe<span class="Delimiter">(</span>current_recipe_name<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="Constant">' '</span> << 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> << <span class="Constant">" => "</span> << no_scientific<span class="Delimiter">(</span>after_canonize<span class="Delimiter">.</span>value<span class="Delimiter">)</span> << <span class="Constant">" => "</span> << 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> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: grab an address, and then dump its value at intervals</span> -<span class="Comment">//: useful for tracking down memory corruption (writing to an out-of-bounds address)</span> -<span class="Delimiter">:(before "End Globals")</span> -<span class="Normal">int</span> foo = -<span class="Constant">1</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -_FOO<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$foo"</span><span class="Delimiter">,</span> _FOO<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> _FOO: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>foo != -<span class="Constant">1</span><span class="Delimiter">)</span> cerr << foo << <span class="Constant">": "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> foo<span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> - <span class="Normal">else</span> cerr << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Normal">else</span> <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> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/032array.cc.html b/html/031array.cc.html index b5ce1f19..6d799a05 100644 --- a/html/032array.cc.html +++ b/html/031array.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 032array.cc</title> +<title>Mu - 031array.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -59,7 +59,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><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> - canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + <span class="Comment">// Update CREATE_ARRAY product in Check</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'create-array' cannot create non-array "</span> << product<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -82,26 +82,29 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> 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> + <span class="Comment">// Update CREATE_ARRAY product in Run</span> <span class="Normal">int</span> base_address = product<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - <span class="Normal">int</span> array_size = to_integer<span class="Delimiter">(</span>product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">);</span> + <span class="Normal">int</span> array_length = to_integer<span class="Delimiter">(</span>product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">);</span> <span class="Comment">// initialize array size, so that size_of will work</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> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << array_length << <span class="Constant">" in location "</span> << base_address << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">,</span> array_length<span class="Delimiter">);</span> <span class="Comment">// in array elements</span> <span class="Normal">int</span> 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">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"creating array of size "</span> << size << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"creating array of size "</span> << size << end<span class="Delimiter">();</span> <span class="Comment">// initialize array</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">1</span><span class="Delimiter">;</span> i <= size_of<span class="Delimiter">(</span>product<span class="Delimiter">);</span> ++i<span class="Delimiter">)</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> - 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>array_size<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Comment">// no need to update product</span> + <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario copy_array)</span> <span class="Comment"># Arrays can be copied around with a single instruction just like numbers,</span> <span class="Comment"># no matter how large they are.</span> +<span class="Comment"># You don't need to pass the size around, since each array variable stores its</span> +<span class="Comment"># size in memory at run-time. We'll call a variable with an explicit size a</span> +<span class="Comment"># 'static' array, and one without a 'dynamic' array since it can contain</span> +<span class="Comment"># arrays of many different sizes.</span> def main [ <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> @@ -114,20 +117,6 @@ def main [ <span class="traceContains">+mem: storing 15 in location 7</span> <span class="traceContains">+mem: storing 16 in location 8</span> -<span class="Delimiter">:(scenario copy_array_indirect)</span> -def main [ - <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - <span class="Constant">6</span>:array:number<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:array:number -] -<span class="traceContains">+mem: storing 3 in location 6</span> -<span class="traceContains">+mem: storing 14 in location 7</span> -<span class="traceContains">+mem: storing 15 in location 8</span> -<span class="traceContains">+mem: storing 16 in location 9</span> - <span class="Delimiter">:(scenario stash_array)</span> def main [ <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array @@ -138,18 +127,20 @@ def main [ ] <span class="traceContains">+app: foo: 3 14 15 16</span> -<span class="Comment">//: disable the size mismatch check since the destination array need not be initialized</span> -<span class="Delimiter">:(before "End size_mismatch(x) Cases")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End size_of(reagent) Cases")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type && r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'"</span> << r<span class="Delimiter">.</span>original_string << <span class="Constant">"' is an array of what?</span><span class="cSpecial">\n</span><span class="Constant">"</span> << 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="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="Identifier">return</span> <span class="Constant">1</span> + array_length<span class="Delimiter">(</span>r<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="Comment">//: disable the size mismatch check for arrays since the destination array</span> +<span class="Comment">//: need not be initialized</span> +<span class="Delimiter">:(before "End size_mismatch(x) Cases")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Comment">//: arrays are disallowed inside containers unless their length is fixed in</span> <span class="Comment">//: advance</span> @@ -215,14 +206,20 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><span class="Delimiter">;</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> + <span class="Comment">// Update INDEX base in Check</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'index' on a non-array "</span> << base<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + reagent index = 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="Comment">// Update INDEX index in Check</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>index<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'index' should be a number, but got "</span> << index<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Normal">if</span> <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> + <span class="Comment">// Update INDEX product in Check</span> reagent element<span class="Delimiter">;</span> element<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> @@ -234,28 +231,29 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> 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> + <span class="Comment">// Update INDEX base in Run</span> <span class="Normal">int</span> base_address = base<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">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"base address is "</span> << base_address << end<span class="Delimiter">();</span> <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to access location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - 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<<span class="Normal">double</span>> offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> + reagent index = 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="Comment">// Update INDEX index in Run</span> + vector<<span class="Normal">double</span>> index_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>index<span class="Delimiter">));</span> type_tree* element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> < <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> >= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"invalid index "</span> << no_scientific<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> < <span class="Constant">0</span> || index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> >= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"invalid index "</span> << no_scientific<span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Normal">int</span> 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> + <span class="Normal">int</span> src = base_address + <span class="Constant">1</span> + index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src << end<span class="Delimiter">();</span> trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"its type is "</span> << get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> element_type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>name << 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> - tmp<span class="Delimiter">.</span>type = <span class="Normal">new</span> 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> + reagent element<span class="Delimiter">;</span> + element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span> + element<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*element_type<span class="Delimiter">);</span> + <span class="Comment">// Read element</span> + products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>element<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -268,16 +266,14 @@ type_tree* array_element<span class="Delimiter">(</span><span class="Normal">con <span class="Identifier">return</span> type<span class="Delimiter">-></span>right<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(scenario index_indirect)</span> -def main [ - <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - <span class="Constant">6</span>:number<span class="Special"> <- </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="Normal">int</span> array_length<span class="Delimiter">(</span><span class="Normal">const</span> reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> to_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// this should never happen at transform time</span> + <span class="Comment">// x should already be canonized.</span> + <span class="Identifier">return</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="Delimiter">}</span> <span class="Delimiter">:(scenario index_out_of_bounds)</span> <span class="Special">% Hide_errors = true;</span> @@ -289,8 +285,7 @@ def main [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - 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> + index <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> <span class="Comment"># less than size of array in locations, but larger than its length in elements</span> ] <span class="traceContains">+error: main: invalid index 4</span> @@ -304,8 +299,7 @@ def main [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - index *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span> + index <span class="Constant">1</span>:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span> ] <span class="traceContains">+error: main: invalid index -1</span> @@ -319,10 +313,9 @@ def main [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - <span class="Constant">9</span>:number<span class="Special"> <- </span>index *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> <span class="Constant">0</span> + <span class="Constant">9</span>:number<span class="Special"> <- </span>index <span class="Constant">1</span>: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="traceContains">+error: main: 'index' on 1:array:point can't be saved in 9:number; type should be point</span> <span class="Comment">//: we might want to call 'index' without saving the results, say in a sandbox</span> @@ -336,70 +329,80 @@ def main [ ] <span class="Comment"># just don't die</span> -<span class="SalientComment">//:: To write to elements of containers, you need their address.</span> +<span class="SalientComment">//:: To write to elements of arrays, use 'put'.</span> -<span class="Delimiter">:(scenario index_address)</span> +<span class="Delimiter">:(scenario put_index)</span> def main [ <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:address:number<span class="Special"> <- </span>index-address <span class="Constant">1</span>:array:number<span class="Delimiter">,</span> <span class="Constant">0</span> + <span class="Constant">1</span>:array:number<span class="Special"> <- </span>put-index <span class="Constant">1</span>:array:number<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">34</span> ] -<span class="traceContains">+mem: storing 2 in location 5</span> +<span class="traceContains">+mem: storing 34 in location 3</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -INDEX_ADDRESS<span class="Delimiter">,</span> +PUT_INDEX<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"index-address"</span><span class="Delimiter">,</span> INDEX_ADDRESS<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"put-index"</span><span class="Delimiter">,</span> PUT_INDEX<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> INDEX_ADDRESS: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'index-address' expects exactly 2 ingredients in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> +<span class="Normal">case</span> PUT_INDEX: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">3</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'put-index' expects exactly 3 ingredients in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> 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> + <span class="Comment">// Update PUT_INDEX base in Check</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'index-address' on a non-array "</span> << base<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'put-index' on a non-array "</span> << base<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Normal">if</span> <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 index = 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="Comment">// Update PUT_INDEX index in Check</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>index<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'put-index' should have type 'number', but got "</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>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + reagent value = 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="Comment">// Update PUT_INDEX value in Check</span> reagent element<span class="Delimiter">;</span> - element<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"address"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">),</span> - <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">)));</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'index' on "</span> << base<span class="Delimiter">.</span>original_string << <span class="Constant">" can't be saved in "</span> << product<span class="Delimiter">.</span>original_string << <span class="Constant">"; type should be "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + element<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">));</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'put-index "</span> << base<span class="Delimiter">.</span>original_string << <span class="Constant">", "</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>original_string << <span class="Constant">"' should store "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" but "</span> << value<span class="Delimiter">.</span>name << <span class="Constant">" has type "</span> << names_to_string_without_quotes<span class="Delimiter">(</span>value<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> INDEX_ADDRESS: <span class="Delimiter">{</span> +<span class="Normal">case</span> PUT_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> + <span class="Comment">// Update PUT_INDEX base in Run</span> <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to access location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - 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<<span class="Normal">double</span>> offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> + reagent index = 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="Comment">// Update PUT_INDEX index in Run</span> + vector<<span class="Normal">double</span>> index_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>index<span class="Delimiter">));</span> type_tree* element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> < <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> >= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"invalid index "</span> << no_scientific<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> < <span class="Constant">0</span> || index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> >= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"invalid index "</span> << no_scientific<span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Normal">int</span> 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> - 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="Normal">int</span> address = base_address + <span class="Constant">1</span> + index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy to is "</span> << address << end<span class="Delimiter">();</span> + <span class="Comment">// optimization: directly write the element rather than updating 'product'</span> + <span class="Comment">// and writing the entire array</span> + vector<<span class="Normal">double</span>> value = read_memory<span class="Delimiter">(</span>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> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>value<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">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << no_scientific<span class="Delimiter">(</span>value<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> << <span class="Constant">" in location "</span> << address+i << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+i<span class="Delimiter">,</span> value<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(scenario index_address_out_of_bounds)</span> +<span class="Delimiter">:(scenario put_index_out_of_bounds)</span> <span class="Special">% Hide_errors = true;</span> def main [ <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> <- </span>create-array @@ -409,12 +412,12 @@ def main [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - 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="Constant">8</span>:point<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> + <span class="Constant">1</span>:array:point<span class="Special"> <- </span>put-index <span class="Constant">1</span>:array:point<span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">8</span>:point <span class="Comment"># '4' is less than size of array in locations, but larger than its length in elements</span> ] <span class="traceContains">+error: main: invalid index 4</span> -<span class="Delimiter">:(scenario index_address_out_of_bounds_2)</span> +<span class="Delimiter">:(scenario put_index_out_of_bounds_2)</span> <span class="Special">% Hide_errors = true;</span> def main [ <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> <- </span>create-array @@ -424,26 +427,11 @@ def main [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - index-address *<span class="Constant">8</span>:address:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span> + <span class="Constant">8</span>:point<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> + <span class="Constant">1</span>:array:point<span class="Special"> <- </span>put-index <span class="Constant">1</span>:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">8</span>:point ] <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> -def main [ - <span class="Constant">1</span>:array:point:<span class="Constant">3</span><span class="Special"> <- </span>create-array - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> - <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> - <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> - <span class="Constant">8</span>:address:array:point<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe - <span class="Constant">9</span>:address:number<span class="Special"> <- </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 (address point)</span> - <span class="SalientComment">//:: compute the length of an array</span> <span class="Delimiter">:(scenario array_length)</span> @@ -466,24 +454,24 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'length' expects exactly 2 ingredients in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - 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> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"tried to calculate length of non-array "</span> << x<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + reagent array = 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 LENGTH array in Check</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_array<span class="Delimiter">(</span>array<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"tried to calculate length of non-array "</span> << array<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> 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> - <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + reagent array = 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 LENGTH array in Run</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>array<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to access location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> 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>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> 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> array<span class="Delimiter">.</span>value<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -491,22 +479,8 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">//: stop copying potentially huge arrays into it.</span> <span class="Delimiter">:(before "End should_copy_ingredients Special-cases")</span> recipe_ordinal r = current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">;</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>r == CREATE_ARRAY || r == INDEX || r == INDEX_ADDRESS || r == LENGTH<span class="Delimiter">)</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>r == CREATE_ARRAY || r == INDEX || r == PUT_INDEX || r == LENGTH<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - -<span class="Comment">//: a particularly common array type is the string, or address:array:character</span> -<span class="Delimiter">:(code)</span> -<span class="Normal">bool</span> is_mu_string<span class="Delimiter">(</span><span class="Normal">const</span> reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> x<span class="Delimiter">.</span>type - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">)</span> - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">)</span> - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right == <span class="Constant">NULL</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/033exclusive_container.cc.html b/html/032exclusive_container.cc.html index 9b8d00f0..44bbd996 100644 --- a/html/033exclusive_container.cc.html +++ b/html/032exclusive_container.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 033exclusive_container.cc</title> +<title>Mu - 032exclusive_container.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -43,7 +43,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">//: We'll use this container as a running example, with two number elements.</span> <span class="Delimiter">{</span> type_ordinal tmp = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"number-or-point"</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_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> <span class="Comment">// initialize</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">"number-or-point"</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>reagent<span class="Delimiter">(</span><span class="Constant">"i:number"</span><span class="Delimiter">));</span> @@ -70,7 +70,7 @@ def main [ <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> <span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < t<span class="Delimiter">.</span>size<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> reagent tmp<span class="Delimiter">;</span> tmp<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*type<span class="Delimiter">);</span> <span class="Normal">int</span> size = size_of<span class="Delimiter">(</span>variant_type<span class="Delimiter">(</span>tmp<span class="Delimiter">,</span> i<span class="Delimiter">));</span> @@ -95,18 +95,24 @@ def main [ <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> - <span class="Constant">20</span>:address:point<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> <span class="Constant">1</span>:variant + <span class="Constant">20</span>:point<span class="Delimiter">,</span> <span class="Constant">22</span>:boolean<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> <span class="Constant">1</span>:variant ] -<span class="traceContains">+mem: storing 13 in location 20</span> +<span class="Comment"># point</span> +<span class="traceContains">+mem: storing 35 in location 20</span> +<span class="traceContains">+mem: storing 36 in location 21</span> +<span class="Comment"># boolean</span> +<span class="traceContains">+mem: storing 1 in location 22</span> <span class="Delimiter">:(scenario maybe_convert_fail)</span> def main [ <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> - <span class="Constant">20</span>:address:number<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> <span class="Constant">0</span>:variant + <span class="Constant">20</span>:number<span class="Delimiter">,</span> <span class="Constant">21</span>:boolean<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> <span class="Constant">0</span>:variant ] -<span class="traceContains">+mem: storing 0 in location 20</span> +<span class="Comment"># number: no write</span> +<span class="Comment"># boolean</span> +<span class="traceContains">+mem: storing 0 in location 21</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> MAYBE_CONVERT<span class="Delimiter">,</span> @@ -120,7 +126,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><span class="Delimiter">;</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> + <span class="Comment">// Update MAYBE_CONVERT base in Check</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'maybe-convert' should be an exclusive-container, but got "</span> << base<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -130,8 +136,12 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'maybe-convert' expects exactly 2 products in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> 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="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Comment">// Update MAYBE_CONVERT product in Check</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> populate_value<span class="Delimiter">(</span>offset<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>offset<span class="Delimiter">.</span>value >= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span> @@ -139,41 +149,56 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> reagent variant = variant_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> offset<span class="Delimiter">.</span>value<span class="Delimiter">);</span> - variant<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"address"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">),</span> variant<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>product<span class="Delimiter">,</span> variant<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'maybe-convert "</span> << base<span class="Delimiter">.</span>original_string << <span class="Constant">", "</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>original_string << <span class="Constant">"' should write to "</span> << to_string<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" but "</span> << product<span class="Delimiter">.</span>name << <span class="Constant">" has type "</span> << to_string<span class="Delimiter">(</span>product<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + reagent status = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Comment">// Update MAYBE_CONVERT status in Check</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_boolean<span class="Delimiter">(</span>status<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second product yielded by 'maybe-convert' should be a boolean, but tried to write to "</span> << inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> 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> + <span class="Comment">// Update MAYBE_CONVERT base in Run</span> <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to access location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">int</span> 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> - <span class="Normal">int</span> result<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> + <span class="Comment">// Update MAYBE_CONVERT product in Run</span> + reagent status = current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Comment">// Update MAYBE_CONVERT status in Run</span> + <span class="Comment">// optimization: directly write results to only update first product when necessary</span> <span class="Normal">if</span> <span class="Delimiter">(</span>tag == <span class="Normal">static_cast</span><<span class="Normal">int</span>><span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - result = base_address+<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Normal">const</span> reagent variant = variant_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> tag<span class="Delimiter">);</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < size_of<span class="Delimiter">(</span>variant<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">double</span> val = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address+<span class="Constant">1</span>+i<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << no_scientific<span class="Delimiter">(</span>val<span class="Delimiter">)</span> << <span class="Constant">" in location "</span> << product<span class="Delimiter">.</span>value+i << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> product<span class="Delimiter">.</span>value+i<span class="Delimiter">,</span> val<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing 1 in location "</span> << status<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> status<span class="Delimiter">.</span>value<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Delimiter">{</span> - result = <span class="Constant">0</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing 0 in location "</span> << status<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> status<span class="Delimiter">.</span>value<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="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -<span class="Normal">const</span> reagent variant_type<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_base<span class="Delimiter">,</span> <span class="Normal">int</span> tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">const</span> reagent variant_type<span class="Delimiter">(</span><span class="Normal">const</span> reagent& base<span class="Delimiter">,</span> <span class="Normal">int</span> tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>tag >= <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">-></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">-></span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">);</span> reagent element = info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>tag<span class="Delimiter">);</span> <span class="Comment">// End variant_type Special-cases</span> @@ -186,9 +211,9 @@ def main [ <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> - <span class="Constant">20</span>:address:number<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> <span class="Constant">1</span>:variant + <span class="Constant">20</span>:number<span class="Delimiter">,</span> <span class="Constant">21</span>:boolean<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> <span class="Constant">1</span>:variant ] -<span class="traceContains">+error: main: 'maybe-convert 12:number-or-point/unsafe, 1:variant' should write to (address point) but 20 has type (address number)</span> +<span class="traceContains">+error: main: 'maybe-convert 12:number-or-point/unsafe, 1:variant' should write to point but 20 has type number</span> <span class="SalientComment">//:: Allow exclusive containers to be defined in mu code.</span> @@ -373,6 +398,21 @@ def main [ ] <span class="traceContains">+error: main: too few ingredients in '1:foo <- merge 1/y, 23'</span> +<span class="Delimiter">:(scenario merge_check_exclusive_container_containing_container_4)</span> +exclusive-container foo [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:bar +] +container bar [ + <span class="Normal">a</span>:number + <span class="Normal">b</span>:number +] +def main [ + <span class="Constant">1</span>:bar<span class="Special"> <- </span>merge <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">24</span> + <span class="Constant">3</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">1</span>:bar +] +$error: <span class="Constant">0</span> + <span class="Comment">//: Since the different variants of an exclusive-container might have</span> <span class="Comment">//: different sizes, relax the size mismatch check for 'merge' instructions.</span> <span class="Delimiter">:(before "End size_mismatch(x) Cases")</span> @@ -381,7 +421,7 @@ def main [ && !current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<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>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> + <span class="Comment">// Update size_mismatch Check for MERGE(x)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</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> diff --git a/html/033address.cc.html b/html/033address.cc.html new file mode 100644 index 00000000..cdae9d7c --- /dev/null +++ b/html/033address.cc.html @@ -0,0 +1,1064 @@ +<!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 - 033address.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v2"> +<meta name="syntax" content="cpp"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 12pt; font-size: 1em; } +.Constant { color: #00a0a0; } +.traceAbsent { color: #c00000; } +.Special { color: #c00000; } +.traceContains { color: #008000; } +.cSpecial { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #800080; } +.SalientComment { color: #00ffff; } +.Identifier { color: #fcb165; } +.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Addresses help us spend less time copying data around.</span> + +<span class="Comment">//: So far we've been operating on primitives like numbers and characters, and</span> +<span class="Comment">//: we've started combining these primitives together into larger logical</span> +<span class="Comment">//: units (containers or arrays) that may contain many different primitives at</span> +<span class="Comment">//: once. Containers and arrays can grow quite large in complex programs, and</span> +<span class="Comment">//: we'd like some way to efficiently share them between recipes without</span> +<span class="Comment">//: constantly having to make copies. Right now 'next-ingredient' and 'reply'</span> +<span class="Comment">//: copy data across recipe boundaries. To avoid copying large quantities of</span> +<span class="Comment">//: data around, we'll use *addresses*. An address is a bookmark to some</span> +<span class="Comment">//: arbitrary quantity of data (the *payload*). It's a primitive, so it's as</span> +<span class="Comment">//: efficient to copy as a number. To read or modify the payload 'pointed to'</span> +<span class="Comment">//: by an address, we'll perform a *lookup*.</span> +<span class="Comment">//:</span> +<span class="Comment">//: The notion of 'lookup' isn't an instruction like 'add' or 'subtract'.</span> +<span class="Comment">//: Instead it's an operation that can be performed when reading any of the</span> +<span class="Comment">//: ingredients of an instruction, and when writing to any of the products.</span> +<span class="Comment">//: Modern computers provide efficient support for addresses and lookups,</span> +<span class="Comment">//: making this a realistic feature.</span> +<span class="Comment">//:</span> +<span class="Comment">//: To recap: an address is a bookmark to some potentially large payload, and</span> +<span class="Comment">//: you can replace any ingredient or product with a lookup to an address of</span> +<span class="Comment">//: the appropriate type. But how do we get addresses to begin with? That</span> +<span class="Comment">//: requires a little more explanation. Once we introduce the notion of</span> +<span class="Comment">//: bookmarks to data, we have to think about the life cycle of a piece of</span> +<span class="Comment">//: data and its bookmark. Otherwise several bad outcomes can result (and</span> +<span class="Comment">//: indeed *have* resulted in past languages like C):</span> +<span class="Comment">//:</span> +<span class="Comment">//: a) You can run out of memory if you don't have a way to reclaim</span> +<span class="Comment">//: data.</span> +<span class="Comment">//: b) If you allow data to be reclaimed, you have to be careful not to</span> +<span class="Comment">//: leave any stale addresses pointing at it. Otherwise your program might</span> +<span class="Comment">//: try to lookup such an address and find something unexpected. Such</span> +<span class="Comment">//: problems can be very hard to track down, and they can also be exploited</span> +<span class="Comment">//: to break into your computer over the network, etc.</span> +<span class="Comment">//:</span> +<span class="Comment">//: To avoid these problems, we introduce a *reference count* or refcount. The</span> +<span class="Comment">//: life cycle of a bit of data accessed through addresses looks like this.</span> +<span class="Comment">//:</span> +<span class="Comment">//: We create space in computer memory for it using the 'new' instruction.</span> +<span class="Comment">//: The 'new' instruction takes a type as an ingredient, allocates</span> +<span class="Comment">//: sufficient space to hold that type, and returns an address (bookmark)</span> +<span class="Comment">//: to the allocated space.</span> +<span class="Comment">//:</span> +<span class="Comment">//: x:address:number <- new number:type</span> +<span class="Comment">//:</span> +<span class="Comment">//: +------------+</span> +<span class="Comment">//: x -------> | number |</span> +<span class="Comment">//: +------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: That isn't entirely accurate. Under the hood, 'new' allocates an extra</span> +<span class="Comment">//: number -- the refcount:</span> +<span class="Comment">//:</span> +<span class="Comment">//: +------------+------------+</span> +<span class="Comment">//: x -------> | refcount | number |</span> +<span class="Comment">//: +------------+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: This probably seems like a waste of space. In practice it isn't worth</span> +<span class="Comment">//: allocating individual numbers and our payload will tend to be larger,</span> +<span class="Comment">//: so the picture would look more like this (zooming out a bit):</span> +<span class="Comment">//:</span> +<span class="Comment">//: +-------------------------+</span> +<span class="Comment">//: +---+ |</span> +<span class="Comment">//: x -------> | r | |</span> +<span class="Comment">//: +---+ DATA |</span> +<span class="Comment">//: | |</span> +<span class="Comment">//: | |</span> +<span class="Comment">//: +-------------------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: (Here 'r' denotes the refcount. It occupies a tiny amount of space</span> +<span class="Comment">//: compared to the payload.)</span> +<span class="Comment">//:</span> +<span class="Comment">//: Anyways, back to our example where the data is just a single number.</span> +<span class="Comment">//: After the call to 'new', Mu's map of memory looks like this:</span> +<span class="Comment">//:</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//: x -------> | 1 | number |</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: The refcount of 1 here indicates that this number has one bookmark</span> +<span class="Comment">//: outstanding. If you then make a copy of x, the refcount increments:</span> +<span class="Comment">//:</span> +<span class="Comment">//: y:address:number <- copy x</span> +<span class="Comment">//:</span> +<span class="Comment">//: x ---+ +---+------------+</span> +<span class="Comment">//: +---> | 2 | number |</span> +<span class="Comment">//: y ---+ +---+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: Whether you access the payload through x or y, Mu knows how many</span> +<span class="Comment">//: bookmarks are outstanding to it. When you change x or y, the refcount</span> +<span class="Comment">//: transparently decrements:</span> +<span class="Comment">//:</span> +<span class="Comment">//: x <- copy 0 # an address is just a number, you can always write 0 to it</span> +<span class="Comment">//:</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//: y -------> | 1 | number |</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: The final flourish is what happens when the refcount goes down to 0: Mu</span> +<span class="Comment">//: reclaims the space occupied by both refcount and payload in memory, and</span> +<span class="Comment">//: they're ready to be reused by later calls to 'new'.</span> +<span class="Comment">//:</span> +<span class="Comment">//: y <- copy 0</span> +<span class="Comment">//:</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//: | 0 | XXXXXXX |</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: Using refcounts fixes both our problems a) and b) above: you can use</span> +<span class="Comment">//: memory for many different purposes as many times as you want without</span> +<span class="Comment">//: running out of memory, and you don't have to worry about ever leaving a</span> +<span class="Comment">//: dangling bookmark when you reclaim memory.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Ok, let's rewind the clock back to this situation where we have an</span> +<span class="Comment">//: address:</span> +<span class="Comment">//:</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//: x -------> | 1 | number |</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: Once you have an address you can read or modify its payload by performing</span> +<span class="Comment">//: a lookup:</span> +<span class="Comment">//:</span> +<span class="Comment">//: x/lookup <- copy 34</span> +<span class="Comment">//:</span> +<span class="Comment">//: or more concisely:</span> +<span class="Comment">//:</span> +<span class="Comment">//: *x <- copy 34</span> +<span class="Comment">//:</span> +<span class="Comment">//: This modifies not x, but the payload x points to:</span> +<span class="Comment">//:</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//: x -------> | 1 | 34 |</span> +<span class="Comment">//: +---+------------+</span> +<span class="Comment">//:</span> +<span class="Comment">//: You can also read from the payload in instructions like this:</span> +<span class="Comment">//:</span> +<span class="Comment">//: z:number <- add *x, 1</span> +<span class="Comment">//:</span> +<span class="Comment">//: After this instruction runs the value of z will be 35.</span> +<span class="Comment">//:</span> +<span class="Comment">//: The rest of this (long) layer is divided up into 4 sections:</span> +<span class="Comment">//: the implementation of the 'new' instruction</span> +<span class="Comment">//: how instructions lookup addresses</span> +<span class="Comment">//: how instructions update refcounts when modifying address variables</span> +<span class="Comment">//: how instructions abandon and reclaim memory when refcounts drop to 0</span> + +<span class="SalientComment">//:: the 'new' instruction allocates unique memory including a refcount</span> +<span class="Comment">//: todo: give 'new' a custodian ingredient. Following malloc/free is a temporary hack.</span> + +<span class="Delimiter">:(scenario new)</span> +<span class="Comment"># call 'new' two times with identical types without modifying the results; you</span> +<span class="Comment"># should get back different results</span> +def main [ + <span class="Constant">1</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:number/<span class="Special">raw</span> +] +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Comment">//: 'new' takes a weird 'type' as its first ingredient; don't error on it</span> +<span class="Delimiter">:(before "End Mu Types Initialization")</span> +put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"type"</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> is_mu_type_literal<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> is_literal<span class="Delimiter">(</span>r<span class="Delimiter">)</span> && r<span class="Delimiter">.</span>type && r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"type"</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +NEW<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"new"</span><span class="Delimiter">,</span> NEW<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> NEW: <span class="Delimiter">{</span> + <span class="Normal">const</span> recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + <span class="Normal">if</span> <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> > <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'new' requires one or two ingredients, but got "</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="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> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_type_literal<span class="Delimiter">(</span>type<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'new' should be a type, but got "</span> << type<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"result of 'new' should never be ignored</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!product_of_new_is_valid<span class="Delimiter">(</span>inst<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"product of 'new' has incorrect type: "</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> product_of_new_is_valid<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<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> + canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// array allocation</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + reagent expected_product<span class="Delimiter">(</span><span class="Constant">"x:"</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(expected_product) When Checking 'new'</span> + <span class="Identifier">return</span> types_strictly_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> expected_product<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: To implement 'new', a Mu transform turns all 'new' instructions into</span> +<span class="Comment">//: 'allocate' instructions that precompute the amount of memory they want to</span> +<span class="Comment">//: allocate.</span> + +<span class="Comment">//: Ensure that we never call 'allocate' directly, and that there's no 'new'</span> +<span class="Comment">//: instructions left after the transforms have run.</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> ALLOCATE: <span class="Delimiter">{</span> + raise << <span class="Constant">"never call 'allocate' directly'; always use 'new'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> NEW: <span class="Delimiter">{</span> + raise << <span class="Constant">"no implementation for 'new'; why wasn't it translated to 'allocate'? Please save a copy of your program and send it to Kartik.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after "Transform.push_back(check_instruction)")</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> +<span class="Normal">void</span> transform_new_to_allocate<span class="Delimiter">(</span><span class="Normal">const</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">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- convert 'new' to 'allocate' for recipe "</span> << get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name << end<span class="Delimiter">();</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>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& 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> + <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"new"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = ALLOCATE<span class="Delimiter">;</span> + string_tree* type_name = <span class="Normal">new</span> 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">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"size of "</span> << to_string<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> << <span class="Constant">" is "</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>value << end<span class="Delimiter">();</span> + <span class="Normal">delete</span> type<span class="Delimiter">;</span> + <span class="Normal">delete</span> type_name<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: implement 'allocate' based on size</span> + +<span class="Delimiter">:(before "End Globals")</span> +<span class="Normal">const</span> <span class="Normal">int</span> Reserved_for_tests = <span class="Constant">1000</span><span class="Delimiter">;</span> +<span class="Normal">int</span> Memory_allocated_until = Reserved_for_tests<span class="Delimiter">;</span> +<span class="Normal">int</span> Initial_memory_per_routine = <span class="Constant">100000</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +Memory_allocated_until = Reserved_for_tests<span class="Delimiter">;</span> +Initial_memory_per_routine = <span class="Constant">100000</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Fields")</span> +<span class="Normal">int</span> alloc<span class="Delimiter">,</span> alloc_max<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Constructor")</span> +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><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"routine allocated memory from "</span> << alloc << <span class="Constant">" to "</span> << alloc_max << end<span class="Delimiter">();</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +ALLOCATE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"allocate"</span><span class="Delimiter">,</span> ALLOCATE<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> ALLOCATE: <span class="Delimiter">{</span> + <span class="Comment">// compute the space we need</span> + <span class="Normal">int</span> 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> + <span class="Normal">if</span> <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> + <span class="Comment">// array allocation</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"array size is "</span> << ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + size = <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span> + size*ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// include space for refcount</span> + size++<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"allocating size "</span> << size << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? Total_alloc += size;</span> +<span class="CommentedCode">//? Num_alloc++;</span> + <span class="Comment">// compute the region of memory to return</span> + <span class="Comment">// really crappy at the moment</span> + ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span> + <span class="Normal">const</span> <span class="Normal">int</span> result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new alloc: "</span> << result << end<span class="Delimiter">();</span> + <span class="Comment">// save result</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Comment">// initialize allocated space</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> address = result<span class="Delimiter">;</span> address < result+size<span class="Delimiter">;</span> ++address<span class="Delimiter">)</span> + 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="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// initialize array length</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> << <span class="Constant">" in location "</span> << result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + <span class="Delimiter">}</span> + Current_routine<span class="Delimiter">-></span>alloc += size<span class="Delimiter">;</span> + <span class="Comment">// no support yet for reclaiming memory between routines</span> + assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc <= Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: statistics for debugging</span> +<span class="CommentedCode">//? :(before "End Globals")</span> +<span class="CommentedCode">//? int Total_alloc = 0;</span> +<span class="CommentedCode">//? int Num_alloc = 0;</span> +<span class="CommentedCode">//? int Total_free = 0;</span> +<span class="CommentedCode">//? int Num_free = 0;</span> +<span class="CommentedCode">//? :(before "End Setup")</span> +<span class="CommentedCode">//? Total_alloc = Num_alloc = Total_free = Num_free = 0;</span> +<span class="CommentedCode">//? :(before "End Teardown")</span> +<span class="CommentedCode">//? cerr << Total_alloc << "/" << Num_alloc</span> +<span class="CommentedCode">//? << " vs " << Total_free << "/" << Num_free << '\n';</span> +<span class="CommentedCode">//? cerr << SIZE(Memory) << '\n';</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> ensure_space<span class="Delimiter">(</span><span class="Normal">int</span> size<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>size > Initial_memory_per_routine<span class="Delimiter">)</span> <span class="Delimiter">{</span> + tb_shutdown<span class="Delimiter">();</span> + cerr << <span class="Constant">"can't allocate "</span> << size << <span class="Constant">" locations, that's too much compared to "</span> << Initial_memory_per_routine << <span class="Constant">".</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc + size > Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// waste the remaining space and create a new chunk</span> + Current_routine<span class="Delimiter">-></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">-></span>alloc_max = Memory_allocated_until<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"routine allocated memory from "</span> << Current_routine<span class="Delimiter">-></span>alloc << <span class="Constant">" to "</span> << Current_routine<span class="Delimiter">-></span>alloc_max << 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">% put(Memory, Memory_allocated_until, 1);</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number/lookup +] +<span class="traceContains">+mem: storing 0 in location 2</span> + +<span class="Delimiter">:(scenario new_error)</span> +<span class="Special">% Hide_errors = true;</span> +def main [ + <span class="Constant">1</span>:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type +] +<span class="traceContains">+error: main: product of 'new' has incorrect type: 1:number/raw <- new number:type</span> + +<span class="Delimiter">:(scenario new_array)</span> +def main [ + <span class="Constant">1</span>:address:array:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">5</span> + <span class="Constant">2</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">3</span>:number/<span class="Special">raw <- </span>subtract <span class="Constant">2</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:number/<span class="Special">raw</span> +] +<span class="traceContains">+run: {1: ("address" "array" "number"), "raw": ()} <- new {number: "type"}, {5: "literal"}</span> +<span class="traceContains">+mem: array size is 5</span> +<span class="Comment"># don't forget the extra location for array size, and the second extra location for the refcount</span> +<span class="traceContains">+mem: storing 7 in location 3</span> + +<span class="Delimiter">:(scenario new_empty_array)</span> +def main [ + <span class="Constant">1</span>:address:array:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">0</span> + <span class="Constant">2</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">3</span>:number/<span class="Special">raw <- </span>subtract <span class="Constant">2</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:number/<span class="Special">raw</span> +] +<span class="traceContains">+run: {1: ("address" "array" "number"), "raw": ()} <- new {number: "type"}, {0: "literal"}</span> +<span class="traceContains">+mem: array size is 0</span> +<span class="Comment"># one location for array size, and one for the refcount</span> +<span class="traceContains">+mem: storing 2 in location 3</span> + +<span class="Comment">//: If a routine runs out of its initial allocation, it should allocate more.</span> +<span class="Delimiter">:(scenario new_overflow)</span> +<span class="Special">% Initial_memory_per_routine = 3; // barely enough room for point allocation below</span> +def main [ + <span class="Constant">1</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:address:point/<span class="Special">raw <- </span><span class="Normal">new</span> point:type <span class="Comment"># not enough room in initial page</span> +] +<span class="traceContains">+new: routine allocated memory from 1000 to 1003</span> +<span class="traceContains">+new: routine allocated memory from 1003 to 1006</span> + +<span class="SalientComment">//:: /lookup can go from an address to the payload it points at, skipping the refcount</span> +<span class="Comment">//: the tests in this section use unsafe operations so as to stay decoupled from 'new'</span> + +<span class="Delimiter">:(scenario copy_indirect)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">11</span>:number<span class="Special"> <- </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">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number/lookup +] +<span class="Comment"># 1 contains 10. Skip refcount and lookup location 11.</span> +<span class="traceContains">+mem: storing 34 in location 2</span> + +<span class="Delimiter">:(before "End Preprocess read_memory(x)")</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> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">1</span>:address:number/lookup<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+mem: storing 34 in location 11</span> + +<span class="Delimiter">:(before "End Preprocess write_memory(x)")</span> +canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"can't write to location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: writes to address 0 always loudly fail</span> +<span class="Delimiter">:(scenario store_to_0_fails)</span> +<span class="Special">% Hide_errors = true;</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">1</span>:address:number/lookup<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +<span class="traceAbsent">-mem: storing 34 in location 0</span> +<span class="traceContains">+error: can't write to location 0 in '1:address:number/lookup <- copy 34'</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> canonize<span class="Delimiter">(</span>reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <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> + <span class="Normal">while</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">))</span> + lookup_memory<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> lookup_memory<span class="Delimiter">(</span>reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to /lookup "</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">" but it isn't an address</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Comment">// compute value</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to /lookup 0</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"location "</span> << x<span class="Delimiter">.</span>value << <span class="Constant">" is "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">))</span> << 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_from_type<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>value != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"skipping refcount at "</span> << x<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// skip refcount</span> + <span class="Delimiter">}</span> + drop_one_lookup<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> test_lookup_address_skips_refcount<span class="Delimiter">()</span> <span class="Delimiter">{</span> + reagent x<span class="Delimiter">(</span><span class="Constant">"*x:address:number"</span><span class="Delimiter">);</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">34</span><span class="Delimiter">);</span> <span class="Comment">// unsafe</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">1000</span><span class="Delimiter">);</span> + lookup_memory<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"mem: skipping refcount at 1000"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">,</span> <span class="Constant">1001</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> test_lookup_zero_address_does_not_skip_refcount<span class="Delimiter">()</span> <span class="Delimiter">{</span> + reagent x<span class="Delimiter">(</span><span class="Constant">"*x:address:number"</span><span class="Delimiter">);</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">34</span><span class="Delimiter">);</span> <span class="Comment">// unsafe</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> + lookup_memory<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + CHECK_TRACE_DOESNT_CONTAIN<span class="Delimiter">(</span><span class="Constant">"mem: skipping refcount at 0"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after "bool types_strictly_match(reagent to, reagent from)")</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>to<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>from<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after "bool is_mu_array(reagent r)")</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after "bool is_mu_address(reagent r)")</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after "bool is_mu_number(reagent r)")</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "bool is_mu_boolean(reagent r)")</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after "Update product While Type-checking Merge")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Compute Call Ingredient")</span> +canonize_type<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Preprocess NEXT_INGREDIENT product")</span> +canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Check REPLY Copy(lhs, rhs)</span> +canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> +canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> canonize_type<span class="Delimiter">(</span>reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">while</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type || r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"can't lookup non-address: "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">)</span> << <span class="Constant">": "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + drop_from_type<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"address"</span><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> + +<span class="Normal">void</span> drop_from_type<span class="Delimiter">(</span>reagent& r<span class="Delimiter">,</span> string expected_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name != expected_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"can't drop2 "</span> << expected_type << <span class="Constant">" from "</span> << to_string<span class="Delimiter">(</span>r<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><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">-></span>right<span class="Delimiter">;</span> + tmp<span class="Delimiter">-></span>right = <span class="Constant">NULL</span><span class="Delimiter">;</span> + <span class="Normal">delete</span> tmp<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> drop_one_lookup<span class="Delimiter">(</span>reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> string_tree*> >::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> + <span class="Normal">if</span> <span class="Delimiter">(</span>p<span class="Delimiter">-></span>first == <span class="Constant">"lookup"</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> + assert<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Tedious fixup to support addresses in container/array instructions of previous layers.</span> +<span class="Comment">//: Most instructions don't require fixup if they use the 'ingredients' and</span> +<span class="Comment">//: 'products' variables in run_current_routine().</span> + +<span class="Delimiter">:(scenario get_indirect)</span> +def main [ + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">2</span>:number<span class="Special"> <- </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 2</span> + +<span class="Delimiter">:(scenario get_indirect2)</span> +def main [ + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe + <span class="Constant">2</span>:address:number/lookup<span class="Special"> <- </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 21</span> + +<span class="Delimiter">:(scenario include_nonlookup_properties)</span> +def main [ + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>get <span class="Constant">1</span>:address:point/lookup/foo<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+mem: storing 34 in location 2</span> + +<span class="Delimiter">:(after "Update GET base in Check")</span> +<span class="Normal">if</span> <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 "Update GET product in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "Update GET base in Run")</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario put_indirect)</span> +def main [ + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">1</span>:address:point/lookup<span class="Special"> <- </span>put <span class="Constant">1</span>:address:point/lookup<span class="Delimiter">,</span> <span class="Constant">0</span>:offset<span class="Delimiter">,</span> <span class="Constant">36</span> +] +<span class="traceContains">+mem: storing 36 in location 11</span> + +<span class="Delimiter">:(after "Update PUT base in Check")</span> +<span class="Normal">if</span> <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 "Update PUT offset in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "Update PUT base in Run")</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario copy_array_indirect)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> + <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">2</span>:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:array:number/lookup +] +<span class="traceContains">+mem: storing 3 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 "Update CREATE_ARRAY product in Check")</span> +<span class="Comment">// 'create-array' does not support indirection. Static arrays are meant to be</span> +<span class="Comment">// allocated on the 'stack'.</span> +assert<span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">));</span> +<span class="Delimiter">:(before "Update CREATE_ARRAY product in Run")</span> +<span class="Comment">// 'create-array' does not support indirection. Static arrays are meant to be</span> +<span class="Comment">// allocated on the 'stack'.</span> +assert<span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">));</span> + +<span class="Delimiter">:(scenario index_indirect)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> + <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">2</span>:number<span class="Special"> <- </span>index <span class="Constant">1</span>:address:array:number/lookup<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+mem: storing 15 in location 2</span> + +<span class="Delimiter">:(before "Update INDEX base in Check")</span> +<span class="Normal">if</span> <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">:(before "Update INDEX index in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>index<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "Update INDEX product in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "Update INDEX base in Run")</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> +<span class="Delimiter">:(before "Update INDEX index in Run")</span> +canonize<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario put_index_indirect)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> + <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">1</span>:address:array:number/lookup<span class="Special"> <- </span>put-index <span class="Constant">1</span>:address:array:number/lookup<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">34</span> +] +<span class="traceContains">+mem: storing 34 in location 13</span> + +<span class="Delimiter">:(scenario put_index_indirect_2)</span> +def main [ + <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> + <span class="Constant">5</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> + <span class="Constant">5</span>:address:array:number/lookup<span class="Special"> <- </span>put-index <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">5</span>:address:number/lookup<span class="Delimiter">,</span> <span class="Constant">34</span> +] +<span class="traceContains">+mem: storing 34 in location 3</span> + +<span class="Delimiter">:(before "Update PUT_INDEX base in Check")</span> +<span class="Normal">if</span> <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">:(before "Update PUT_INDEX index in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>index<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "Update PUT_INDEX value in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>value<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "Update PUT_INDEX base in Run")</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> +<span class="Delimiter">:(before "Update PUT_INDEX index in Run")</span> +canonize<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario length_indirect)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span> + <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">2</span>:number<span class="Special"> <- </span>length <span class="Constant">1</span>:address:array:number/lookup +] +<span class="traceContains">+mem: storing 3 in location 2</span> + +<span class="Delimiter">:(before "Update LENGTH array in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>array<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "Update LENGTH array in Run")</span> +canonize<span class="Delimiter">(</span>array<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario maybe_convert_indirect)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>merge <span class="Constant">0</span>/number<span class="Delimiter">,</span> <span class="Constant">34</span> + <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span>:boolean<span class="Special"> <- </span>maybe-convert <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point/lookup<span class="Delimiter">,</span> i:variant +] +<span class="traceContains">+mem: storing 34 in location 2</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario maybe_convert_indirect_2)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>merge <span class="Constant">0</span>/number<span class="Delimiter">,</span> <span class="Constant">34</span> + <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe + <span class="Constant">2</span>:address:number/lookup<span class="Delimiter">,</span> <span class="Constant">3</span>:boolean<span class="Special"> <- </span>maybe-convert <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point/lookup<span class="Delimiter">,</span> i:variant +] +<span class="traceContains">+mem: storing 34 in location 21</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario maybe_convert_indirect_3)</span> +def main [ + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>merge <span class="Constant">0</span>/number<span class="Delimiter">,</span> <span class="Constant">34</span> + <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">2</span>:address:boolean<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe + <span class="Constant">3</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:boolean/lookup<span class="Special"> <- </span>maybe-convert <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point/lookup<span class="Delimiter">,</span> i:variant +] +<span class="traceContains">+mem: storing 34 in location 3</span> +<span class="traceContains">+mem: storing 1 in location 21</span> + +<span class="Delimiter">:(before "Update MAYBE_CONVERT base in Check")</span> +<span class="Normal">if</span> <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">:(before "Update MAYBE_CONVERT product in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "Update MAYBE_CONVERT status in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>status<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "Update MAYBE_CONVERT base in Run")</span> +canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> +<span class="Delimiter">:(before "Update MAYBE_CONVERT product in Run")</span> +canonize<span class="Delimiter">(</span>product<span class="Delimiter">);</span> +<span class="Delimiter">:(before "Update MAYBE_CONVERT status in Run")</span> +canonize<span class="Delimiter">(</span>status<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario merge_exclusive_container_indirect)</span> +def main [ + <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">1</span>:address:number-<span class="Normal">or</span>-point/lookup<span class="Special"> <- </span>merge <span class="Constant">0</span>/number<span class="Delimiter">,</span> <span class="Constant">34</span> +] +<span class="Comment"># skip 10 for refcount</span> +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="traceContains">+mem: storing 34 in location 12</span> + +<span class="Delimiter">:(before "Update size_mismatch Check for MERGE(x)</span> +canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + +<span class="Comment">//: abbreviation for '/lookup': a prefix '*'</span> + +<span class="Delimiter">:(scenario lookup_abbreviation)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:number +] +<span class="traceContains">+parse: ingredient: {1: ("address" "number"), "lookup": ()}</span> +<span class="traceContains">+mem: storing 34 in location 3</span> + +<span class="Delimiter">:(before "End Parsing reagent")</span> +<span class="Delimiter">{</span> + <span class="Normal">while</span> <span class="Delimiter">(</span>!name<span class="Delimiter">.</span>empty<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> + 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<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + raise << <span class="Constant">"illegal name "</span> << original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: update refcounts when copying addresses</span> + +<span class="Delimiter">:(scenario refcounts)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +<span class="traceContains">+run: {1: ("address" "number")} <- copy {1000: "literal", "unsafe": ()}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> +<span class="traceContains">+run: {2: ("address" "number")} <- copy {1: ("address" "number")}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> +<span class="traceContains">+run: {1: ("address" "number")} <- copy {0: "literal"}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> +<span class="traceContains">+run: {2: ("address" "number")} <- copy {0: "literal"}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> +<span class="Comment"># the /unsafe corrupts memory but fortunately we won't be running any more 'new' in this scenario</span> +<span class="traceContains">+mem: automatically abandoning 1000</span> + +<span class="Delimiter">:(before "End write_memory(reagent x) Special-cases")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// compute old address of x, as well as new address we want to write in</span> + <span class="Normal">int</span> old_address = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span> + <span class="Normal">int</span> new_address = data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Comment">// decrement refcount of old address</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>old_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">int</span> old_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"decrementing refcount of "</span> << old_address << <span class="Constant">": "</span> << old_refcount << <span class="Constant">" -> "</span> << <span class="Delimiter">(</span>old_refcount-<span class="Constant">1</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">,</span> old_refcount-<span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// perform the write</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << no_scientific<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="Constant">" in location "</span> << x<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> + <span class="Comment">// increment refcount of new address</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">int</span> new_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>new_refcount >= <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// == 0 only when new_address == old_address</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"incrementing refcount of "</span> << new_address << <span class="Constant">": "</span> << new_refcount << <span class="Constant">" -> "</span> << <span class="Delimiter">(</span>new_refcount+<span class="Constant">1</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">,</span> new_refcount+<span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// abandon old address if necessary</span> + <span class="Comment">// do this after all refcount updates are done just in case old and new are identical</span> + assert<span class="Delimiter">(</span>old_address >= <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>old_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">)</span> < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + DUMP<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> + cerr << old_address << <span class="Constant">' '</span> << get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">)</span> >= <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">)</span> > <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Comment">// lookup_memory without drop_one_lookup {</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"automatically abandoning "</span> << old_address << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"computing size to abandon at "</span> << x<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>old_address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> + drop_from_type<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> + <span class="Comment">// }</span> + abandon<span class="Delimiter">(</span>old_address<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario refcounts_2)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Comment"># over-writing one allocation with another</span> + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +<span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> +<span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> +<span class="traceContains">+mem: automatically abandoning 1000</span> + +<span class="Delimiter">:(scenario refcounts_3)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Comment"># passing in addresses to recipes increments refcount</span> + foo <span class="Constant">1</span>:address:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +def foo [ + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>next-ingredient + <span class="Comment"># return does NOT yet decrement refcount; memory must be explicitly managed</span> + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +<span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> +<span class="traceContains">+run: {2: ("address" "number")} <- next-ingredient</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> +<span class="traceContains">+run: {2: ("address" "number")} <- copy {0: "literal"}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> +<span class="traceContains">+run: {1: ("address" "number")} <- copy {0: "literal"}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> +<span class="traceContains">+mem: automatically abandoning 1000</span> + +<span class="Delimiter">:(scenario refcounts_4)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Comment"># idempotent copies leave refcount unchanged</span> + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number +] +<span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> +<span class="traceContains">+run: {1: ("address" "number")} <- copy {1: ("address" "number")}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> + +<span class="Delimiter">:(scenario refcounts_5)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Comment"># passing in addresses to recipes increments refcount</span> + foo <span class="Constant">1</span>:address:number + <span class="Comment"># return does NOT yet decrement refcount; memory must be explicitly managed</span> + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type +] +def foo [ + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>next-ingredient +] +<span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> +<span class="traceContains">+run: {2: ("address" "number")} <- next-ingredient</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> +<span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> + +<span class="Delimiter">:(scenario refcounts_array)</span> +def main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">30</span> + <span class="Comment"># allocate an array</span> + <span class="Constant">10</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">20</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span>:address:array:number + <span class="Comment"># allocate another array in its place, implicitly freeing the previous allocation</span> + <span class="Constant">10</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">25</span> +] +<span class="traceContains">+run: {10: ("address" "array" "number")} <- new {number: "type"}, {20: "literal"}</span> +<span class="Comment"># abandoned array is of old size (20, not 25)</span> +<span class="traceContains">+abandon: saving in free-list of size 22</span> + +<span class="SalientComment">//:: abandon and reclaim memory when refcount drops to 0</span> + +<span class="Delimiter">:(scenario new_reclaim)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number <span class="Comment"># because 1 will get reset during abandon below</span> + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># abandon</span> + <span class="Constant">3</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type <span class="Comment"># must be same size as abandoned memory to reuse</span> + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span>:address:number +] +<span class="Comment"># both allocations should have returned the same address</span> +<span class="traceContains">+mem: storing 1 in location 4</span> + +<span class="Comment">//: When abandoning addresses we'll save them to a 'free list', segregated by size.</span> + +<span class="Delimiter">:(before "End routine Fields")</span> +map<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>> free_list<span class="Delimiter">;</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> abandon<span class="Delimiter">(</span><span class="Normal">int</span> address<span class="Delimiter">,</span> <span class="Normal">int</span> size<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"saving in free-list of size "</span> << size << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? Total_free += size;</span> +<span class="CommentedCode">//? Num_free++;</span> +<span class="CommentedCode">//? cerr << "abandon: " << size << '\n';</span> + <span class="Comment">// clear memory</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address<span class="Delimiter">;</span> curr < address+size<span class="Delimiter">;</span> ++curr<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> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">));</span> + put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">,</span> address<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "ensure_space(size)" following "case ALLOCATE")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">))</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"picking up space from free-list of size "</span> << size << end<span class="Delimiter">();</span> + <span class="Normal">int</span> result = get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new alloc from free list: "</span> << result << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">));</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = result+<span class="Constant">1</span><span class="Delimiter">;</span> curr < result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"memory in free list was not zeroed out: "</span> << curr << <span class="Constant">'/'</span> << result << <span class="Constant">"; somebody wrote to us after free!!!</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// always fatal</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + <span class="Normal">else</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario new_differing_size_no_reclaim)</span> +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># abandon</span> + <span class="Constant">3</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> <span class="Comment"># different size</span> + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:number +] +<span class="Comment"># no reuse</span> +<span class="traceContains">+mem: storing 0 in location 4</span> + +<span class="Delimiter">:(scenario new_reclaim_array)</span> +def main [ + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:array:number + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># abandon</span> + <span class="Constant">3</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> <span class="Comment"># same size</span> + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:number +] +<span class="Comment"># reuse</span> +<span class="traceContains">+mem: storing 1 in location 4</span> + +<span class="SalientComment">//:: helpers for debugging</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_DUMP<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$dump"</span><span class="Delimiter">,</span> _DUMP<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> _DUMP: <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 << maybe<span class="Delimiter">(</span>current_recipe_name<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="Constant">' '</span> << 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> << <span class="Constant">" => "</span> << no_scientific<span class="Delimiter">(</span>after_canonize<span class="Delimiter">.</span>value<span class="Delimiter">)</span> << <span class="Constant">" => "</span> << 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> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: grab an address, and then dump its value at intervals</span> +<span class="Comment">//: useful for tracking down memory corruption (writing to an out-of-bounds address)</span> +<span class="Delimiter">:(before "End Globals")</span> +<span class="Normal">int</span> Bar = -<span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_BAR<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$bar"</span><span class="Delimiter">,</span> _BAR<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> _BAR: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Bar != -<span class="Constant">1</span><span class="Delimiter">)</span> cerr << Bar << <span class="Constant">": "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Bar<span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Normal">else</span> cerr << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <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> + Bar = 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> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/034new_text.cc.html b/html/034new_text.cc.html new file mode 100644 index 00000000..f818078c --- /dev/null +++ b/html/034new_text.cc.html @@ -0,0 +1,161 @@ +<!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 - 034new_text.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v2"> +<meta name="syntax" content="cpp"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 12pt; font-size: 1em; } +.Constant { color: #00a0a0; } +.traceContains { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #800080; } +.Special { color: #c00000; } +.Identifier { color: #fcb165; } +.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Extend 'new' to handle a unicode string literal argument.</span> + +<span class="Delimiter">:(scenario new_string)</span> +def main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc def] + <span class="Constant">2</span>:character<span class="Special"> <- </span>index *<span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">5</span> +] +<span class="Comment"># number code for 'e'</span> +<span class="traceContains">+mem: storing 101 in location 2</span> + +<span class="Delimiter">:(scenario new_string_handles_unicode)</span> +def main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [a«c] + <span class="Constant">2</span>:number<span class="Special"> <- </span>length *<span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:character<span class="Special"> <- </span>index *<span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+mem: storing 3 in location 2</span> +<span class="Comment"># unicode for '«'</span> +<span class="traceContains">+mem: storing 171 in location 3</span> + +<span class="Delimiter">:(before "End NEW Check Special-cases")</span> +<span class="Normal">if</span> <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 "Convert 'new' To 'allocate'")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"new"</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">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "case NEW" following "Primitive Recipe Implementations")</span> + <span class="Normal">if</span> <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> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new string alloc: "</span> << products<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> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">int</span> new_mu_string<span class="Delimiter">(</span><span class="Normal">const</span> string& contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// allocate an array just large enough for it</span> + <span class="Normal">int</span> string_length = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> +<span class="CommentedCode">//? Total_alloc += string_length+1;</span> +<span class="CommentedCode">//? Num_alloc++;</span> + 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> + <span class="Normal">int</span> result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> + <span class="Comment">// initialize refcount</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc++<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Comment">// store length</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc++<span class="Delimiter">,</span> string_length<span class="Delimiter">);</span> + <span class="Normal">int</span> curr = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">const</span> <span class="Normal">char</span>* raw_contents = contents<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < string_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">uint32_t</span> curr_character<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>curr < SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> + tb_utf8_char_to_unicode<span class="Delimiter">(</span>&curr_character<span class="Delimiter">,</span> &raw_contents[curr]<span class="Delimiter">);</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></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">-></span>alloc<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Comment">// mu strings are not null-terminated in memory</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: stash recognizes strings</span> + +<span class="Delimiter">:(scenario stash_string)</span> +def main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character +] +<span class="traceContains">+app: foo: abc</span> + +<span class="Delimiter">:(before "End print Special-cases(reagent r, data)")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span> + <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="Constant">' '</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario unicode_string)</span> +def main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [♠] + stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character +] +<span class="traceContains">+app: foo: ♠</span> + +<span class="Delimiter">:(scenario stash_space_after_string)</span> +def main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + stash <span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> [foo] +] +<span class="traceContains">+app: abc 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> +def main [ + <span class="Constant">1</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:address:array:character/<span class="Special">raw <- </span><span class="Normal">new</span> [a] <span class="Comment"># not enough room in initial page, if you take the array size into account</span> +] +<span class="traceContains">+new: routine allocated memory from 1000 to 1002</span> +<span class="traceContains">+new: routine allocated memory from 1002 to 1004</span> + +<span class="Comment">//: helpers</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">int</span> unicode_length<span class="Delimiter">(</span><span class="Normal">const</span> string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">const</span> <span class="Normal">char</span>* in = s<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> + <span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">int</span> curr = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">while</span> <span class="Delimiter">(</span>curr < SIZE<span class="Delimiter">(</span>s<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// carefully bounds-check on the string</span> + <span class="Comment">// before accessing its raw pointer</span> + ++result<span class="Delimiter">;</span> + curr += tb_utf8_char_length<span class="Delimiter">(</span>in[curr]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +string read_mu_string<span class="Delimiter">(</span><span class="Normal">int</span> address<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> + address++<span class="Delimiter">;</span> <span class="Comment">// skip refcount</span> + <span class="Normal">int</span> size = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>size == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> + ostringstream tmp<span class="Delimiter">;</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address+<span class="Constant">1</span><span class="Delimiter">;</span> curr <= address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + tmp << to_unicode<span class="Delimiter">(</span><span class="Normal">static_cast</span><<span class="Normal">uint32_t</span>><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> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/038location_array.cc.html b/html/035location_array.cc.html index 9e77007e..172b1a56 100644 --- a/html/038location_array.cc.html +++ b/html/035location_array.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 038location_array.cc</title> +<title>Mu - 035location_array.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -37,19 +37,17 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> <span class="Normal">case</span> TO_LOCATION_ARRAY: <span class="Delimiter">{</span> <span class="Normal">const</span> recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_shared_address_of_array_of_numbers<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> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_address_of_array_of_numbers<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"product of 'to-location-array' has incorrect type: "</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -<span class="Normal">bool</span> is_shared_address_of_array_of_numbers<span class="Delimiter">(</span>reagent product<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">bool</span> is_address_of_array_of_numbers<span class="Delimiter">(</span>reagent product<span class="Delimiter">)</span> <span class="Delimiter">{</span> canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> diff --git a/html/037new.cc.html b/html/037new.cc.html deleted file mode 100644 index c932c8af..00000000 --- a/html/037new.cc.html +++ /dev/null @@ -1,704 +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 - 037new.cc</title> -<meta name="Generator" content="Vim/7.4"> -<meta name="plugin-version" content="vim7.4_v2"> -<meta name="syntax" content="cpp"> -<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> -<meta name="colorscheme" content="minimal"> -<style type="text/css"> -<!-- -pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } -body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } -* { font-size: 12pt; font-size: 1em; } -.Constant { color: #00a0a0; } -.cSpecial { color: #008000; } -.traceContains { color: #008000; } -.SalientComment { color: #00ffff; } -.Comment { color: #9090ff; } -.Delimiter { color: #800080; } -.Special { color: #c00000; } -.Identifier { color: #fcb165; } -.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } -.CommentedCode { color: #6c6c6c; } ---> -</style> - -<script type='text/javascript'> -<!-- - ---> -</script> -</head> -<body> -<pre id='vimCodeElement'> -<span class="Comment">//: Creating space for new variables at runtime.</span> - -<span class="Comment">//: Mu has two primitives for managing allocations:</span> -<span class="Comment">//: - 'allocate' reserves a specified amount of space</span> -<span class="Comment">//: - 'abandon' returns allocated space to be reused by future calls to 'allocate'</span> -<span class="Comment">//:</span> -<span class="Comment">//: In practice it's useful to let programs copy addresses anywhere they want,</span> -<span class="Comment">//: but a prime source of (particularly security) bugs is accessing memory</span> -<span class="Comment">//: after it's been abandoned. To avoid this, mu programs use a safer</span> -<span class="Comment">//: primitive called 'new', which adds two features:</span> -<span class="Comment">//:</span> -<span class="Comment">//: - it takes a type rather than a size, to save you the trouble of</span> -<span class="Comment">//: calculating sizes of different variables.</span> -<span class="Comment">//: - it allocates an extra location where it tracks so-called 'reference</span> -<span class="Comment">//: counts' or refcounts: the number of address variables in your program that</span> -<span class="Comment">//: point to this allocation. The initial refcount of an allocation starts out</span> -<span class="Comment">//: at 1 (the product of the 'new' instruction). When other variables are</span> -<span class="Comment">//: copied from it the refcount is incremented. When a variable stops pointing</span> -<span class="Comment">//: at it the refcount is decremented. When the refcount goes to 0 the</span> -<span class="Comment">//: allocation is automatically abandoned.</span> -<span class="Comment">//:</span> -<span class="Comment">//: Mu programs guarantee you'll have no memory corruption bugs as long as you</span> -<span class="Comment">//: use 'new' and never use 'allocate' or 'abandon'. However, they don't help</span> -<span class="Comment">//: you at all to remember to abandon memory after you're done with it. To</span> -<span class="Comment">//: minimize memory use, be sure to reset allocated addresses to 0 when you're</span> -<span class="Comment">//: done with them.</span> - -<span class="Comment">//: To help you distinguish addresses that point at allocations, 'new' returns</span> -<span class="Comment">//: type address:shared:___. Think of 'shared' as a generic container that</span> -<span class="Comment">//: contains one extra field: the refcount. However, lookup operations will</span> -<span class="Comment">//: transparently drop the 'shared' and access to the refcount. Copying</span> -<span class="Comment">//: between shared and non-shared addresses is forbidden.</span> -<span class="Delimiter">:(before "End Mu Types Initialization")</span> -type_ordinal shared = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span> -get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> shared<span class="Delimiter">).</span>name = <span class="Constant">"shared"</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before "End Drop Address In lookup_memory(x)")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"shared"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"skipping refcount at "</span> << x<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> - x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// skip refcount</span> - drop_from_type<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> -<span class="Delimiter">}</span> -<span class="Delimiter">:(before "End Drop Address In canonize_type(r)")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"shared"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - drop_from_type<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenarios run)</span> -<span class="Delimiter">:(scenario new)</span> -<span class="Comment"># call new two times with identical arguments; you should get back different results</span> -def main [ - <span class="Constant">1</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type - <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:address:shared:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:shared:number/<span class="Special">raw</span> -] -<span class="traceContains">+mem: storing 0 in location 3</span> - -<span class="Delimiter">:(before "End Globals")</span> -<span class="Normal">const</span> <span class="Normal">int</span> Reserved_for_tests = <span class="Constant">1000</span><span class="Delimiter">;</span> -<span class="Normal">int</span> Memory_allocated_until = Reserved_for_tests<span class="Delimiter">;</span> -<span class="Normal">int</span> Initial_memory_per_routine = <span class="Constant">100000</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before "End Setup")</span> -Memory_allocated_until = Reserved_for_tests<span class="Delimiter">;</span> -Initial_memory_per_routine = <span class="Constant">100000</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before "End routine Fields")</span> -<span class="Normal">int</span> alloc<span class="Delimiter">,</span> alloc_max<span class="Delimiter">;</span> -<span class="Delimiter">:(before "End routine Constructor")</span> -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><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"routine allocated memory from "</span> << alloc << <span class="Constant">" to "</span> << alloc_max << 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 "End Mu Types Initialization")</span> -put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"type"</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 "End Primitive Recipe Declarations")</span> -NEW<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"new"</span><span class="Delimiter">,</span> NEW<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> NEW: <span class="Delimiter">{</span> - <span class="Normal">const</span> recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> - <span class="Normal">if</span> <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> > <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'new' requires one or two ingredients, but got "</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="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> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_type_literal<span class="Delimiter">(</span>type<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'new' should be a type, but got "</span> << type<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"result of 'new' should never be ignored</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!product_of_new_is_valid<span class="Delimiter">(</span>inst<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"product of 'new' has incorrect type: "</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> -<span class="Normal">bool</span> product_of_new_is_valid<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<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> - canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// array allocation</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!product<span class="Delimiter">.</span>type || product<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - drop_from_type<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - reagent expected_product<span class="Delimiter">(</span><span class="Constant">"x:"</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(expected_product) When Checking 'new'</span> - <span class="Identifier">return</span> types_strictly_match<span class="Delimiter">(</span>product<span class="Delimiter">,</span> expected_product<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 "Transform.push_back(check_instruction)")</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> -<span class="Normal">void</span> transform_new_to_allocate<span class="Delimiter">(</span><span class="Normal">const</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">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- convert 'new' to 'allocate' for recipe "</span> << get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name << end<span class="Delimiter">();</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>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& 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> - <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"new"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - inst<span class="Delimiter">.</span>operation = ALLOCATE<span class="Delimiter">;</span> - string_tree* type_name = <span class="Normal">new</span> 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">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"size of "</span> << to_string<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> << <span class="Constant">" is "</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>value << end<span class="Delimiter">();</span> - <span class="Normal">delete</span> type<span class="Delimiter">;</span> - <span class="Normal">delete</span> 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 "End Primitive Recipe Declarations")</span> -ALLOCATE<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"allocate"</span><span class="Delimiter">,</span> ALLOCATE<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> ALLOCATE: <span class="Delimiter">{</span> - <span class="Comment">// compute the space we need</span> - <span class="Normal">int</span> 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> - <span class="Normal">if</span> <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> - <span class="Comment">// array</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"array size is "</span> << ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> - size = <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span> + size*ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Comment">// include space for refcount</span> - size++<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"allocating size "</span> << size << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? Total_alloc += size;</span> -<span class="CommentedCode">//? Num_alloc++;</span> - <span class="Comment">// compute the region of memory to return</span> - <span class="Comment">// really crappy at the moment</span> - ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span> - <span class="Normal">const</span> <span class="Normal">int</span> result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new alloc: "</span> << result << end<span class="Delimiter">();</span> - <span class="Comment">// save result</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> - <span class="Comment">// initialize allocated space</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> address = result<span class="Delimiter">;</span> address < result+size<span class="Delimiter">;</span> ++address<span class="Delimiter">)</span> - 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> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> << <span class="Constant">" in location "</span> << result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> - <span class="Delimiter">}</span> - <span class="Comment">// bump</span> - Current_routine<span class="Delimiter">-></span>alloc += size<span class="Delimiter">;</span> - <span class="Comment">// no support for reclaiming memory</span> - assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc <= Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="SalientComment">//:: ensure we never call 'allocate' directly; its types are not checked</span> -<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> ALLOCATE: <span class="Delimiter">{</span> - raise << <span class="Constant">"never call 'allocate' directly'; always use 'new'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="SalientComment">//:: ensure we never call 'new' without translating it (unless we add special-cases later)</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> NEW: <span class="Delimiter">{</span> - raise << <span class="Constant">"no implementation for 'new'; why wasn't it translated to 'allocate'? Please save a copy of your program and send it to Kartik.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="CommentedCode">//? :(before "End Globals")</span> -<span class="CommentedCode">//? int Total_alloc = 0;</span> -<span class="CommentedCode">//? int Num_alloc = 0;</span> -<span class="CommentedCode">//? int Total_free = 0;</span> -<span class="CommentedCode">//? int Num_free = 0;</span> -<span class="CommentedCode">//? :(before "End Setup")</span> -<span class="CommentedCode">//? Total_alloc = Num_alloc = Total_free = Num_free = 0;</span> -<span class="CommentedCode">//? :(before "End Teardown")</span> -<span class="CommentedCode">//? cerr << Total_alloc << "/" << Num_alloc</span> -<span class="CommentedCode">//? << " vs " << Total_free << "/" << Num_free << '\n';</span> -<span class="CommentedCode">//? cerr << SIZE(Memory) << '\n';</span> - -<span class="Delimiter">:(code)</span> -<span class="Normal">void</span> ensure_space<span class="Delimiter">(</span><span class="Normal">int</span> size<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>size > Initial_memory_per_routine<span class="Delimiter">)</span> <span class="Delimiter">{</span> - tb_shutdown<span class="Delimiter">();</span> - cerr << <span class="Constant">"can't allocate "</span> << size << <span class="Constant">" locations, that's too much compared to "</span> << Initial_memory_per_routine << <span class="Constant">".</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> - exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc + size > Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// waste the remaining space and create a new chunk</span> - Current_routine<span class="Delimiter">-></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">-></span>alloc_max = Memory_allocated_until<span class="Delimiter">;</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"routine allocated memory from "</span> << Current_routine<span class="Delimiter">-></span>alloc << <span class="Constant">" to "</span> << Current_routine<span class="Delimiter">-></span>alloc_max << 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">% put(Memory, Memory_allocated_until, 1);</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:shared:number -] -<span class="traceContains">+mem: storing 0 in location 2</span> - -<span class="Delimiter">:(scenario new_error)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - <span class="Constant">1</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type -] -<span class="traceContains">+error: main: product of 'new' has incorrect type: 1:address:number/raw <- new number:type</span> - -<span class="Delimiter">:(scenario new_array)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">5</span> - <span class="Constant">2</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type - <span class="Constant">3</span>:number/<span class="Special">raw <- </span>subtract <span class="Constant">2</span>:address:shared:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:number/<span class="Special">raw</span> -] -<span class="traceContains">+run: {1: ("address" "shared" "array" "number"), "raw": ()} <- new {number: "type"}, {5: "literal"}</span> -<span class="traceContains">+mem: array size is 5</span> -<span class="Comment"># don't forget the extra location for array size, and the second extra location for the refcount</span> -<span class="traceContains">+mem: storing 7 in location 3</span> - -<span class="Delimiter">:(scenario new_empty_array)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">0</span> - <span class="Constant">2</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type - <span class="Constant">3</span>:number/<span class="Special">raw <- </span>subtract <span class="Constant">2</span>:address:shared:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:number/<span class="Special">raw</span> -] -<span class="traceContains">+run: {1: ("address" "shared" "array" "number"), "raw": ()} <- new {number: "type"}, {0: "literal"}</span> -<span class="traceContains">+mem: array size is 0</span> -<span class="Comment"># one location for array size, and one for the refcount</span> -<span class="traceContains">+mem: storing 2 in location 3</span> - -<span class="Comment">//: If a routine runs out of its initial allocation, it should allocate more.</span> -<span class="Delimiter">:(scenario new_overflow)</span> -<span class="Special">% Initial_memory_per_routine = 3; // barely enough room for point allocation below</span> -def main [ - <span class="Constant">1</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:address:shared:point/<span class="Special">raw <- </span><span class="Normal">new</span> point:type <span class="Comment"># not enough room in initial page</span> -] -<span class="traceContains">+new: routine allocated memory from 1000 to 1003</span> -<span class="traceContains">+new: routine allocated memory from 1003 to 1006</span> - -<span class="SalientComment">//:: A way to return memory, and to reuse reclaimed memory.</span> -<span class="Comment">//: todo: custodians, etc. Following malloc/free is a temporary hack.</span> - -<span class="Delimiter">:(scenario new_reclaim)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:number <span class="Comment"># because 1 will get reset during abandon below</span> - abandon <span class="Constant">1</span>:address:shared:number <span class="Comment"># unsafe</span> - <span class="Constant">3</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type <span class="Comment"># must be same size as abandoned memory to reuse</span> - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:shared:number<span class="Delimiter">,</span> <span class="Constant">3</span>:address:shared:number -] -<span class="Comment"># both allocations should have returned the same address</span> -<span class="traceContains">+mem: storing 1 in location 4</span> - -<span class="Delimiter">:(before "End routine Fields")</span> -map<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>> free_list<span class="Delimiter">;</span> - -<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -ABANDON<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">,</span> ABANDON<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> ABANDON: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'abandon' requires one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - 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> - <span class="Normal">if</span> <span class="Delimiter">(</span>!types<span class="Delimiter">.</span>type || types<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> || types<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'abandon' should be an address:shared:___, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> ABANDON: <span class="Delimiter">{</span> - <span class="Normal">int</span> 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> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"address to abandon is "</span> << address << end<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> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"value of ingredient is "</span> << types<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> - canonize<span class="Delimiter">(</span>types<span class="Delimiter">);</span> - <span class="Comment">// lookup_memory without drop_one_lookup {</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"value of ingredient after canonization is "</span> << types<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> - <span class="Normal">int</span> address_location = types<span class="Delimiter">.</span>value<span class="Delimiter">;</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>+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> - drop_from_type<span class="Delimiter">(</span>types<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - drop_from_type<span class="Delimiter">(</span>types<span class="Delimiter">,</span> <span class="Constant">"shared"</span><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="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> - <span class="Comment">// clear the address</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"resetting location "</span> << address_location << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address_location<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">:(code)</span> -<span class="Normal">void</span> abandon<span class="Delimiter">(</span><span class="Normal">int</span> address<span class="Delimiter">,</span> <span class="Normal">int</span> size<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"saving in free-list of size "</span> << size << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? Total_free += size;</span> -<span class="CommentedCode">//? Num_free++;</span> -<span class="CommentedCode">//? cerr << "abandon: " << size << '\n';</span> - <span class="Comment">// clear memory</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address<span class="Delimiter">;</span> curr < address+size<span class="Delimiter">;</span> ++curr<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> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">));</span> - put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">,</span> address<span class="Delimiter">);</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(before "ensure_space(size)" following "case ALLOCATE")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">))</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"picking up space from free-list of size "</span> << size << end<span class="Delimiter">();</span> - <span class="Normal">int</span> result = get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new alloc from free list: "</span> << result << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">));</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = result+<span class="Constant">1</span><span class="Delimiter">;</span> curr < result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"memory in free list was not zeroed out: "</span> << curr << <span class="Constant">'/'</span> << result << <span class="Constant">"; somebody wrote to us after free!!!</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// always fatal</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> - <span class="Normal">else</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario new_differing_size_no_reclaim)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:number - abandon <span class="Constant">1</span>:address:shared:number - <span class="Constant">3</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> <span class="Comment"># different size</span> - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:shared:number<span class="Delimiter">,</span> <span class="Constant">3</span>:address:shared:array:number -] -<span class="Comment"># no reuse</span> -<span class="traceContains">+mem: storing 0 in location 4</span> - -<span class="Delimiter">:(scenario new_reclaim_array)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> - <span class="Constant">2</span>:address:shared:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:array:number - abandon <span class="Constant">1</span>:address:shared:array:number <span class="Comment"># unsafe</span> - <span class="Constant">3</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:shared:array:number<span class="Delimiter">,</span> <span class="Constant">3</span>:address:shared:array:number -] -<span class="Comment"># reuse</span> -<span class="traceContains">+mem: storing 1 in location 4</span> - -<span class="Delimiter">:(scenario reset_on_abandon)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - abandon <span class="Constant">1</span>:address:shared:number -] -<span class="Comment"># reuse</span> -<span class="traceContains">+run: abandon {1: ("address" "shared" "number")}</span> -<span class="traceContains">+mem: resetting location 1</span> - -<span class="SalientComment">//:: Manage refcounts when copying addresses.</span> - -<span class="Delimiter">:(scenario refcounts)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:number - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">0</span> -] -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- copy {1000: "literal", "unsafe": ()}</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {2: ("address" "shared" "number")} <- copy {1: ("address" "shared" "number")}</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- copy {0: "literal"}</span> -<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> -<span class="traceContains">+run: {2: ("address" "shared" "number")} <- copy {0: "literal"}</span> -<span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> -<span class="Comment"># the /unsafe corrupts memory but fortunately we won't be running any more 'new' in this scenario</span> -<span class="traceContains">+mem: automatically abandoning 1000</span> - -<span class="Delimiter">:(before "End write_memory(reagent x) Special-cases")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right - && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Comment">// compute old address of x, as well as new address we want to write in</span> - <span class="Normal">int</span> old_address = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> - assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span> - <span class="Normal">int</span> new_address = data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Comment">// decrement refcount of old address</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>old_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> old_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"decrementing refcount of "</span> << old_address << <span class="Constant">": "</span> << old_refcount << <span class="Constant">" -> "</span> << <span class="Delimiter">(</span>old_refcount-<span class="Constant">1</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">,</span> old_refcount-<span class="Constant">1</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Comment">// perform the write</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << no_scientific<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="Constant">" in location "</span> << x<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> - <span class="Comment">// increment refcount of new address</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> new_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> - assert<span class="Delimiter">(</span>new_refcount >= <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// == 0 only when new_address == old_address</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"incrementing refcount of "</span> << new_address << <span class="Constant">": "</span> << new_refcount << <span class="Constant">" -> "</span> << <span class="Delimiter">(</span>new_refcount+<span class="Constant">1</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">,</span> new_refcount+<span class="Constant">1</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Comment">// abandon old address if necessary</span> - <span class="Comment">// do this after all refcount updates are done just in case old and new are identical</span> - assert<span class="Delimiter">(</span>old_address >= <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>old_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">)</span> >= <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">)</span> > <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Comment">// lookup_memory without drop_one_lookup {</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"automatically abandoning "</span> << old_address << end<span class="Delimiter">();</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"computing size to abandon at "</span> << x<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> - x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>old_address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> - drop_from_type<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - drop_from_type<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - <span class="Comment">// }</span> - abandon<span class="Delimiter">(</span>old_address<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario refcounts_2)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Comment"># over-writing one allocation with another</span> - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">0</span> -] -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- new {number: "type"}</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- new {number: "type"}</span> -<span class="traceContains">+mem: automatically abandoning 1000</span> - -<span class="Delimiter">:(scenario refcounts_3)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Comment"># passing in addresses to recipes increments refcount</span> - foo <span class="Constant">1</span>:address:shared:number - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">0</span> -] -def foo [ - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>next-ingredient - <span class="Comment"># return does NOT yet decrement refcount; memory must be explicitly managed</span> - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">0</span> -] -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- new {number: "type"}</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {2: ("address" "shared" "number")} <- next-ingredient</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> -<span class="traceContains">+run: {2: ("address" "shared" "number")} <- copy {0: "literal"}</span> -<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- copy {0: "literal"}</span> -<span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> -<span class="traceContains">+mem: automatically abandoning 1000</span> - -<span class="Delimiter">:(scenario refcounts_4)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Comment"># idempotent copies leave refcount unchanged</span> - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:number -] -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- new {number: "type"}</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- copy {1: ("address" "shared" "number")}</span> -<span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> - -<span class="Delimiter">:(scenario refcounts_5)</span> -def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Comment"># passing in addresses to recipes increments refcount</span> - foo <span class="Constant">1</span>:address:shared:number - <span class="Comment"># return does NOT yet decrement refcount; memory must be explicitly managed</span> - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type -] -def foo [ - <span class="Constant">2</span>:address:shared:number<span class="Special"> <- </span>next-ingredient -] -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- new {number: "type"}</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {2: ("address" "shared" "number")} <- next-ingredient</span> -<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> -<span class="traceContains">+run: {1: ("address" "shared" "number")} <- new {number: "type"}</span> -<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> - -<span class="Delimiter">:(scenario refcounts_array)</span> -def main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">30</span> - <span class="Comment"># allocate an array</span> - <span class="Constant">10</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">20</span> - <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span>:address:shared:array:number - <span class="Comment"># allocate another array in its place, implicitly freeing the previous allocation</span> - <span class="Constant">10</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">25</span> -] -<span class="traceContains">+run: {10: ("address" "shared" "array" "number")} <- new {number: "type"}, {20: "literal"}</span> -<span class="Comment"># abandoned array is of old size (20, not 25)</span> -<span class="traceContains">+abandon: saving in free-list of size 22</span> - -<span class="SalientComment">//:: Extend 'new' to handle a unicode string literal argument.</span> - -<span class="Delimiter">:(scenario new_string)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc def] - <span class="Constant">2</span>:character<span class="Special"> <- </span>index *<span class="Constant">1</span>:address:shared:array:character<span class="Delimiter">,</span> <span class="Constant">5</span> -] -<span class="Comment"># number code for 'e'</span> -<span class="traceContains">+mem: storing 101 in location 2</span> - -<span class="Delimiter">:(scenario new_string_handles_unicode)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [a«c] - <span class="Constant">2</span>:number<span class="Special"> <- </span>length *<span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:character<span class="Special"> <- </span>index *<span class="Constant">1</span>:address:shared:array:character<span class="Delimiter">,</span> <span class="Constant">1</span> -] -<span class="traceContains">+mem: storing 3 in location 2</span> -<span class="Comment"># unicode for '«'</span> -<span class="traceContains">+mem: storing 171 in location 3</span> - -<span class="Delimiter">:(before "End NEW Check Special-cases")</span> -<span class="Normal">if</span> <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 "Convert 'new' To 'allocate'")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"new"</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">continue</span><span class="Delimiter">;</span> -<span class="Delimiter">:(after "case NEW" following "Primitive Recipe Implementations")</span> - <span class="Normal">if</span> <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> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new string alloc: "</span> << products<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> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - -<span class="Delimiter">:(code)</span> -<span class="Normal">int</span> new_mu_string<span class="Delimiter">(</span><span class="Normal">const</span> string& contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// allocate an array just large enough for it</span> - <span class="Normal">int</span> string_length = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> -<span class="CommentedCode">//? Total_alloc += string_length+1;</span> -<span class="CommentedCode">//? Num_alloc++;</span> - 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> - <span class="Normal">int</span> result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> - <span class="Comment">// initialize refcount</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc++<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Comment">// store length</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc++<span class="Delimiter">,</span> string_length<span class="Delimiter">);</span> - <span class="Normal">int</span> curr = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Normal">const</span> <span class="Normal">char</span>* raw_contents = contents<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < string_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">uint32_t</span> curr_character<span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>curr < SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> - tb_utf8_char_to_unicode<span class="Delimiter">(</span>&curr_character<span class="Delimiter">,</span> &raw_contents[curr]<span class="Delimiter">);</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></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">-></span>alloc<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Comment">// mu strings are not null-terminated in memory</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: stash recognizes strings</span> - -<span class="Delimiter">:(scenario stash_string)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:character -] -<span class="traceContains">+app: foo: abc</span> - -<span class="Delimiter">:(before "End print Special-cases(reagent r, data)")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span> - <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="Constant">' '</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario unicode_string)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [♠] - stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:character -] -<span class="traceContains">+app: foo: ♠</span> - -<span class="Delimiter">:(scenario stash_space_after_string)</span> -def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - stash <span class="Constant">1</span>:address:shared:array:character<span class="Delimiter">,</span> [foo] -] -<span class="traceContains">+app: abc 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> -def main [ - <span class="Constant">1</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw <- </span><span class="Normal">new</span> [a] <span class="Comment"># not enough room in initial page, if you take the array size into account</span> -] -<span class="traceContains">+new: routine allocated memory from 1000 to 1002</span> -<span class="traceContains">+new: routine allocated memory from 1002 to 1004</span> - -<span class="Comment">//: helpers</span> -<span class="Delimiter">:(code)</span> -<span class="Normal">int</span> unicode_length<span class="Delimiter">(</span><span class="Normal">const</span> string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> <span class="Normal">char</span>* in = s<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> - <span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Normal">int</span> curr = <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Normal">while</span> <span class="Delimiter">(</span>curr < SIZE<span class="Delimiter">(</span>s<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// carefully bounds-check on the string</span> - <span class="Comment">// before accessing its raw pointer</span> - ++result<span class="Delimiter">;</span> - curr += tb_utf8_char_length<span class="Delimiter">(</span>in[curr]<span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -string read_mu_string<span class="Delimiter">(</span><span class="Normal">int</span> address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> - address++<span class="Delimiter">;</span> <span class="Comment">// skip refcount</span> - <span class="Normal">int</span> size = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>size == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> - ostringstream tmp<span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address+<span class="Constant">1</span><span class="Delimiter">;</span> curr <= address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - tmp << to_unicode<span class="Delimiter">(</span><span class="Normal">static_cast</span><<span class="Normal">uint32_t</span>><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> - -<span class="Normal">bool</span> is_mu_type_literal<span class="Delimiter">(</span>reagent r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> is_literal<span class="Delimiter">(</span>r<span class="Delimiter">)</span> && r<span class="Delimiter">.</span>type && r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"type"</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/042name.cc.html b/html/042name.cc.html index 67b00f78..a7fb1088 100644 --- a/html/042name.cc.html +++ b/html/042name.cc.html @@ -149,9 +149,8 @@ Name = Name_snapshot<span class="Delimiter">;</span> type_ordinal skip_addresses<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> type_ordinal address = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - type_ordinal shared = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(;</span> type<span class="Delimiter">;</span> type = type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value != address && type<span class="Delimiter">-></span>value != shared<span class="Delimiter">)</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value != address<span class="Delimiter">)</span> <span class="Identifier">return</span> type<span class="Delimiter">-></span>value<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> @@ -186,6 +185,24 @@ type_ordinal skip_addresses<span class="Delimiter">(</span>type_tree* type<span <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario transform_names_supports_containers)</span> +def main [ + <span class="Normal">x</span>:point<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> + <span class="Normal">y</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> +] +<span class="traceContains">+name: assign x 1</span> +<span class="Comment"># skip location 2 because x occupies two locations</span> +<span class="traceContains">+name: assign y 3</span> + +<span class="Delimiter">:(scenario transform_names_supports_static_arrays)</span> +def main [ + <span class="Normal">x</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + <span class="Normal">y</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> +] +<span class="traceContains">+name: assign x 1</span> +<span class="Comment"># skip locations 2, 3, 4 because x occupies four locations</span> +<span class="traceContains">+name: assign y 5</span> + <span class="Delimiter">:(scenario transform_names_passes_dummy)</span> <span class="Comment"># _ is just a dummy result that never gets consumed</span> def main [ @@ -234,7 +251,8 @@ def main [ <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="SalientComment">//:: Support element names for containers in 'get' and 'get-location' and 'put'.</span> +<span class="Comment">//: (get-location is implemented later)</span> <span class="Delimiter">:(scenario transform_names_transforms_container_elements)</span> def main [ @@ -247,18 +265,19 @@ def main [ <span class="Delimiter">:(before "End transform_names(inst) Special-cases")</span> <span class="Comment">// replace element names of containers with offsets</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"get"</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">"get-address"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"exactly 2 ingredients expected in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"get"</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">"get-location"</span> || inst<span class="Delimiter">.</span>name == <span class="Constant">"put"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">//: avoid raising any errors here; later layers will support overloading new</span> + <span class="Comment">//: instructions with the same names (static dispatch), which could lead to</span> + <span class="Comment">//: spurious errors</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> < <span class="Constant">2</span><span class="Delimiter">)</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> <span class="Normal">if</span> <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 << 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">"expected ingredient 1 of "</span> << <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"get"</span> ? <span class="Constant">"'get'"</span> : <span class="Constant">"'get-address'"</span><span class="Delimiter">)</span> << <span class="Constant">" to have type 'offset'; got "</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>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> <span class="Normal">if</span> <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">"0123456789"</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>type<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>base_type == -<span class="Constant">1</span><span class="Delimiter">)</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"expected a container in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// otherwise we'll raise an error elsewhere</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">"name"</span><span class="Delimiter">)</span> << <span class="Constant">"element "</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="Constant">" of type "</span> << get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name << <span class="Constant">" is at offset "</span> << 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> << end<span class="Delimiter">();</span> @@ -284,10 +303,12 @@ def main [ <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> - <span class="Constant">20</span>:address:point<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> p:variant + <span class="Constant">20</span>:point<span class="Delimiter">,</span> <span class="Constant">22</span>:boolean<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:number-<span class="Normal">or</span>-point/unsafe<span class="Delimiter">,</span> p:variant ] <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="traceContains">+mem: storing 35 in location 20</span> +<span class="traceContains">+mem: storing 36 in location 21</span> +<span class="traceContains">+mem: storing 1 in location 22</span> <span class="Delimiter">:(before "End transform_names(inst) Special-cases")</span> <span class="Comment">// convert variant names of exclusive containers</span> diff --git a/html/043space.cc.html b/html/043space.cc.html index c4783e1e..05049dc3 100644 --- a/html/043space.cc.html +++ b/html/043space.cc.html @@ -44,24 +44,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># if default-space is 10, and if an array of 5 locals lies from location 12 to 16 (inclusive),</span> <span class="Comment"># then local 0 is really location 12, local 1 is really location 13, and so on.</span> def main [ - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">10</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+mem: storing 23 in location 13</span> <span class="Delimiter">:(scenario lookup_sidesteps_default_space)</span> def main [ - <span class="Comment"># pretend pointer from outside</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend pointer from outside (2000 reserved for refcount)</span> + <span class="Constant">2001</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">1000</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">1001</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> <span class="Comment"># actual start of this recipe</span> - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">3</span>/unsafe + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">2000</span>/unsafe <span class="Comment"># even local variables always contain raw addresses</span> <span class="Constant">8</span>:number/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:number ] <span class="traceContains">+mem: storing 34 in location 8</span> @@ -88,7 +88,7 @@ def main [ default_space = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End canonize(x) Special-cases")</span> - absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> absolutize<span class="Delimiter">(</span>reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> @@ -126,13 +126,11 @@ default_space = <span class="Constant">0</span><span class="Delimiter">;</span> || !x<span class="Delimiter">.</span>type || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> || !x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">)</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> || !x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> - || !x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">)</span> - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'default-space' should be of type address:shared:array:location, but tried to write "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">)</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'default-space' should be of type address:array:location, but tried to write "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << 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> @@ -140,8 +138,8 @@ default_space = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">:(scenario get_default_space)</span> def main [ - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe - <span class="Constant">1</span>:address:shared:array:location/<span class="Special">raw <- </span>copy <span class="Normal">default</span>-space:address:shared:array:location + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">1</span>:address:array:location/<span class="Special">raw <- </span>copy <span class="Normal">default</span>-space:address:array:location ] <span class="traceContains">+mem: storing 10 in location 1</span> @@ -156,42 +154,42 @@ def main [ <span class="Delimiter">:(scenario lookup_sidesteps_default_space_in_get)</span> def main [ - <span class="Comment"># pretend pointer to container from outside</span> - <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend pointer to container from outside (2000 reserved for refcount)</span> + <span class="Constant">2001</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2002</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">1000</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">1001</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> <span class="Comment"># actual start of this recipe</span> - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe - <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">12</span>/unsafe + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">2000</span>/unsafe <span class="Constant">9</span>:number/<span class="Special">raw <- </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 "reagent tmp" following "case GET:")</span> -tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> +<span class="Delimiter">:(before "Read element" following "case GET:")</span> +element<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> <span class="SalientComment">//:: fix 'index'</span> <span class="Delimiter">:(scenario lookup_sidesteps_default_space_in_index)</span> def main [ - <span class="Comment"># pretend pointer to array from outside</span> - <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">2</span> - <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend pointer to array from outside (2000 reserved for refcount)</span> + <span class="Constant">2001</span>:number<span class="Special"> <- </span>copy <span class="Constant">2</span> <span class="Comment"># length</span> + <span class="Constant">2002</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2003</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">1000</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">1001</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> <span class="Comment"># actual start of this recipe</span> - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe - <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">12</span>/unsafe + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">2000</span>/unsafe <span class="Constant">9</span>:number/<span class="Special">raw <- </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 "reagent tmp" following "case INDEX:")</span> -tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> +<span class="Delimiter">:(before "Read element" following "case INDEX:")</span> +element<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> <span class="SalientComment">//:: convenience operation to automatically deduce the amount of space to</span> <span class="SalientComment">//:: allocate in a default space with names</span> @@ -213,7 +211,7 @@ def main [ <span class="Delimiter">:(before "End Rewrite Instruction(curr, recipe result)")</span> <span class="Comment">// rewrite `new-default-space` to</span> -<span class="Comment">// `default-space:address:shared:array:location <- new location:type, number-of-locals:literal`</span> +<span class="Comment">// `default-space:address:array:location <- new location:type, number-of-locals:literal`</span> <span class="Comment">// where N is Name[recipe][""]</span> <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"new-default-space"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> rewrite_default_space_instruction<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> @@ -244,7 +242,7 @@ def main [ def foo [ local-scope <span class="Normal">x</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Identifier">return</span> <span class="Normal">default</span>-space:address:shared:array:location + <span class="Identifier">return</span> <span class="Normal">default</span>-space:address:array:location ] <span class="Comment"># both calls to foo should have received the same default-space</span> <span class="traceContains">+mem: storing 1 in location 3</span> @@ -253,9 +251,9 @@ def foo [ <span class="CommentedCode">//? :(scenario local_scope_frees_up_allocations)</span> <span class="CommentedCode">//? def main [</span> <span class="CommentedCode">//? local-scope</span> -<span class="CommentedCode">//? x:address:shared:array:character <- new [abc]</span> +<span class="CommentedCode">//? x:address:array:character <- new [abc]</span> <span class="CommentedCode">//? ]</span> -<span class="CommentedCode">//? +mem: clearing x:address:shared:array:character</span> +<span class="CommentedCode">//? +mem: clearing x:address:array:character</span> <span class="Comment">//: todo: do this in a transform, rather than magically in the reply instruction</span> <span class="Delimiter">:(after "Falling Through End Of Recipe")</span> @@ -279,7 +277,7 @@ try_reclaim_locals<span class="Delimiter">();</span> <span class="Normal">const</span> instruction& inst = exiting_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name != <span class="Constant">"local-scope"</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// reclaim any local variables unless they're being returned</span> - <span class="Comment">// </span><span class="Todo">TODO</span><span class="Comment">: this isn't working yet. Doesn't handle address:shared stored in</span> + <span class="Comment">// </span><span class="Todo">TODO</span><span class="Comment">: this isn't working yet. Doesn't handle address stored in</span> <span class="Comment">// containers created by 'copy' or 'merge'. We'd end up deleting the address</span> <span class="Comment">// even if some container containing it was returned.</span> <span class="Comment">// This might doom our whole refcounting-based approach :/</span> @@ -320,7 +318,7 @@ try_reclaim_locals<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">"number-of-locals:literal"</span><span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise << <span class="Constant">"new-default-space can't take any results</span><span class="cSpecial">\n</span><span class="Constant">"</span> << 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">"default-space:address:shared:array:location"</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">"default-space:address:array:location"</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: all recipes must set default-space one way or another</span> diff --git a/html/044space_surround.cc.html b/html/044space_surround.cc.html index 7badc275..d4028860 100644 --- a/html/044space_surround.cc.html +++ b/html/044space_surround.cc.html @@ -41,15 +41,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">:(scenario surrounding_space)</span> <span class="Comment"># location 1 in space 1 refers to the space surrounding the default space, here 20.</span> def main [ - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">10</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">20</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">21</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> <span class="Comment"># actual start of this recipe</span> - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe - <span class="Constant">0</span>:address:shared:array:location/names:dummy<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe <span class="Comment"># later layers will explain the /names: property</span> + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + <span class="Constant">0</span>:address:array:location/names:dummy<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe <span class="Comment"># later layers will explain the /names: property</span> <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">32</span> <span class="Constant">1</span>:number/space:<span class="Constant">1</span><span class="Special"> <- </span>copy <span class="Constant">33</span> ] diff --git a/html/045closure_name.cc.html b/html/045closure_name.cc.html index d7f38829..4338d824 100644 --- a/html/045closure_name.cc.html +++ b/html/045closure_name.cc.html @@ -40,22 +40,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">:(scenario closure)</span> def main [ - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">30</span> - <span class="Constant">1</span>:address:shared:array:location/names:<span class="Normal">new</span>-counter<span class="Special"> <- </span><span class="Normal">new</span>-counter - <span class="Constant">2</span>:number/<span class="Special">raw <- </span>increment-counter <span class="Constant">1</span>:address:shared:array:location/names:<span class="Normal">new</span>-counter - <span class="Constant">3</span>:number/<span class="Special">raw <- </span>increment-counter <span class="Constant">1</span>:address:shared:array:location/names:<span class="Normal">new</span>-counter + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">30</span> + <span class="Constant">1</span>:address:array:location/names:<span class="Normal">new</span>-counter<span class="Special"> <- </span><span class="Normal">new</span>-counter + <span class="Constant">2</span>:number/<span class="Special">raw <- </span>increment-counter <span class="Constant">1</span>:address:array:location/names:<span class="Normal">new</span>-counter + <span class="Constant">3</span>:number/<span class="Special">raw <- </span>increment-counter <span class="Constant">1</span>:address:array:location/names:<span class="Normal">new</span>-counter ] def <span class="Normal">new</span>-counter [ - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">30</span> + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">30</span> <span class="Normal">x</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> <span class="Normal">y</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> <span class="Comment"># variable that will be incremented</span> - <span class="Identifier">return</span> <span class="Normal">default</span>-space:address:shared:array:location + <span class="Identifier">return</span> <span class="Normal">default</span>-space:address:array:location ] def increment-counter [ - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">30</span> - <span class="Constant">0</span>:address:shared:array:location/names:<span class="Normal">new</span>-counter<span class="Special"> <- </span>next-ingredient <span class="Comment"># outer space must be created by 'new-counter' above</span> + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">30</span> + <span class="Constant">0</span>:address:array:location/names:<span class="Normal">new</span>-counter<span class="Special"> <- </span>next-ingredient <span class="Comment"># outer space must be created by 'new-counter' above</span> <span class="Normal">y</span>:number/space:<span class="Constant">1</span><span class="Special"> <- </span>add y:number/space:<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">1</span> <span class="Comment"># increment</span> <span class="Normal">y</span>:number<span class="Special"> <- </span>copy <span class="Constant">234</span> <span class="Comment"># dummy</span> <span class="Identifier">return</span> y:number/space:<span class="Constant">1</span> @@ -87,13 +87,11 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Normal">if</span> <span class="Delimiter">(</span>!type || type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> || !type<span class="Delimiter">-></span>right - || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">)</span> + || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> || !type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> - || !type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">)</span> - || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"slot 0 should always have type address:shared:array:location, but is "</span> << to_string<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="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">)</span> + || type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"slot 0 should always have type address:array:location, but is "</span> << to_string<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="cSpecial">'\n'</span> << 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">"names"</span><span class="Delimiter">);</span> diff --git a/html/046global.cc.html b/html/046global.cc.html index 6fce3f17..6744937e 100644 --- a/html/046global.cc.html +++ b/html/046global.cc.html @@ -45,15 +45,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">:(scenario global_space)</span> def main [ - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">10</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> - <span class="Comment"># pretend shared:array:location; in practice we'll use new</span> + <span class="Comment"># pretend address:array:location; in practice we'll use new</span> <span class="Constant">20</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># refcount</span> <span class="Constant">21</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Comment"># length</span> <span class="Comment"># actual start of this recipe</span> - global-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe - <span class="Normal">default</span>-space:address:shared:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe + global-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe + <span class="Normal">default</span>-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>/unsafe <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> <span class="Constant">1</span>:number/space:global<span class="Special"> <- </span>copy <span class="Constant">24</span> ] @@ -80,13 +80,11 @@ global_space = <span class="Constant">0</span><span class="Delimiter">;</span> || !x<span class="Delimiter">.</span>type || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> || !x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">)</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> || !x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">)</span> - || !x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">)</span> - || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'global-space' should be of type address:shared:array:location, but tried to write "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">)</span> + || x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'global-space' should be of type address:array:location, but tried to write "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>global_space<span class="Delimiter">)</span> raise << <span class="Constant">"routine already has a global-space; you can't over-write your globals"</span> << end<span class="Delimiter">();</span> @@ -107,7 +105,7 @@ global_space = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">:(scenario global_space_with_names)</span> def main [ - global-space:address:shared:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">10</span> + global-space:address:array:location<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">10</span> <span class="Normal">x</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> <span class="Constant">1</span>:number/space:global<span class="Special"> <- </span>copy <span class="Constant">24</span> ] diff --git a/html/047check_type_by_name.cc.html b/html/047check_type_by_name.cc.html index a3300f78..35f546f9 100644 --- a/html/047check_type_by_name.cc.html +++ b/html/047check_type_by_name.cc.html @@ -94,7 +94,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << caller<span class="Delimiter">.</span>name << <span class="Constant">" can't determine the size of array variable "</span> << x<span class="Delimiter">.</span>name << <span class="Constant">". Either allocate it separately and make the type of "</span> << x<span class="Delimiter">.</span>name << <span class="Constant">" address:shared:..., or specify the length of the array in the type of "</span> << x<span class="Delimiter">.</span>name << <span class="Constant">".</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << caller<span class="Delimiter">.</span>name << <span class="Constant">" can't determine the size of array variable "</span> << x<span class="Delimiter">.</span>name << <span class="Constant">". Either allocate it separately and make the type of "</span> << x<span class="Delimiter">.</span>name << <span class="Constant">" address:..., or specify the length of the array in the type of "</span> << x<span class="Delimiter">.</span>name << <span class="Constant">".</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -130,17 +130,17 @@ def main [ <span class="Delimiter">:(scenario typo_in_address_type_fails)</span> <span class="Special">% Hide_errors = true;</span> def main [ - <span class="Normal">y</span>:address:shared:charcter<span class="Special"> <- </span><span class="Normal">new</span> character:type + <span class="Normal">y</span>:address:charcter<span class="Special"> <- </span><span class="Normal">new</span> character:type *y<span class="Special"> <- </span>copy <span class="Constant">67</span> ] -<span class="traceContains">+error: main: unknown type charcter in 'y:address:shared:charcter <- new character:type'</span> +<span class="traceContains">+error: main: unknown type charcter in 'y:address:charcter <- new character:type'</span> <span class="Delimiter">:(scenario array_type_without_size_fails)</span> <span class="Special">% Hide_errors = true;</span> def main [ <span class="Normal">x</span>:array:number<span class="Special"> <- </span>merge <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">12</span><span class="Delimiter">,</span> <span class="Constant">13</span> ] -<span class="traceContains">+error: main can't determine the size of array variable x. Either allocate it separately and make the type of x address:shared:..., or specify the length of the array in the type of x.</span> +<span class="traceContains">+error: main can't determine the size of array variable x. Either allocate it separately and make the type of x address:..., or specify the length of the array in the type of x.</span> <span class="Delimiter">:(scenarios transform)</span> <span class="Delimiter">:(scenario transform_checks_types_of_identical_reagents_in_multiple_spaces)</span> @@ -148,7 +148,7 @@ def foo [ <span class="Comment"># dummy</span> ] def main [ local-scope - <span class="Constant">0</span>:address:shared:array:location/names:foo<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># specify surrounding space</span> + <span class="Constant">0</span>:address:array:location/names:foo<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># specify surrounding space</span> <span class="Normal">x</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">1</span>/<span class="Constant">true</span> <span class="Normal">x</span>:number/space:<span class="Constant">1</span><span class="Special"> <- </span>copy <span class="Constant">34</span> x/space:<span class="Constant">1</span><span class="Special"> <- </span>copy <span class="Constant">35</span> diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html index aa172588..30ce17fc 100644 --- a/html/050scenario.cc.html +++ b/html/050scenario.cc.html @@ -136,9 +136,9 @@ scenario foo [ <span class="Delimiter">:(scenario read_scenario_with_bracket_in_comment_in_nested_string)</span> scenario foo [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [<span class="Comment"># not a comment]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [<span class="Comment"># not a comment]</span> ] -<span class="traceContains">+run: {1: ("address" "shared" "array" "character")} <- new {"# not a comment": "literal-string"}</span> +<span class="traceContains">+run: {1: ("address" "array" "character")} <- new {"# not a comment": "literal-string"}</span> <span class="SalientComment">//:: Run scenarios when we run 'mu test'.</span> <span class="Comment">//: Treat the text of the scenario as a regular series of instructions.</span> @@ -191,6 +191,7 @@ cerr << <span class="Constant">"</span><span class="cSpecial">\n</spa Passed = <span class="Constant">false</span><span class="Delimiter">;</span> ++Num_failures<span class="Delimiter">;</span> <span class="Delimiter">}</span> + <span class="Comment">// End Mu Test Teardown</span> <span class="Normal">if</span> <span class="Delimiter">(</span>not_already_inside_test && Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> teardown<span class="Delimiter">();</span> ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> diff --git a/html/054parse_tree.cc.html b/html/054parse_tree.cc.html index e4e4760e..380f7a1d 100644 --- a/html/054parse_tree.cc.html +++ b/html/054parse_tree.cc.html @@ -104,11 +104,11 @@ container bar [ <span class="Delimiter">:(scenario dilated_reagent_in_static_array)</span> def main [ - <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>array <span class="Delimiter">(</span>address shared number<span class="Delimiter">)</span> <span class="Constant">3</span><span class="Delimiter">)}</span><span class="Special"> <- </span>create-array - <span class="Constant">5</span>:address:address:shared:number<span class="Special"> <- </span>index-address <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>array <span class="Delimiter">(</span>address shared number<span class="Delimiter">)</span> <span class="Constant">3</span><span class="Delimiter">)},</span> <span class="Constant">0</span> - *<span class="Constant">5</span>:address:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - **<span class="Constant">5</span>:address:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">6</span>:number<span class="Special"> <- </span>copy **<span class="Constant">5</span>:address:address:shared:number + <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>array <span class="Delimiter">(</span>address number<span class="Delimiter">)</span> <span class="Constant">3</span><span class="Delimiter">)}</span><span class="Special"> <- </span>create-array + <span class="Constant">5</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>array <span class="Delimiter">(</span>address number<span class="Delimiter">)</span> <span class="Constant">3</span><span class="Delimiter">)}</span><span class="Special"> <- </span>put-index <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>array <span class="Delimiter">(</span>address number<span class="Delimiter">)</span> <span class="Constant">3</span><span class="Delimiter">)},</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">5</span>:address:number + *<span class="Constant">5</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">6</span>:number<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:number ] <span class="traceContains">+run: creating array of size 4</span> <span class="traceContains">+mem: storing 34 in location 6</span> @@ -117,7 +117,7 @@ def main [ <span class="Delimiter">:(scenario dilated_reagent_with_new)</span> def main [ - <span class="Normal">x</span>:address:shared:address:number<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>address number<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> + <span class="Normal">x</span>:address:address:number<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>address number<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> ] <span class="traceContains">+new: size of ("address" "number") is 1</span> diff --git a/html/055recipe_header.cc.html b/html/055recipe_header.cc.html index 52ee83d5..93acb6c8 100644 --- a/html/055recipe_header.cc.html +++ b/html/055recipe_header.cc.html @@ -257,54 +257,16 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Comment">// ingredients coerced from call to callee</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"ingredient "</span> << i << <span class="Constant">" has the wrong type at '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_unique_address<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 << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"avoid passing non-shared addresses into calls, like ingredient "</span> << i << <span class="Constant">" at '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">long</span> <span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>products<span class="Delimiter">));</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// products coerced from callee to call</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> callee<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"product "</span> << i << <span class="Constant">" has the wrong type at '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_unique_address<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"avoid getting non-shared addresses out of calls, like product "</span> << i << <span class="Constant">" at '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="Normal">bool</span> is_unique_address<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Identifier">return</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>value != get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: additionally, flag an error on calls receiving non-shared addresses</span> - -<span class="Delimiter">:(scenario forbid_calls_with_nonshared_addresses)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - foo <span class="Constant">1</span>:address:number -] -def foo x:address:number [ - local-scope - load-ingredients -] -<span class="traceContains">+error: main: avoid passing non-shared addresses into calls, like ingredient 0 at 'foo 1:address:number'</span> - -<span class="Delimiter">:(scenario forbid_calls_with_nonshared_addresses_2)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - <span class="Constant">1</span>:address:number<span class="Special"> <- </span>foo -] -def foo <span class="Delimiter">-></span> x:address:number [ - local-scope - load-ingredients - x<span class="Special"> <- </span>copy <span class="Constant">0</span> -] -<span class="traceContains">+error: main: avoid getting non-shared addresses out of calls, like product 0 at '1:address:number <- foo '</span> - <span class="SalientComment">//:: Check types going in and out of all recipes with headers.</span> <span class="Delimiter">:(scenarios transform)</span> diff --git a/html/056static_dispatch.cc.html b/html/056static_dispatch.cc.html index 116970e1..0193d57f 100644 --- a/html/056static_dispatch.cc.html +++ b/html/056static_dispatch.cc.html @@ -439,13 +439,13 @@ $error: <span class="Constant">0</span> <span class="Delimiter">:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_first_use)</span> def main [ - <span class="Normal">x</span>:address:shared:foo<span class="Special"> <- </span><span class="Normal">new</span> foo:type + <span class="Normal">x</span>:address:foo<span class="Special"> <- </span><span class="Normal">new</span> foo:type test x ] container foo [ <span class="Normal">x</span>:number ] -def test a:address:shared:foo <span class="Delimiter">-></span> z:number [ +def test a:address:foo <span class="Delimiter">-></span> z:number [ local-scope load-ingredients <span class="Normal">z</span>:number<span class="Special"> <- </span>get *a<span class="Delimiter">,</span> x:offset @@ -454,10 +454,10 @@ $error: <span class="Constant">0</span> <span class="Delimiter">:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_second_use)</span> def main [ - <span class="Normal">x</span>:address:shared:foo<span class="Special"> <- </span><span class="Normal">new</span> foo:type + <span class="Normal">x</span>:address:foo<span class="Special"> <- </span><span class="Normal">new</span> foo:type test x ] -def test a:address:shared:foo <span class="Delimiter">-></span> z:number [ +def test a:address:foo <span class="Delimiter">-></span> z:number [ local-scope load-ingredients <span class="Normal">z</span>:number<span class="Special"> <- </span>get *a<span class="Delimiter">,</span> x:offset diff --git a/html/057shape_shifting_container.cc.html b/html/057shape_shifting_container.cc.html index 821572e9..7c8b2826 100644 --- a/html/057shape_shifting_container.cc.html +++ b/html/057shape_shifting_container.cc.html @@ -67,9 +67,9 @@ container foo:_a:_b [ <span class="Normal">y</span>:_b ] def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] <span class="Comment"># compound types for type ingredients</span> - <span class="Delimiter">{</span><span class="Constant">2</span>: <span class="Delimiter">(</span>foo number <span class="Delimiter">(</span>address shared array character<span class="Delimiter">))}</span><span class="Special"> <- </span>merge <span class="Constant">34</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:character/y + <span class="Delimiter">{</span><span class="Constant">2</span>: <span class="Delimiter">(</span>foo number <span class="Delimiter">(</span>address array character<span class="Delimiter">))}</span><span class="Special"> <- </span>merge <span class="Constant">34</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character/y ] $error: <span class="Constant">0</span> @@ -80,18 +80,18 @@ container foo:_a:_b [ ] container bar:_a:_b [ <span class="Comment"># dilated element</span> - <span class="Delimiter">{</span>data: <span class="Delimiter">(</span>foo _a <span class="Delimiter">(</span>address shared _b<span class="Delimiter">))}</span> + <span class="Delimiter">{</span>data: <span class="Delimiter">(</span>foo _a <span class="Delimiter">(</span>address _b<span class="Delimiter">))}</span> ] def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - <span class="Constant">2</span>:bar:number:array:character<span class="Special"> <- </span>merge <span class="Constant">34</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:character/y + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + <span class="Constant">2</span>:bar:number:array:character<span class="Special"> <- </span>merge <span class="Constant">34</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character/y ] $error: <span class="Constant">0</span> <span class="Delimiter">:(before "End Globals")</span> <span class="Comment">// We'll use large type ordinals to mean "the following type of the variable".</span> <span class="Normal">const</span> <span class="Normal">int</span> START_TYPE_INGREDIENTS = <span class="Constant">2000</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before "End Test Run Initialization")</span> +<span class="Delimiter">:(before "End Commandline Parsing")</span> <span class="Comment">// after loading .mu files</span> assert<span class="Delimiter">(</span>Next_type_ordinal < START_TYPE_INGREDIENTS<span class="Delimiter">);</span> <span class="Delimiter">:(before "End type_info Fields")</span> @@ -161,32 +161,6 @@ def main [ <span class="traceContains">+mem: storing 23 in location 7</span> $mem: <span class="Constant">7</span> -<span class="Delimiter">:(code)</span> -<span class="Comment">// shape-shifting version of size_of</span> -<span class="Normal">int</span> size_of_type_ingredient<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* element_template<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* rest_of_use<span class="Delimiter">)</span> <span class="Delimiter">{</span> - type_tree* element_type = type_ingredient<span class="Delimiter">(</span>element_template<span class="Delimiter">,</span> rest_of_use<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!element_type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> - <span class="Normal">int</span> result = size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> - <span class="Normal">delete</span> element_type<span class="Delimiter">;</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -type_tree* type_ingredient<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* element_template<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* rest_of_use<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> type_ingredient_index = element_template<span class="Delimiter">-></span>value - START_TYPE_INGREDIENTS<span class="Delimiter">;</span> - <span class="Normal">const</span> type_tree* curr = rest_of_use<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!curr<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span> - <span class="Normal">while</span> <span class="Delimiter">(</span>type_ingredient_index > <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">-></span>right<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!curr<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - assert<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">)</span> curr = curr<span class="Delimiter">-></span>left<span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>value > <span class="Constant">0</span><span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"type"</span><span class="Delimiter">)</span> << <span class="Constant">"type deduced to be "</span> << get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> curr<span class="Delimiter">-></span>value<span class="Delimiter">).</span>name << <span class="Constant">"$"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*curr<span class="Delimiter">);</span> -<span class="Delimiter">}</span> - <span class="Delimiter">:(scenario get_on_shape_shifting_container)</span> container foo:_t [ <span class="Normal">x</span>:_t @@ -198,16 +172,6 @@ def main [ ] <span class="traceContains">+mem: storing 16 in location 2</span> -<span class="Delimiter">:(before "End GET field Cases")</span> -<span class="Normal">const</span> 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>type<span class="Delimiter">;</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value >= START_TYPE_INGREDIENTS<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> size = size_of_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!size<span class="Delimiter">)</span> - raise << <span class="Constant">"illegal field type '"</span> << to_string<span class="Delimiter">(</span>type<span class="Delimiter">)</span> << <span class="Constant">"' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">"</span> << 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 [ <span class="Normal">x</span>:_t @@ -227,9 +191,9 @@ container foo:_t [ ] def main [ <span class="Constant">1</span>:foo:address:point<span class="Special"> <- </span>merge <span class="Constant">34</span>/unsafe<span class="Delimiter">,</span> <span class="Constant">48</span> - <span class="Constant">2</span>:address:point<span class="Special"> <- </span>get <span class="Constant">1</span>:foo:address:point<span class="Delimiter">,</span> x:offset + <span class="Constant">3</span>:address:point<span class="Special"> <- </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="traceContains">+mem: storing 34 in location 3</span> <span class="Delimiter">:(scenario get_on_shape_shifting_container_inside_container)</span> container foo:_t [ @@ -252,18 +216,18 @@ container foo:_a:_b [ <span class="Normal">y</span>:_b ] def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - <span class="Delimiter">{</span><span class="Constant">2</span>: <span class="Delimiter">(</span>foo number <span class="Delimiter">(</span>address shared array character<span class="Delimiter">))}</span><span class="Special"> <- </span>merge <span class="Constant">34</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:array:character/y - <span class="Constant">3</span>:address:shared:array:character<span class="Special"> <- </span>get <span class="Delimiter">{</span><span class="Constant">2</span>: <span class="Delimiter">(</span>foo number <span class="Delimiter">(</span>address shared array character<span class="Delimiter">))},</span> y:offset - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + <span class="Delimiter">{</span><span class="Constant">2</span>: <span class="Delimiter">(</span>foo number <span class="Delimiter">(</span>address array character<span class="Delimiter">))}</span><span class="Special"> <- </span>merge <span class="Constant">34</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character/y + <span class="Constant">3</span>:address:array:character<span class="Special"> <- </span>get <span class="Delimiter">{</span><span class="Constant">2</span>: <span class="Delimiter">(</span>foo number <span class="Delimiter">(</span>address array character<span class="Delimiter">))},</span> y:offset + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:character ] <span class="traceContains">+mem: storing 1 in location 4</span> <span class="Delimiter">:(before "End element_type Special-cases")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> - raise << <span class="Constant">"illegal type "</span> << names_to_string<span class="Delimiter">(</span>canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> info<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> + raise << <span class="Constant">"illegal type "</span> << names_to_string<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> info<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> @@ -398,15 +362,14 @@ def main [ <span class="Constant">"container bar:_elem [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" x:foo:_elem</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> - reagent callsite<span class="Delimiter">(</span><span class="Constant">"x:bar:address:shared:array:character"</span><span class="Delimiter">);</span> + reagent callsite<span class="Delimiter">(</span><span class="Constant">"x:bar:address:array:character"</span><span class="Delimiter">);</span> reagent element = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"x"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> - CHECK<span class="Delimiter">(</span>!element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_replace_type_ingredients_head_middle<span class="Delimiter">()</span> <span class="Delimiter">{</span> @@ -433,7 +396,7 @@ def main [ <span class="Constant">" x:_a</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" y:_b</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> - reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo number (address shared array character))}"</span><span class="Delimiter">);</span> + reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo number (address array character))}"</span><span class="Delimiter">);</span> reagent element1 = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element1<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"x"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element1<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> @@ -441,10 +404,9 @@ def main [ reagent element2 = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"y"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> - CHECK<span class="Delimiter">(</span>!element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_replace_middle_type_ingredient_with_multiple<span class="Delimiter">()</span> <span class="Delimiter">{</span> @@ -453,7 +415,7 @@ def main [ <span class="Constant">" y:_b</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" z:_c</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> - reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo number (address shared array character) boolean)}"</span><span class="Delimiter">);</span> + reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo number (address array character) boolean)}"</span><span class="Delimiter">);</span> reagent element1 = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element1<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"x"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element1<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> @@ -461,10 +423,9 @@ def main [ reagent element2 = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"y"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> - CHECK<span class="Delimiter">(</span>!element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!element2<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> reagent element3 = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element3<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"z"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element3<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"boolean"</span><span class="Delimiter">);</span> @@ -476,39 +437,36 @@ def main [ <span class="Constant">" key:_key</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" value:_value</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> - reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo (address shared array character) number)}"</span><span class="Delimiter">);</span> + reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo (address array character) number)}"</span><span class="Delimiter">);</span> reagent element = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"key"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> - CHECK<span class="Delimiter">(</span>!element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_replace_middle_type_ingredient_with_multiple3<span class="Delimiter">()</span> <span class="Delimiter">{</span> run<span class="Delimiter">(</span><span class="Constant">"container foo_table:_key:_value [</span><span class="cSpecial">\n</span><span class="Constant">"</span> - <span class="Constant">" data:address:shared:array:foo_table_row:_key:_value</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" data:address:array:foo_table_row:_key:_value</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"container foo_table_row:_key:_value [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" key:_key</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" value:_value</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> - reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo_table (address shared array character) number)}"</span><span class="Delimiter">);</span> + reagent callsite<span class="Delimiter">(</span><span class="Constant">"{f: (foo_table (address array character) number)}"</span><span class="Delimiter">);</span> reagent element = element_type<span class="Delimiter">(</span>callsite<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"data"</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"foo_table_row"</span><span class="Delimiter">);</span> - CHECK<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> - CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> - CHECK<span class="Delimiter">(</span>!element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"foo_table_row"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"array"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>left<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">-></span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> has_nth_type<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* base<span class="Delimiter">,</span> <span class="Normal">int</span> n<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -530,29 +488,6 @@ def main [ ] <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 [ - <span class="Normal">x</span>:_t - <span class="Normal">y</span>:number -] -def main [ - <span class="Constant">10</span>:foo:point<span class="Special"> <- </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"> <- </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 "End GET_ADDRESS field Cases")</span> -<span class="Normal">const</span> 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>type<span class="Delimiter">;</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value >= START_TYPE_INGREDIENTS<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> size = size_of_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!size<span class="Delimiter">)</span> - raise << <span class="Constant">"illegal type '"</span> << to_string<span class="Delimiter">(</span>type<span class="Delimiter">)</span> << <span class="Constant">"' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">"</span> << 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="Comment">//: 'merge' on shape-shifting containers</span> <span class="Delimiter">:(scenario merge_check_shape_shifting_container_containing_exclusive_container)</span> @@ -635,9 +570,9 @@ def main [ <span class="Delimiter">:(before "End variant_type Special-cases")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> - raise << <span class="Constant">"illegal type '"</span> << to_string<span class="Delimiter">(</span>canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">"' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> canonized_base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> info<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> + raise << <span class="Constant">"illegal type '"</span> << to_string<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">"' seems to be missing a type ingredient or three</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> info<span class="Delimiter">);</span> <span class="Delimiter">}</span> </pre> </body> diff --git a/html/058shape_shifting_recipe.cc.html b/html/058shape_shifting_recipe.cc.html index 4b20f023..4af6577f 100644 --- a/html/058shape_shifting_recipe.cc.html +++ b/html/058shape_shifting_recipe.cc.html @@ -24,6 +24,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .Comment { color: #9090ff; } .Todo { color: #000000; background-color: #ffff00; padding-bottom: 1px; } .CommentedCode { color: #6c6c6c; } +.PreProc { color: #800080; } --> </style> @@ -438,6 +439,10 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla <span class="Normal">const</span> type_tree* replacement = get<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> type<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">"transform"</span><span class="Delimiter">)</span> << type<span class="Delimiter">-></span>name << <span class="Constant">" => "</span> << names_to_string<span class="Delimiter">(</span>replacement<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> replacement<span class="Delimiter">-></span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// error in program; should be reported elsewhere</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Comment">// type is a single type ingredient</span> assert<span class="Delimiter">(</span>!type<span class="Delimiter">-></span>left<span class="Delimiter">);</span> @@ -594,8 +599,8 @@ container c:_a:_b [ <span class="Normal">b</span>:_b ] def main [ - <span class="Normal">s</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - <span class="Delimiter">{</span>x: <span class="Delimiter">(</span>c <span class="Delimiter">(</span>address shared array character<span class="Delimiter">)</span> number<span class="Delimiter">)}</span><span class="Special"> <- </span>merge s<span class="Delimiter">,</span> <span class="Constant">34</span> + <span class="Normal">s</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + <span class="Delimiter">{</span>x: <span class="Delimiter">(</span>c <span class="Delimiter">(</span>address array character<span class="Delimiter">)</span> number<span class="Delimiter">)}</span><span class="Special"> <- </span>merge s<span class="Delimiter">,</span> <span class="Constant">34</span> foo x ] def foo x:c:_bar:_baz [ @@ -632,14 +637,14 @@ def foo a:_t [ <span class="Delimiter">:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient)</span> def main [ - <span class="Constant">1</span>:address:shared:foo:point<span class="Special"> <- </span>bar <span class="Constant">3</span> - <span class="Constant">11</span>:foo:point<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:shared:foo:point + <span class="Constant">1</span>:address:foo:point<span class="Special"> <- </span>bar <span class="Constant">3</span> + <span class="Constant">11</span>:foo:point<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:foo:point ] container foo:_t [ <span class="Normal">x</span>:_t <span class="Normal">y</span>:number ] -def bar x:number <span class="Delimiter">-></span> result:address:shared:foo:_t [ +def bar x:number <span class="Delimiter">-></span> result:address:foo:_t [ local-scope load-ingredients <span class="Comment"># new refers to _t in its ingredient *value*</span> @@ -651,10 +656,10 @@ def bar x:number <span class="Delimiter">-></span> result:address:shared:foo: <span class="Delimiter">:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient_2)</span> def main [ - <span class="Constant">1</span>:address:shared:foo:point<span class="Special"> <- </span>bar <span class="Constant">3</span> - <span class="Constant">11</span>:foo:point<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:shared:foo:point + <span class="Constant">1</span>:address:foo:point<span class="Special"> <- </span>bar <span class="Constant">3</span> + <span class="Constant">11</span>:foo:point<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:foo:point ] -def bar x:number <span class="Delimiter">-></span> result:address:shared:foo:_t [ +def bar x:number <span class="Delimiter">-></span> result:address:foo:_t [ local-scope load-ingredients <span class="Comment"># new refers to _t in its ingredient *value*</span> @@ -673,7 +678,7 @@ container foo:_t [ def main [ _<span class="Special"> <- </span>bar <span class="Constant">34</span> ] -def bar x:_t <span class="Delimiter">-></span> result:address:shared:_t [ +def bar x:_t <span class="Delimiter">-></span> result:address:_t [ local-scope load-ingredients result<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -689,7 +694,7 @@ $error: <span class="Constant">0</span> transform<span class="Delimiter">(</span><span class="Constant">"def barz x:_elem [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" load-ingredients</span><span class="cSpecial">\n</span><span class="Constant">"</span> - <span class="Constant">" y:address:shared:number <- new _elem:type</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" y:address:number <- new _elem:type</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"def fooz [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> @@ -711,11 +716,10 @@ $error: <span class="Constant">0</span> <span class="Delimiter">:(scenario shape_shifting_recipe_supports_compound_types)</span> def main [ - <span class="Constant">1</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - <span class="Constant">2</span>:address:number<span class="Special"> <- </span>get-address *<span class="Constant">1</span>:address:shared:point<span class="Delimiter">,</span> y:offset - *<span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">3</span>:address:shared:point<span class="Special"> <- </span>bar <span class="Constant">1</span>:address:shared:point <span class="Comment"># specialize _t to address:shared:point</span> - <span class="Constant">4</span>:point<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:point + <span class="Constant">1</span>:address:point<span class="Special"> <- </span><span class="Normal">new</span> point:type + *<span class="Constant">1</span>:address:point<span class="Special"> <- </span>put *<span class="Constant">1</span>:address:point<span class="Delimiter">,</span> y:offset<span class="Delimiter">,</span> <span class="Constant">34</span> + <span class="Constant">3</span>:address:point<span class="Special"> <- </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"> <- </span>copy *<span class="Constant">3</span>:address:point ] def bar a:_t <span class="Delimiter">-></span> result:_t [ local-scope @@ -728,13 +732,13 @@ def bar a:_t <span class="Delimiter">-></span> result:_t [ <span class="Special">% Hide_errors = true;</span> def main [ <span class="Normal">a</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> - <span class="Normal">b</span>:address:shared:number<span class="Special"> <- </span>foo a + <span class="Normal">b</span>:address:number<span class="Special"> <- </span>foo a ] def foo a:_t <span class="Delimiter">-></span> b:_t [ load-ingredients b<span class="Special"> <- </span>copy a ] -<span class="traceContains">+error: main: no call found for 'b:address:shared:number <- foo a'</span> +<span class="traceContains">+error: main: no call found for 'b:address:number <- foo a'</span> <span class="Delimiter">:(scenario specialize_inside_recipe_without_header)</span> def main [ @@ -782,7 +786,7 @@ def foo x:_elem <span class="Delimiter">-></span> y:_elem [ def main [ local-scope <span class="Comment"># permit '0' to map to address to shape-shifting type-ingredient</span> - <span class="Constant">1</span>:address:shared:character/<span class="Special">raw <- </span>foo <span class="Constant">0</span> + <span class="Constant">1</span>:address:character/<span class="Special">raw <- </span>foo <span class="Constant">0</span> ] def foo x:address:_elem <span class="Delimiter">-></span> y:address:_elem [ local-scope @@ -852,7 +856,7 @@ container d2:_elem [ <span class="Comment"># static dispatch between shape-shifting variants, _including pointer lookups_</span> def main [ <span class="Normal">e1</span>:d1:number<span class="Special"> <- </span>merge <span class="Constant">3</span> - <span class="Normal">e2</span>:address:shared:d2:number<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>d2 number<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> + <span class="Normal">e2</span>:address:d2:number<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>d2 number<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo e1 <span class="Constant">2</span>:number/<span class="Special">raw <- </span>foo *e2 <span class="Comment"># different from previous scenario</span> ] @@ -935,15 +939,15 @@ def foo x:_elem <span class="Delimiter">-></span> y:number [ <span class="Delimiter">:(scenarios run)</span> <span class="Delimiter">:(scenario specialize_most_similar_variant)</span> def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Constant">2</span>:number<span class="Special"> <- </span>foo <span class="Constant">1</span>:address:shared:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:number<span class="Special"> <- </span>foo <span class="Constant">1</span>:address:number ] def foo x:_elem <span class="Delimiter">-></span> y:number [ local-scope load-ingredients <span class="Identifier">return</span> <span class="Constant">34</span> ] -def foo x:address:shared:_elem <span class="Delimiter">-></span> y:number [ +def foo x:address:_elem <span class="Delimiter">-></span> y:number [ local-scope load-ingredients <span class="Identifier">return</span> <span class="Constant">35</span> @@ -954,17 +958,17 @@ def foo x:address:shared:_elem <span class="Delimiter">-></span> y:number [ <span class="Comment"># version with headers padded with lots of unrelated concrete types</span> def main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> - <span class="Constant">2</span>:address:shared:array:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>foo <span class="Constant">2</span>:address:shared:array:number<span class="Delimiter">,</span> <span class="Constant">1</span>:number + <span class="Constant">2</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>foo <span class="Constant">2</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">1</span>:number ] <span class="Comment"># variant with concrete type</span> -def foo dummy:address:shared:array:number<span class="Delimiter">,</span> x:number <span class="Delimiter">-></span> y:number<span class="Delimiter">,</span> dummy:address:shared:array:number [ +def foo dummy:address:array:number<span class="Delimiter">,</span> x:number <span class="Delimiter">-></span> y:number<span class="Delimiter">,</span> dummy:address:array:number [ local-scope load-ingredients <span class="Identifier">return</span> <span class="Constant">34</span> ] <span class="Comment"># shape-shifting variant</span> -def foo dummy:address:shared:array:number<span class="Delimiter">,</span> x:_elem <span class="Delimiter">-></span> y:number<span class="Delimiter">,</span> dummy:address:shared:array:number [ +def foo dummy:address:array:number<span class="Delimiter">,</span> x:_elem <span class="Delimiter">-></span> y:number<span class="Delimiter">,</span> dummy:address:array:number [ local-scope load-ingredients <span class="Identifier">return</span> <span class="Constant">35</span> @@ -974,10 +978,10 @@ def foo dummy:address:shared:array:number<span class="Delimiter">,</span> x:_ele <span class="Delimiter">:(scenario specialize_most_similar_variant_3)</span> def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - foo <span class="Constant">1</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + foo <span class="Constant">1</span>:address:array:character ] -def foo x:address:shared:array:character [ +def foo x:address:array:character [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> ] def foo x:address:_elem [ @@ -1014,13 +1018,53 @@ def foo x:number <span class="Delimiter">-></span> y:number [ <span class="Identifier">return</span> <span class="Constant">34</span> ] <span class="Comment"># shape-shifting variant</span> -def foo x:address:shared:_elem <span class="Delimiter">-></span> y:number [ +def foo x:address:_elem <span class="Delimiter">-></span> y:number [ local-scope load-ingredients <span class="Identifier">return</span> <span class="Constant">35</span> ] <span class="Comment"># prefer the concrete variant, ignore concrete types in scoring the shape-shifting variant</span> <span class="traceContains">+mem: storing 34 in location 1</span> + +<span class="Delimiter">:(scenario missing_type_during_specialization)</span> +<span class="Special">% Hide_errors = true;</span> +<span class="Comment"># define a shape-shifting recipe</span> +def foo a:_elem [ +] +<span class="Comment"># define a container with field 'z'</span> +container foo2 [ + <span class="Normal">z</span>:number +] +def main [ + local-scope + <span class="Normal">x</span>:foo2<span class="Special"> <- </span>merge <span class="Constant">34</span> + <span class="Normal">y</span>:number<span class="Special"> <- </span>get x<span class="Delimiter">,</span> z:offse <span class="Comment"># typo in 'offset'</span> +<span class="PreProc"> </span><span class="Comment"># define a variable with the same name 'z'</span> + <span class="Normal">z</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Comment"># trigger specialization of the shape-shifting recipe</span> + foo z +] +<span class="Comment"># shouldn't crash</span> + +<span class="Delimiter">:(scenario missing_type_during_specialization2)</span> +<span class="Special">% Hide_errors = true;</span> +<span class="Comment"># define a shape-shifting recipe</span> +def foo a:_elem [ +] +<span class="Comment"># define a container with field 'z'</span> +container foo2 [ + <span class="Normal">z</span>:number +] +def main [ + local-scope + <span class="Normal">x</span>:foo2<span class="Special"> <- </span>merge <span class="Constant">34</span> + <span class="Normal">y</span>:number<span class="Special"> <- </span>get x<span class="Delimiter">,</span> z:offse <span class="Comment"># typo in 'offset'</span> +<span class="PreProc"> </span><span class="Comment"># define a variable with the same name 'z'</span> + <span class="Normal">z</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Comment"># trigger specialization of the shape-shifting recipe</span> + foo *z +] +<span class="Comment"># shouldn't crash</span> </pre> </body> </html> diff --git a/html/060immutable.cc.html b/html/060immutable.cc.html deleted file mode 100644 index 508306b3..00000000 --- a/html/060immutable.cc.html +++ /dev/null @@ -1,520 +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 - 060immutable.cc</title> -<meta name="Generator" content="Vim/7.4"> -<meta name="plugin-version" content="vim7.4_v2"> -<meta name="syntax" content="cpp"> -<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> -<meta name="colorscheme" content="minimal"> -<style type="text/css"> -<!-- -pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } -body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } -* { font-size: 12pt; font-size: 1em; } -.Constant { color: #00a0a0; } -.cSpecial { color: #008000; } -.traceContains { color: #008000; } -.Comment { color: #9090ff; } -.Delimiter { color: #800080; } -.Special { color: #c00000; } -.Identifier { color: #fcb165; } -.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } -.Todo { color: #000000; background-color: #ffff00; padding-bottom: 1px; } ---> -</style> - -<script type='text/javascript'> -<!-- - ---> -</script> -</head> -<body> -<pre id='vimCodeElement'> -<span class="Comment">//: Addresses passed into of a recipe are meant to be immutable unless they're</span> -<span class="Comment">//: also products. This layer will start enforcing this check.</span> -<span class="Comment">//:</span> -<span class="Comment">//: One hole for now: variables in surrounding spaces are implicitly mutable.</span> - -<span class="Delimiter">:(scenario can_modify_value_ingredients)</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - foo *p -] -def foo p:point [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>get-address p<span class="Delimiter">,</span> x:offset - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario can_modify_ingredients_that_are_also_products)</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - p<span class="Special"> <- </span>foo p -] -def foo p:address:shared:point <span class="Delimiter">-></span> p:address:shared:point [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario ignore_literal_ingredients_for_immutability_checks)</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:d1<span class="Special"> <- </span><span class="Normal">new</span> d1:type - <span class="Normal">q</span>:number<span class="Special"> <- </span>foo p -] -def foo p:address:shared:d1 <span class="Delimiter">-></span> q:number [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:shared:d1<span class="Special"> <- </span><span class="Normal">new</span> d1:type - <span class="Normal">y</span>:address:number<span class="Special"> <- </span>get-address *x<span class="Delimiter">,</span> p:offset <span class="Comment"># ignore this 'p'</span> - q<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -container d1 [ - <span class="Normal">p</span>:number - <span class="Normal">q</span>:number -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario cannot_modify_immutable_ingredients)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - local-scope - <span class="Normal">x</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - foo x -] -def foo x:address:shared:number [ - local-scope - load-ingredients - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -<span class="traceContains">+error: foo: cannot modify x in instruction '*x <- copy 34' because it's not also a product of foo</span> - -<span class="Delimiter">:(scenario cannot_take_address_inside_immutable_ingredients)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - foo p -] -def foo p:address:shared:point [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -<span class="traceContains">+error: foo: cannot modify ingredient p after instruction 'x:address:number <- get-address *p, x:offset' because it's not also a product of foo</span> - -<span class="Delimiter">:(scenario cannot_call_mutating_recipes_on_immutable_ingredients)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - foo p -] -def foo p:address:shared:point [ - local-scope - load-ingredients - bar p -] -def bar p:address:shared:point <span class="Delimiter">-></span> p:address:shared:point [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -<span class="traceContains">+error: foo: cannot modify ingredient p at instruction 'bar p' because it's not also a product of foo</span> - -<span class="Delimiter">:(scenario cannot_modify_copies_of_immutable_ingredients)</span> -<span class="Special">% Hide_errors = true;</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - foo p -] -def foo p:address:shared:point [ - local-scope - load-ingredients - <span class="Normal">q</span>:address:shared:point<span class="Special"> <- </span>copy p - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>get-address *q<span class="Delimiter">,</span> x:offset -] -<span class="traceContains">+error: foo: cannot modify q after instruction 'x:address:number <- get-address *q, x:offset' because that would modify ingredient p which is not also a product of foo</span> - -<span class="Delimiter">:(scenario can_modify_copies_of_mutable_ingredients)</span> -def main [ - local-scope - <span class="Normal">p</span>:address:shared:point<span class="Special"> <- </span><span class="Normal">new</span> point:type - foo p -] -def foo p:address:shared:point <span class="Delimiter">-></span> p:address:shared:point [ - local-scope - load-ingredients - <span class="Normal">q</span>:address:shared:point<span class="Special"> <- </span>copy p - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>get-address *q<span class="Delimiter">,</span> x:offset -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario cannot_modify_address_inside_immutable_ingredients)</span> -<span class="Special">% Hide_errors = true;</span> -container foo [ - <span class="Normal">x</span>:address:shared:array:number <span class="Comment"># contains an address</span> -] -def main [ - <span class="Comment"># don't run anything</span> -] -def foo a:address:shared:foo [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:shared:array:number<span class="Special"> <- </span>get *a<span class="Delimiter">,</span> x:offset <span class="Comment"># just a regular get of the container</span> - <span class="Normal">y</span>:address:number<span class="Special"> <- </span>index-address *x<span class="Delimiter">,</span> <span class="Constant">0</span> <span class="Comment"># but then index-address on the result</span> - *y<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -<span class="traceContains">+error: foo: cannot modify x after instruction 'y:address:number <- index-address *x, 0' because that would modify ingredient a which is not also a product of foo</span> - -<span class="Delimiter">:(scenario cannot_modify_address_inside_immutable_ingredients_2)</span> -container foo [ - <span class="Normal">x</span>:address:shared:array:number <span class="Comment"># contains an address</span> -] -def main [ - <span class="Comment"># don't run anything</span> -] -def foo a:address:shared:foo [ - local-scope - load-ingredients - <span class="Normal">b</span>:foo<span class="Special"> <- </span>merge <span class="Constant">0</span> <span class="Comment"># completely unrelated to 'a'</span> - <span class="Normal">x</span>:address:shared:array:number<span class="Special"> <- </span>get b<span class="Delimiter">,</span> x:offset <span class="Comment"># just a regular get of the container</span> - <span class="Normal">y</span>:address:number<span class="Special"> <- </span>index-address *x<span class="Delimiter">,</span> <span class="Constant">0</span> <span class="Comment"># but then index-address on the result</span> - *y<span class="Special"> <- </span>copy <span class="Constant">34</span> -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario cannot_modify_address_inside_immutable_ingredients_3)</span> -<span class="Special">% Hide_errors = true;</span> -container foo [ - <span class="Normal">x</span>:number -] -def main [ - <span class="Comment"># don't run anything</span> -] -def foo a:address:shared:array:address:number [ - local-scope - load-ingredients - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>index *a<span class="Delimiter">,</span> <span class="Constant">0</span> <span class="Comment"># just a regular index of the array</span> - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> <span class="Comment"># but then modify the result</span> -] -<span class="Comment"># +error: foo: cannot modify x in instruction '*x <- copy 34' because that would modify ingredient a which is not also a product of foo</span> -<span class="traceContains">+error: foo: cannot modify x in instruction '*x <- copy 34' because it's not also a product of foo</span> - -<span class="Delimiter">:(scenario cannot_modify_address_inside_immutable_ingredients_4)</span> -container foo [ - <span class="Normal">x</span>:address:shared:array:number <span class="Comment"># contains an address</span> -] -def main [ - <span class="Comment"># don't run anything</span> -] -def foo a:address:shared:array:address:number [ - local-scope - load-ingredients - <span class="Normal">b</span>:address:shared:array:address:number<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>address number<span class="Delimiter">)</span>: type<span class="Delimiter">},</span> <span class="Constant">3</span> <span class="Comment"># completely unrelated to 'a'</span> - <span class="Normal">x</span>:address:number<span class="Special"> <- </span>index *b<span class="Delimiter">,</span> <span class="Constant">0</span> <span class="Comment"># just a regular index of the array</span> - *x<span class="Special"> <- </span>copy <span class="Constant">34</span> <span class="Comment"># but then modify the result</span> -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario can_traverse_immutable_ingredients)</span> -container test-list [ - <span class="Normal">next</span>:address:shared:test-list -] -def main [ - local-scope - <span class="Normal">p</span>:address:shared:test-list<span class="Special"> <- </span><span class="Normal">new</span> test-list:type - foo p -] -def foo p:address:shared:test-list [ - local-scope - load-ingredients - <span class="Normal">p2</span>:address:shared:test-list<span class="Special"> <- </span>bar p -] -def bar x:address:shared:test-list <span class="Delimiter">-></span> y:address:shared:test-list [ - local-scope - load-ingredients - y<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(scenario handle_optional_ingredients_in_immutability_checks)</span> -def main [ - <span class="Normal">k</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - test k -] -<span class="Comment"># recipe taking an immutable address ingredient</span> -def test k:address:shared:number [ - local-scope - load-ingredients - foo k -] -<span class="Comment"># ..calling a recipe with an optional address ingredient</span> -def foo <span class="Delimiter">-></span> [ - local-scope - load-ingredients - <span class="Normal">k</span>:address:shared:number<span class="Delimiter">,</span> found?:boolean<span class="Special"> <- </span>next-ingredient -] -$error: <span class="Constant">0</span> - -<span class="Comment">//: when checking for immutable ingredients, remember to take space into account</span> -<span class="Delimiter">:(scenario check_space_of_reagents_in_immutability_checks)</span> -def main [ - <span class="Normal">a</span>:address:shared:array:location<span class="Special"> <- </span><span class="Normal">new</span>-closure - <span class="Normal">b</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - run-closure b:address:shared:number<span class="Delimiter">,</span> a:address:shared:array:location -] -def <span class="Normal">new</span>-closure [ - <span class="Normal">new</span>-<span class="Normal">default</span>-space - <span class="Normal">x</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - <span class="Identifier">return</span> <span class="Normal">default</span>-space -] -def run-closure x:address:shared:number<span class="Delimiter">,</span> s:address:shared:array:location [ - local-scope - load-ingredients - <span class="Constant">0</span>:address:shared:array:location/names:<span class="Normal">new</span>-closure<span class="Special"> <- </span>copy s - *x:address:number/space:<span class="Constant">1</span><span class="Special"> <- </span>copy <span class="Constant">34</span> -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(before "End Transforms")</span> -Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_immutable_ingredients<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> - -<span class="Delimiter">:(code)</span> -<span class="Normal">void</span> check_immutable_ingredients<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// to ensure an address reagent isn't modified, it suffices to show that</span> - <span class="Comment">// a) we never write to its contents directly,</span> - <span class="Comment">// b) we never call get-address or index-address with it, and</span> - <span class="Comment">// c) any non-primitive recipe calls in the body aren't returning it as a product</span> - <span class="Normal">const</span> recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- check mutability of ingredients in recipe "</span> << caller<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!caller<span class="Delimiter">.</span>has_header<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// skip check for old-style recipes calling next-ingredient directly</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> reagent& current_ingredient = caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_address<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// will be copied</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_present_in_products<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// not expected to be immutable</span> - <span class="Comment">// End Immutable Ingredients Special-cases</span> - set<reagent> immutable_vars<span class="Delimiter">;</span> - immutable_vars<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">);</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> instruction& inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - check_immutable_ingredient_in_instruction<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> immutable_vars<span class="Delimiter">,</span> current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">,</span> caller<span class="Delimiter">);</span> - update_aliases<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> immutable_vars<span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> -<span class="Delimiter">}</span> - -<span class="Normal">void</span> update_aliases<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> set<reagent>& current_ingredient_and_aliases<span class="Delimiter">)</span> <span class="Delimiter">{</span> - set<<span class="Normal">int</span>> current_ingredient_indices = ingredient_indices<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> current_ingredient_and_aliases<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Comment">// primitive recipe</span> - <span class="Normal">switch</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">case</span> COPY: - <span class="Normal">for</span> <span class="Delimiter">(</span>set<<span class="Normal">int</span>>::iterator p = current_ingredient_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != current_ingredient_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> - current_ingredient_and_aliases<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>*p<span class="Delimiter">).</span>name<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Normal">case</span> GET: - <span class="Normal">case</span> INDEX: - <span class="Comment">// current_ingredient_indices can only have 0 or one value</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!current_ingredient_indices<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<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> - current_ingredient_and_aliases<span class="Delimiter">.</span>insert<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> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Normal">default</span>: <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> - <span class="Normal">else</span> <span class="Delimiter">{</span> - <span class="Comment">// defined recipe</span> - set<<span class="Normal">int</span>> contained_in_product_indices = scan_contained_in_product_indices<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> current_ingredient_indices<span class="Delimiter">);</span> - <span class="Normal">for</span> <span class="Delimiter">(</span>set<<span class="Normal">int</span>>::iterator p = contained_in_product_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != contained_in_product_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>*p < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">))</span> - current_ingredient_and_aliases<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>*p<span class="Delimiter">));</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> -<span class="Delimiter">}</span> - -set<<span class="Normal">int</span>> scan_contained_in_product_indices<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> set<<span class="Normal">int</span>>& ingredient_indices<span class="Delimiter">)</span> <span class="Delimiter">{</span> - set<reagent> selected_ingredients<span class="Delimiter">;</span> - <span class="Normal">const</span> recipe& callee = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">);</span> - <span class="Normal">for</span> <span class="Delimiter">(</span>set<<span class="Normal">int</span>>::iterator p = ingredient_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != ingredient_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>*p >= SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// optional immutable ingredient</span> - selected_ingredients<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>*p<span class="Delimiter">));</span> - <span class="Delimiter">}</span> - set<<span class="Normal">int</span>> result<span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> reagent& current_product = callee<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - <span class="Comment">// </span><span class="Todo">TODO</span> - <span class="Normal">const</span> string_tree* contained_in_name = property<span class="Delimiter">(</span>current_product<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>contained_in_name && selected_ingredients<span class="Delimiter">.</span>find<span class="Delimiter">(</span>contained_in_name<span class="Delimiter">-></span>value<span class="Delimiter">)</span> != selected_ingredients<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenarios transform)</span> -<span class="Delimiter">:(scenario immutability_infects_contained_in_variables)</span> -<span class="Special">% Hide_errors = true;</span> -container test-list [ - <span class="Normal">next</span>:address:shared:test-list -] -def main [ - local-scope - <span class="Normal">p</span>:address:shared:test-list<span class="Special"> <- </span><span class="Normal">new</span> test-list:type - foo p -] -def foo p:address:shared:test-list [ <span class="Comment"># p is immutable</span> - local-scope - load-ingredients - <span class="Normal">p2</span>:address:shared:test-list<span class="Special"> <- </span>test-next p <span class="Comment"># p2 is immutable</span> - <span class="Normal">p3</span>:address:address:shared:test-list<span class="Special"> <- </span>get-address *p2<span class="Delimiter">,</span> next:offset <span class="Comment"># signal modification of p2</span> -] -def test-next x:address:shared:test-list <span class="Delimiter">-></span> y:address:shared:test-list/contained-in:x [ - local-scope - load-ingredients - y<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset -] -<span class="traceContains">+error: foo: cannot modify p2 after instruction 'p3:address:address:shared:test-list <- get-address *p2, next:offset' because that would modify ingredient p which is not also a product of foo</span> - -<span class="Delimiter">:(code)</span> -<span class="Normal">void</span> check_immutable_ingredient_in_instruction<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> set<reagent>& current_ingredient_and_aliases<span class="Delimiter">,</span> <span class="Normal">const</span> string& original_ingredient_name<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// first check if the instruction is directly modifying something it shouldn't</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"lookup"</span><span class="Delimiter">)</span> - && current_ingredient_and_aliases<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> != current_ingredient_and_aliases<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify "</span> << inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name << <span class="Constant">" in instruction '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"' because it's not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> - <span class="Comment">// check if there's any indirect modification going on</span> - set<<span class="Normal">int</span>> current_ingredient_indices = ingredient_indices<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> current_ingredient_and_aliases<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>current_ingredient_indices<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// ingredient not found in call</span> - <span class="Normal">for</span> <span class="Delimiter">(</span>set<<span class="Normal">int</span>>::iterator p = current_ingredient_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != current_ingredient_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> <span class="Normal">int</span> current_ingredient_index = *p<span class="Delimiter">;</span> - reagent current_ingredient = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>current_ingredient_index<span class="Delimiter">);</span> - canonize_type<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">);</span> - <span class="Normal">const</span> string& current_ingredient_name = current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Comment">// primitive recipe</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == GET_ADDRESS || inst<span class="Delimiter">.</span>operation == INDEX_ADDRESS<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// only reason to use get-address or index-address is to modify, so stop right there</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>current_ingredient_name == original_ingredient_name<span class="Delimiter">)</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify ingredient "</span> << current_ingredient_name << <span class="Constant">" after instruction '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"' because it's not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Normal">else</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify "</span> << current_ingredient_name << <span class="Constant">" after instruction '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"' because that would modify ingredient "</span> << original_ingredient_name << <span class="Constant">" which is not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> - <span class="Normal">else</span> <span class="Delimiter">{</span> - <span class="Comment">// defined recipe</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_address<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// making a copy is ok</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_modified_in_recipe<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation<span class="Delimiter">,</span> current_ingredient_index<span class="Delimiter">,</span> caller<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>current_ingredient_name == original_ingredient_name<span class="Delimiter">)</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify ingredient "</span> << current_ingredient_name << <span class="Constant">" at instruction '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"' because it's not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Normal">else</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify "</span> << current_ingredient_name << <span class="Constant">" after instruction '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"' because that would modify ingredient "</span> << original_ingredient_name << <span class="Constant">" which is not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> -<span class="Delimiter">}</span> - -<span class="Normal">bool</span> is_modified_in_recipe<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">,</span> <span class="Normal">int</span> ingredient_index<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> recipe& callee = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!callee<span class="Delimiter">.</span>has_header<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"can't check mutability of ingredients in "</span> << callee<span class="Delimiter">.</span>name << <span class="Constant">" because it uses 'next-ingredient' directly, rather than a recipe header.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << 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="Normal">if</span> <span class="Delimiter">(</span>ingredient_index >= SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// optional immutable ingredient</span> - <span class="Identifier">return</span> is_present_in_products<span class="Delimiter">(</span>callee<span class="Delimiter">,</span> callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>name<span class="Delimiter">);</span> -<span class="Delimiter">}</span> - -<span class="Normal">bool</span> is_present_in_products<span class="Delimiter">(</span><span class="Normal">const</span> recipe& callee<span class="Delimiter">,</span> <span class="Normal">const</span> string& ingredient_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>callee<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name == ingredient_name<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> - -<span class="Normal">bool</span> is_present_in_ingredients<span class="Delimiter">(</span><span class="Normal">const</span> recipe& callee<span class="Delimiter">,</span> <span class="Normal">const</span> string& ingredient_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name == ingredient_name<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> - -set<<span class="Normal">int</span>> ingredient_indices<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> set<reagent>& ingredient_names<span class="Delimiter">)</span> <span class="Delimiter">{</span> - set<<span class="Normal">int</span>> result<span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <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>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>ingredient_names<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> != ingredient_names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> - result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Identifier">return</span> result<span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Comment">//: Sometimes you want to pass in two addresses, one pointing inside the</span> -<span class="Comment">//: other. For example, you want to delete a node from a linked list. You</span> -<span class="Comment">//: can't pass both pointers back out, because if a caller tries to make both</span> -<span class="Comment">//: identical then you can't tell which value will be written on the way out.</span> -<span class="Comment">//:</span> -<span class="Comment">//: Experimental solution: just tell mu that one points inside the other.</span> -<span class="Comment">//: This way we can return just one pointer as high up as necessary to capture</span> -<span class="Comment">//: all modifications performed by a recipe.</span> -<span class="Comment">//:</span> -<span class="Comment">//: We'll see if we end up wanting to abuse /contained-in for other reasons.</span> - -<span class="Delimiter">:(scenarios transform)</span> -<span class="Delimiter">:(scenario can_modify_contained_in_addresses)</span> -container test-list [ - <span class="Normal">next</span>:address:shared:test-list -] -def main [ - local-scope - <span class="Normal">p</span>:address:shared:test-list<span class="Special"> <- </span><span class="Normal">new</span> test-list:type - foo p -] -def foo p:address:shared:test-list <span class="Delimiter">-></span> p:address:shared:test-list [ - local-scope - load-ingredients - <span class="Normal">p2</span>:address:shared:test-list<span class="Special"> <- </span>test-next p - p<span class="Special"> <- </span>test-remove p2<span class="Delimiter">,</span> p -] -def test-next x:address:shared:test-list <span class="Delimiter">-></span> y:address:shared:test-list [ - local-scope - load-ingredients - y<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset -] -def test-remove x:address:shared:test-list/contained-in:from<span class="Delimiter">,</span> from:address:shared:test-list <span class="Delimiter">-></span> from:address:shared:test-list [ - local-scope - load-ingredients - <span class="Normal">x2</span>:address:address:shared:test-list<span class="Special"> <- </span>get-address *x<span class="Delimiter">,</span> next:offset <span class="Comment"># pretend modification</span> -] -$error: <span class="Constant">0</span> - -<span class="Delimiter">:(before "End Immutable Ingredients Special-cases")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> string_tree* tmp = property<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>tmp<span class="Delimiter">-></span>left || tmp<span class="Delimiter">-></span>right - || !is_present_in_ingredients<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> tmp<span class="Delimiter">-></span>value<span class="Delimiter">)</span> - || !is_present_in_products<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> tmp<span class="Delimiter">-></span>value<span class="Delimiter">))</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"contained-in can only point to another ingredient+product, but got "</span> << to_string<span class="Delimiter">(</span>property<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">continue</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/062scheduler.cc.html b/html/062scheduler.cc.html index 93810126..a809c13a 100644 --- a/html/062scheduler.cc.html +++ b/html/062scheduler.cc.html @@ -108,9 +108,8 @@ Routines<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Normal">bool</span> all_routines_done<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == RUNNING<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == RUNNING<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -510,6 +509,28 @@ DISCONTINUED<span class="Delimiter">,</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Test Teardown")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + raise << <span class="Constant">"some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + ++Num_failures<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Mu Test Teardown")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + raise << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + ++Num_failures<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> any_routines_with_error<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == DISCONTINUED<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> + <span class="Delimiter">:(before "End routine Fields")</span> <span class="Normal">int</span> limit<span class="Delimiter">;</span> <span class="Delimiter">:(before "End routine Constructor")</span> @@ -552,16 +573,16 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(scenario new_concurrent)</span> def f1 [ start-running f2 - <span class="Constant">1</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">1</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type <span class="Comment"># wait for f2 to complete</span> <span class="Delimiter">{</span> loop-unless <span class="Constant">4</span>:number/<span class="Special">raw</span> <span class="Delimiter">}</span> ] def f2 [ - <span class="Constant">2</span>:address:shared:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type + <span class="Constant">2</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type <span class="Comment"># hack: assumes scheduler implementation</span> - <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:address:shared:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:shared:number/<span class="Special">raw</span> + <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:number/<span class="Special">raw</span> <span class="Comment"># signal f2 complete</span> <span class="Constant">4</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">1</span> ] diff --git a/html/063wait.cc.html b/html/063wait.cc.html index da1acf6a..9e28ca29 100644 --- a/html/063wait.cc.html +++ b/html/063wait.cc.html @@ -41,15 +41,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color def f1 [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> start-running f2 - wait-<span class="Normal">for</span>-location <span class="Constant">1</span>:number + <span class="Constant">2</span>:location<span class="Special"> <- </span>copy <span class="Constant">1</span>/unsafe + wait-<span class="Normal">for</span>-location <span class="Constant">2</span>:location <span class="Comment"># now wait for f2 to run and modify location 1 before using its value</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:number + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:number ] def f2 [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> ] -<span class="Comment"># if we got the synchronization wrong we'd be storing 0 in location 2</span> -<span class="traceContains">+mem: storing 34 in location 2</span> +<span class="Comment"># if we got the synchronization wrong we'd be storing 0 in location 3</span> +<span class="traceContains">+mem: storing 34 in location 3</span> <span class="Comment">//: define the new state that all routines can be in</span> @@ -62,6 +63,27 @@ WAITING<span class="Delimiter">,</span> <span class="Delimiter">:(before "End routine Constructor")</span> waiting_on_location = old_value_of_waiting_location = <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Mu Test Teardown")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_waiting<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + raise << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": deadlock!</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + ++Num_failures<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Test Teardown")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + raise << <span class="Constant">"some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + ++Num_failures<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> any_routines_waiting<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == WAITING<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> + <span class="Comment">//: primitive recipe to put routines in that state</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> @@ -70,16 +92,22 @@ WAIT_FOR_LOCATION<span class="Delimiter">,</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"wait-for-location"</span><span class="Delimiter">,</span> WAIT_FOR_LOCATION<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> <span class="Normal">case</span> WAIT_FOR_LOCATION: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'wait-for-location' requires exactly one ingredient, but got "</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'wait-for-location' requires a location ingredient, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> WAIT_FOR_LOCATION: <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> + <span class="Normal">int</span> loc = 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">-></span>state = WAITING<span class="Delimiter">;</span> - Current_routine<span class="Delimiter">-></span>waiting_on_location = loc<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - Current_routine<span class="Delimiter">-></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">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"waiting for location "</span> << loc<span class="Delimiter">.</span>value << <span class="Constant">" to change from "</span> << 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> << end<span class="Delimiter">();</span> + Current_routine<span class="Delimiter">-></span>waiting_on_location = loc<span class="Delimiter">;</span> + Current_routine<span class="Delimiter">-></span>old_value_of_waiting_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"waiting for location "</span> << loc << <span class="Constant">" to change from "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">))</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -96,6 +124,142 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Comment">//: primitive to help compute locations to wait for</span> +<span class="Comment">//: only supports elements inside containers, no arrays or containers within</span> +<span class="Comment">//: containers yet.</span> + +<span class="Delimiter">:(scenario get_location)</span> +def main [ + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">15</span>:location<span class="Special"> <- </span>get-location <span class="Constant">12</span>:point<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+mem: storing 13 in location 15</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +GET_LOCATION<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"get-location"</span><span class="Delimiter">,</span> GET_LOCATION<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> GET_LOCATION: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'get-location' expects exactly 2 ingredients in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + 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="Normal">if</span> <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="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'get-location' should be a container, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << 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">-></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> + <span class="Normal">if</span> <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 << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'get-location' should have type 'offset', but got "</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>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">int</span> offset_value = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <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> + <span class="Normal">if</span> <span class="Delimiter">(</span>offset_value < <span class="Constant">0</span> || offset_value >= 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 << 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">"invalid offset "</span> << offset_value << <span class="Constant">" for "</span> << get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <span class="Delimiter">{</span> + offset_value = offset<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <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> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'get-location "</span> << base<span class="Delimiter">.</span>original_string << <span class="Constant">", "</span> << offset<span class="Delimiter">.</span>original_string << <span class="Constant">"' should write to type location but "</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>name << <span class="Constant">" has type "</span> << names_to_string_without_quotes<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>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> GET_LOCATION: <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> + <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to access location 0 in '"</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">;</span> + <span class="Normal">int</span> 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> + <span class="Normal">if</span> <span class="Delimiter">(</span>offset < <span class="Constant">0</span> || offset >= 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> + <span class="Normal">int</span> result = base_address<span class="Delimiter">;</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> + result += size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">(</span>base<span class="Delimiter">,</span> i<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << result << 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">:(code)</span> +<span class="Normal">bool</span> is_mu_location<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"location"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario get_location_out_of_bounds)</span> +<span class="Special">% Hide_errors = true;</span> +def main [ + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> + get-location <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">+error: main: invalid offset 2 for point-number</span> + +<span class="Delimiter">:(scenario get_location_out_of_bounds_2)</span> +<span class="Special">% Hide_errors = true;</span> +def main [ + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">14</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> + get-location <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: invalid offset -1 for point-number</span> + +<span class="Delimiter">:(scenario get_location_product_type_mismatch)</span> +<span class="Special">% Hide_errors = true;</span> +container boolbool [ + <span class="Normal">x</span>:boolean + <span class="Normal">y</span>:boolean +] +def main [ + <span class="Constant">12</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">1</span> + <span class="Constant">13</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">15</span>:boolean<span class="Special"> <- </span>get-location <span class="Constant">12</span>:boolbool<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+error: main: 'get-location 12:boolbool, 1:offset' should write to type location but 15 has type boolean</span> + +<span class="Delimiter">:(scenario get_location_indirect)</span> +<span class="Comment"># 'get-location' can read from container address</span> +def main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">4</span>:location<span class="Special"> <- </span>get-location <span class="Constant">1</span>:address:point/lookup<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+mem: storing 11 in location 4</span> + +<span class="Delimiter">:(scenario get_location_indirect_2)</span> +def main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> + <span class="Comment"># 10 reserved for refcount</span> + <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">4</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">20</span>/unsafe + <span class="Constant">4</span>:address:location/lookup<span class="Special"> <- </span>get-location <span class="Constant">1</span>:address:point/lookup<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+mem: storing 11 in location 21</span> + <span class="Comment">//: also allow waiting on a routine to stop running</span> <span class="Delimiter">:(scenario wait_for_routine)</span> diff --git a/html/064rewrite_literal_string.cc.html b/html/064rewrite_literal_string.cc.html index b91323f7..b828f719 100644 --- a/html/064rewrite_literal_string.cc.html +++ b/html/064rewrite_literal_string.cc.html @@ -37,7 +37,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color def main [ <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo [abc] ] -def foo x:address:shared:array:character <span class="Delimiter">-></span> n:number [ +def foo x:address:array:character <span class="Delimiter">-></span> n:number [ local-scope load-ingredients n<span class="Special"> <- </span>length *x @@ -79,7 +79,7 @@ set<string> recipes_taking_literal_strings<span class="Delimiter">;</span> <span class="Normal">if</span> <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>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> instruction def<span class="Delimiter">;</span> ostringstream ingredient_name<span class="Delimiter">;</span> - ingredient_name << inst<span class="Delimiter">.</span>name << <span class="Constant">'_'</span> << i << <span class="Constant">'_'</span> << j << <span class="Constant">":address:shared:array:character"</span><span class="Delimiter">;</span> + ingredient_name << inst<span class="Delimiter">.</span>name << <span class="Constant">'_'</span> << i << <span class="Constant">'_'</span> << j << <span class="Constant">":address:array:character"</span><span class="Delimiter">;</span> def<span class="Delimiter">.</span>name = <span class="Constant">"new"</span><span class="Delimiter">;</span> def<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">));</span> def<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">()));</span> diff --git a/html/070text.mu.html b/html/070text.mu.html index 7681faeb..2f8f8b5c 100644 --- a/html/070text.mu.html +++ b/html/070text.mu.html @@ -36,27 +36,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># to-text-line gets called implicitly in various places</span> <span class="Comment"># define it to be identical to 'to-text' by default</span> -<span class="muRecipe">def</span> to-text-line x:_elem<span class="muRecipe"> -> </span>y:address:shared:array:character [ +<span class="muRecipe">def</span> to-text-line x:_elem<span class="muRecipe"> -> </span>y:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> y<span class="Special"> <- </span>to-text x ] <span class="Comment"># variant for arrays (since we can't pass them around otherwise)</span> -<span class="muRecipe">def</span> array-to-text-line x:address:shared:array:_elem<span class="muRecipe"> -> </span>y:address:shared:array:character [ +<span class="muRecipe">def</span> array-to-text-line x:address:array:_elem<span class="muRecipe"> -> </span>y:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> y<span class="Special"> <- </span>to-text *x ] <span class="Comment"># to-text on text is just the identity function</span> -<span class="muRecipe">def</span> to-text x:address:shared:array:character<span class="muRecipe"> -> </span>y:address:shared:array:character [ +<span class="muRecipe">def</span> to-text x:address:array:character<span class="muRecipe"> -> </span>y:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return</span> x ] -<span class="muRecipe">def</span> equal a:address:shared:array:character, b:address:shared:array:character<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> equal a:address:array:character, b:address:array:character<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> a-len:number<span class="Special"> <- </span>length *a @@ -89,8 +89,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-equal-reflexive [ run [ - <span class="Constant">default-space</span>:address:shared:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - x:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> + x:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal x, x ] memory-should-contain [ @@ -100,9 +100,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-equal-identical [ run [ - <span class="Constant">default-space</span>:address:shared:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - x:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - y:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> + x:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal x, y ] memory-should-contain [ @@ -112,9 +112,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-equal-distinct-lengths [ run [ - <span class="Constant">default-space</span>:address:shared:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - x:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - y:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> + x:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal x, y ] memory-should-contain [ @@ -130,9 +130,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-equal-with-empty [ run [ - <span class="Constant">default-space</span>:address:shared:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - x:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - y:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> + x:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal x, y ] memory-should-contain [ @@ -142,9 +142,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-equal-common-lengths-but-distinct [ run [ - <span class="Constant">default-space</span>:address:shared:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - x:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - y:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abd]</span> + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> + x:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abd]</span> <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal x, y ] memory-should-contain [ @@ -155,56 +155,54 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># A new type to help incrementally construct texts.</span> <span class="muData">container</span> buffer [ length:number - data:address:shared:array:character + data:address:array:character ] -<span class="muRecipe">def</span> new-buffer capacity:number<span class="muRecipe"> -> </span>result:address:shared:buffer [ +<span class="muRecipe">def</span> new-buffer capacity:number<span class="muRecipe"> -> </span>result:address:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>new <span class="Constant">buffer:type</span> - len:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">length:offset</span> - *len:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - s:address:address:shared:array:character<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *s<span class="Special"> <- </span>new <span class="Constant">character:type</span>, capacity + *result<span class="Special"> <- </span>put *result, <span class="Constant">length:offset</span>, <span class="Constant">0</span> + data:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, capacity + *result<span class="Special"> <- </span>put *result, <span class="Constant">data:offset</span>, data <span class="muControl">return</span> result ] -<span class="muRecipe">def</span> grow-buffer in:address:shared:buffer<span class="muRecipe"> -> </span>in:address:shared:buffer [ +<span class="muRecipe">def</span> grow-buffer in:address:buffer<span class="muRecipe"> -> </span>in:address:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># double buffer size</span> - x:address:address:shared:array:character<span class="Special"> <- </span>get-address *in, <span class="Constant">data:offset</span> - oldlen:number<span class="Special"> <- </span>length **x + olddata:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + oldlen:number<span class="Special"> <- </span>length *olddata newlen:number<span class="Special"> <- </span>multiply oldlen, <span class="Constant">2</span> - olddata:address:shared:array:character<span class="Special"> <- </span>copy *x - *x<span class="Special"> <- </span>new <span class="Constant">character:type</span>, newlen + newdata:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, newlen + *in<span class="Special"> <- </span>put *in, <span class="Constant">data:offset</span>, newdata <span class="Comment"># copy old contents</span> i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>greater-or-equal i, oldlen <span class="muControl">break-if</span> done? src:character<span class="Special"> <- </span>index *olddata, i - dest:address:character<span class="Special"> <- </span>index-address **x, i - *dest<span class="Special"> <- </span>copy src + *newdata<span class="Special"> <- </span>put-index *newdata, i, src i<span class="Special"> <- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> buffer-full? in:address:shared:buffer<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> buffer-full? in:address:buffer<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:number<span class="Special"> <- </span>get *in, <span class="Constant">length:offset</span> - s:address:shared:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> capacity:number<span class="Special"> <- </span>length *s result<span class="Special"> <- </span>greater-or-equal len, capacity ] <span class="Comment"># most broadly applicable definition of append to a buffer: just call to-text</span> -<span class="muRecipe">def</span> append buf:address:shared:buffer, x:_elem<span class="muRecipe"> -> </span>buf:address:shared:buffer [ +<span class="muRecipe">def</span> append buf:address:buffer, x:_elem<span class="muRecipe"> -> </span>buf:address:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - text:address:shared:array:character<span class="Special"> <- </span>to-text x + text:address:array:character<span class="Special"> <- </span>to-text x len:number<span class="Special"> <- </span>length *text i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> @@ -217,17 +215,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> append in:address:shared:buffer, c:character<span class="muRecipe"> -> </span>in:address:shared:buffer [ +<span class="muRecipe">def</span> append in:address:buffer, c:character<span class="muRecipe"> -> </span>in:address:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - len:address:number<span class="Special"> <- </span>get-address *in, <span class="Constant">length:offset</span> + len:number<span class="Special"> <- </span>get *in, <span class="Constant">length:offset</span> <span class="Delimiter">{</span> <span class="Comment"># backspace? just drop last character if it exists and return</span> backspace?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">8/backspace</span> <span class="muControl">break-unless</span> backspace? - empty?:boolean<span class="Special"> <- </span>lesser-or-equal *len, <span class="Constant">0</span> + empty?:boolean<span class="Special"> <- </span>lesser-or-equal len, <span class="Constant">0</span> <span class="muControl">return-if</span> empty? - *len<span class="Special"> <- </span>subtract *len, <span class="Constant">1</span> + len<span class="Special"> <- </span>subtract len, <span class="Constant">1</span> + *in<span class="Special"> <- </span>put *in, <span class="Constant">length:offset</span>, len <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> @@ -236,30 +235,30 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> full? in<span class="Special"> <- </span>grow-buffer in <span class="Delimiter">}</span> - s:address:shared:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> - dest:address:character<span class="Special"> <- </span>index-address *s, *len - *dest<span class="Special"> <- </span>copy c - *len<span class="Special"> <- </span>add *len, <span class="Constant">1</span> + s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + *s<span class="Special"> <- </span>put-index *s, len, c + len<span class="Special"> <- </span>add len, <span class="Constant">1</span> + *in<span class="Special"> <- </span>put *in, <span class="Constant">length:offset</span>, len ] <span class="muScenario">scenario</span> buffer-append-works [ run [ <span class="Constant">local-scope</span> - x:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">3</span> - s1:address:shared:array:character<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> + x:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">3</span> + s1:address:array:character<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> c:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> x<span class="Special"> <- </span>append x, c c:character<span class="Special"> <- </span>copy <span class="Constant">98/b</span> x<span class="Special"> <- </span>append x, c c:character<span class="Special"> <- </span>copy <span class="Constant">99/c</span> x<span class="Special"> <- </span>append x, c - s2:address:shared:array:character<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> + s2:address:array:character<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> <span class="Constant">1</span>:boolean/<span class="Special">raw <- </span>equal s1, s2 <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *s2 <span class="Constant"> +buffer-filled</span> c:character<span class="Special"> <- </span>copy <span class="Constant">100/d</span> x<span class="Special"> <- </span>append x, c - s3:address:shared:array:character<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> + s3:address:array:character<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal s1, s3 <span class="Constant">11</span>:number/<span class="Special">raw <- </span>get *x, <span class="Constant">length:offset</span> <span class="Constant">12</span>:array:character/<span class="Special">raw <- </span>copy *s3 @@ -287,14 +286,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> buffer-append-handles-backspace [ run [ <span class="Constant">local-scope</span> - x:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">3</span> + x:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">3</span> c:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> x<span class="Special"> <- </span>append x, c c:character<span class="Special"> <- </span>copy <span class="Constant">98/b</span> x<span class="Special"> <- </span>append x, c c:character<span class="Special"> <- </span>copy <span class="Constant">8/backspace</span> x<span class="Special"> <- </span>append x, c - s:address:shared:array:character<span class="Special"> <- </span>buffer-to-array x + s:address:array:character<span class="Special"> <- </span>buffer-to-array x <span class="Constant">1</span>:array:character/<span class="Special">raw <- </span>copy *s ] memory-should-contain [ @@ -304,7 +303,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> to-text n:number<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> to-text n:number<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># is n zero?</span> @@ -322,14 +321,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color n<span class="Special"> <- </span>multiply n, <span class="Constant">-1</span> <span class="Delimiter">}</span> <span class="Comment"># add digits from right to left into intermediate buffer</span> - tmp:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">30</span> + tmp:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">30</span> digit-base:number<span class="Special"> <- </span>copy <span class="Constant">48</span> <span class="Comment"># '0'</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>equal n, <span class="Constant">0</span> <span class="muControl">break-if</span> done? n, digit:number<span class="Special"> <- </span>divide-with-remainder n, <span class="Constant">10</span> c:character<span class="Special"> <- </span>add digit-base, digit - tmp:address:shared:buffer<span class="Special"> <- </span>append tmp, c + tmp:address:buffer<span class="Special"> <- </span>append tmp, c <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># add sign</span> @@ -340,7 +339,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Comment"># reverse buffer into text result</span> len:number<span class="Special"> <- </span>get *tmp, <span class="Constant">length:offset</span> - buf:address:shared:array:character<span class="Special"> <- </span>get *tmp, <span class="Constant">data:offset</span> + buf:address:array:character<span class="Special"> <- </span>get *tmp, <span class="Constant">data:offset</span> result<span class="Special"> <- </span>new <span class="Constant">character:type</span>, len i:number<span class="Special"> <- </span>subtract len, <span class="Constant">1</span> <span class="Comment"># source index, decreasing</span> j:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># destination index, increasing</span> @@ -350,29 +349,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> done? <span class="Comment"># result[j] = tmp[i]</span> src:character<span class="Special"> <- </span>index *buf, i - dest:address:character<span class="Special"> <- </span>index-address *result, j - *dest<span class="Special"> <- </span>copy src + *result<span class="Special"> <- </span>put-index *result, j, src i<span class="Special"> <- </span>subtract i, <span class="Constant">1</span> j<span class="Special"> <- </span>add j, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> to-text x:boolean<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> to-text x:boolean<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> n:number<span class="Special"> <- </span>copy x:boolean result<span class="Special"> <- </span>to-text n ] -<span class="muRecipe">def</span> to-text x:address:_elem<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> to-text x:address:_elem<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> n:number<span class="Special"> <- </span>copy x result<span class="Special"> <- </span>to-text n ] -<span class="muRecipe">def</span> buffer-to-array in:address:shared:buffer<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> buffer-to-array in:address:buffer<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -381,7 +379,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">return</span> <span class="Constant">0</span> <span class="Delimiter">}</span> len:number<span class="Special"> <- </span>get *in, <span class="Constant">length:offset</span> - s:address:shared:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> <span class="Comment"># we can't just return s because it is usually the wrong length</span> result<span class="Special"> <- </span>new <span class="Constant">character:type</span>, len i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -389,8 +387,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color done?:boolean<span class="Special"> <- </span>greater-or-equal i, len <span class="muControl">break-if</span> done? src:character<span class="Special"> <- </span>index *s, i - dest:address:character<span class="Special"> <- </span>index-address *result, i - *dest<span class="Special"> <- </span>copy src + *result<span class="Special"> <- </span>put-index *result, i, src i<span class="Special"> <- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> @@ -398,8 +395,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> integer-to-decimal-digit-zero [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>to-text <span class="Constant">0</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>to-text <span class="Constant">0</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[0]</span> @@ -408,8 +405,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> integer-to-decimal-digit-positive [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>to-text <span class="Constant">234</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>to-text <span class="Constant">234</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[234]</span> @@ -418,8 +415,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> integer-to-decimal-digit-negative [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>to-text <span class="Constant">-1</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>to-text <span class="Constant">-1</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -428,7 +425,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> append a:address:shared:array:character, b:address:shared:array:character<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> append a:address:array:character, b:address:array:character<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># result = new character[a.length + b.length]</span> @@ -444,9 +441,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color a-done?:boolean<span class="Special"> <- </span>greater-or-equal i, a-len <span class="muControl">break-if</span> a-done? <span class="Comment"># result[result-idx] = a[i]</span> - out:address:character<span class="Special"> <- </span>index-address *result, result-idx in:character<span class="Special"> <- </span>index *a, i - *out<span class="Special"> <- </span>copy in + *result<span class="Special"> <- </span>put-index *result, result-idx, in i<span class="Special"> <- </span>add i, <span class="Constant">1</span> result-idx<span class="Special"> <- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -458,9 +454,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color b-done?:boolean<span class="Special"> <- </span>greater-or-equal i, b-len <span class="muControl">break-if</span> b-done? <span class="Comment"># result[result-idx] = a[i]</span> - out:address:character<span class="Special"> <- </span>index-address *result, result-idx in:character<span class="Special"> <- </span>index *b, i - *out<span class="Special"> <- </span>copy in + *result<span class="Special"> <- </span>put-index *result, result-idx, in i<span class="Special"> <- </span>add i, <span class="Constant">1</span> result-idx<span class="Special"> <- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -469,10 +464,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-append-1 [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[hello,]</span> - <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[ world!]</span> - <span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw <- </span>append <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw</span> - <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[hello,]</span> + <span class="Constant">2</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[ world!]</span> + <span class="Constant">3</span>:address:array:character/<span class="Special">raw <- </span>append <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span> + <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">4</span>:array:character<span class="Special"> <- </span><span class="Constant">[hello, world!]</span> @@ -481,33 +476,32 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> replace-character-in-text [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">98/b</span>, <span class="Constant">122/z</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">98/b</span>, <span class="Constant">122/z</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[azc]</span> ] ] -<span class="muRecipe">def</span> replace s:address:shared:array:character, oldc:character, newc:character, from:number/optional<span class="muRecipe"> -> </span>s:address:shared:array:character [ +<span class="muRecipe">def</span> replace s:address:array:character, oldc:character, newc:character, from:number/optional<span class="muRecipe"> -> </span>s:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:number<span class="Special"> <- </span>length *s i:number<span class="Special"> <- </span>find-next s, oldc, from done?:boolean<span class="Special"> <- </span>greater-or-equal i, len <span class="muControl">return-if</span> done?, s/same-as-ingredient:<span class="Constant">0</span> - dest:address:character<span class="Special"> <- </span>index-address *s, i - *dest<span class="Special"> <- </span>copy newc + *s<span class="Special"> <- </span>put-index *s, i, newc i<span class="Special"> <- </span>add i, <span class="Constant">1</span> s<span class="Special"> <- </span>replace s, oldc, newc, i ] <span class="muScenario">scenario</span> replace-character-at-start [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">97/a</span>, <span class="Constant">122/z</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">97/a</span>, <span class="Constant">122/z</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[zbc]</span> @@ -516,9 +510,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> replace-character-at-end [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">99/c</span>, <span class="Constant">122/z</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">99/c</span>, <span class="Constant">122/z</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[abz]</span> @@ -527,9 +521,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> replace-character-missing [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">100/d</span>, <span class="Constant">122/z</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">100/d</span>, <span class="Constant">122/z</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> @@ -538,9 +532,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> replace-all-characters [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[banana]</span> - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">97/a</span>, <span class="Constant">122/z</span> - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[banana]</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">97/a</span>, <span class="Constant">122/z</span> + <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">2</span>:array:character<span class="Special"> <- </span><span class="Constant">[bznznz]</span> @@ -548,7 +542,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># replace underscores in first with remaining args</span> -<span class="muRecipe">def</span> interpolate template:address:shared:array:character<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> interpolate template:address:array:character<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># consume just the template</span> <span class="Comment"># compute result-len, space to allocate for result</span> @@ -556,7 +550,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color result-len:number<span class="Special"> <- </span>copy tem-len <span class="Delimiter">{</span> <span class="Comment"># while ingredients remain</span> - a:address:shared:array:character, arg-received?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + a:address:array:character, arg-received?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="muControl">break-unless</span> arg-received? <span class="Comment"># result-len = result-len + arg.length - 1 (for the 'underscore' being replaced)</span> a-len:number<span class="Special"> <- </span>length *a @@ -564,7 +558,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color result-len<span class="Special"> <- </span>subtract result-len, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - rewind-ingredients + <span class="Constant">rewind-ingredients</span> _<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="Comment"># skip template</span> result<span class="Special"> <- </span>new <span class="Constant">character:type</span>, result-len <span class="Comment"># repeatedly copy sections of template and 'holes' into result</span> @@ -572,7 +566,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while arg received</span> - a:address:shared:array:character, arg-received?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + a:address:array:character, arg-received?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="muControl">break-unless</span> arg-received? <span class="Comment"># copy template into result until '_'</span> <span class="Delimiter">{</span> @@ -584,8 +578,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color underscore?:boolean<span class="Special"> <- </span>equal in, <span class="Constant">95/_</span> <span class="muControl">break-if</span> underscore? <span class="Comment"># result[result-idx] = template[i]</span> - out:address:character<span class="Special"> <- </span>index-address *result, result-idx - *out<span class="Special"> <- </span>copy in + *result<span class="Special"> <- </span>put-index *result, result-idx, in i<span class="Special"> <- </span>add i, <span class="Constant">1</span> result-idx<span class="Special"> <- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -598,8 +591,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> arg-done? <span class="Comment"># result[result-idx] = a[j]</span> in:character<span class="Special"> <- </span>index *a, j - out:address:character<span class="Special"> <- </span>index-address *result, result-idx - *out<span class="Special"> <- </span>copy in + *result<span class="Special"> <- </span>put-index *result, result-idx, in j<span class="Special"> <- </span>add j, <span class="Constant">1</span> result-idx<span class="Special"> <- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -616,8 +608,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> tem-done? <span class="Comment"># result[result-idx] = template[i]</span> in:character<span class="Special"> <- </span>index *template, i - out:address:character<span class="Special"> <- </span>index-address *result, result-idx:number - *out<span class="Special"> <- </span>copy in + *result<span class="Special"> <- </span>put-index *result, result-idx, in i<span class="Special"> <- </span>add i, <span class="Constant">1</span> result-idx<span class="Special"> <- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -626,10 +617,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> interpolate-works [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc _]</span> - <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw <- </span>interpolate <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw</span> - <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc _]</span> + <span class="Constant">2</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[def]</span> + <span class="Constant">3</span>:address:array:character/<span class="Special">raw <- </span>interpolate <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span> + <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">4</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc def]</span> @@ -638,10 +629,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> interpolate-at-start [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[_, hello!]</span> - <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw <- </span>interpolate <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw</span> - <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[_, hello!]</span> + <span class="Constant">2</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">3</span>:address:array:character/<span class="Special">raw <- </span>interpolate <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span> + <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">4</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc, hello!]</span> @@ -651,10 +642,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> interpolate-at-end [ run [ - <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[hello, _]</span> - <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw <- </span>interpolate <span class="Constant">1</span>:address:shared:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:shared:array:character/<span class="Special">raw</span> - <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:shared:array:character/<span class="Special">raw</span> + <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[hello, _]</span> + <span class="Constant">2</span>:address:array:character/<span class="Special">raw <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">3</span>:address:array:character/<span class="Special">raw <- </span>interpolate <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span> + <span class="Constant">4</span>:array:character/<span class="Special">raw <- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span> ] memory-should-contain [ <span class="Constant">4</span>:array:character<span class="Special"> <- </span><span class="Constant">[hello, abc]</span> @@ -723,7 +714,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color result<span class="Special"> <- </span>equal c, <span class="Constant">12288/ideographic-space</span> ] -<span class="muRecipe">def</span> trim s:address:shared:array:character<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> trim s:address:array:character<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:number<span class="Special"> <- </span>length *s @@ -755,7 +746,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Comment"># result = new character[end+1 - start]</span> new-len:number<span class="Special"> <- </span>subtract end, start, <span class="Constant">-1</span> - result:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, new-len + result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, new-len <span class="Comment"># copy the untrimmed parts between start and end</span> i:number<span class="Special"> <- </span>copy start j:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -765,8 +756,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> done? <span class="Comment"># result[j] = s[i]</span> src:character<span class="Special"> <- </span>index *s, i - dest:address:character<span class="Special"> <- </span>index-address *result, j - *dest<span class="Special"> <- </span>copy src + *result<span class="Special"> <- </span>put-index *result, j, src i<span class="Special"> <- </span>add i, <span class="Constant">1</span> j<span class="Special"> <- </span>add j, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -775,9 +765,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> trim-unmodified [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> @@ -786,9 +776,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> trim-left [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> @@ -797,9 +787,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> trim-right [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc ]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc ]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> @@ -808,9 +798,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> trim-left-right [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc ]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc ]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> @@ -819,17 +809,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> trim-newline-tab [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc</span> <span class="Constant">]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>trim <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[abc]</span> ] ] -<span class="muRecipe">def</span> find-next text:address:shared:array:character, pattern:character, idx:number<span class="muRecipe"> -> </span>next-index:number [ +<span class="muRecipe">def</span> find-next text:address:array:character, pattern:character, idx:number<span class="muRecipe"> -> </span>next-index:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:number<span class="Special"> <- </span>length *text @@ -847,8 +837,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -857,8 +847,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-empty [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> @@ -867,8 +857,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-initial [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[/abc]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[/abc]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># prefix match</span> @@ -877,8 +867,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-final [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc/]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc/]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># suffix match</span> @@ -887,8 +877,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-missing [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># no match</span> @@ -897,8 +887,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-invalid-index [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">4/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">4/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># no change</span> @@ -907,8 +897,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-first [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab/c/]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab/c/]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># first '/' of multiple</span> @@ -917,8 +907,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-find-next-second [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab/c/]</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span>, <span class="Constant">3/start-index</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab/c/]</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">3/start-index</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># second '/' of multiple</span> @@ -927,7 +917,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># search for a pattern of multiple characters</span> <span class="Comment"># fairly dumb algorithm</span> -<span class="muRecipe">def</span> find-next text:address:shared:array:character, pattern:address:shared:array:character, idx:number<span class="muRecipe"> -> </span>next-index:number [ +<span class="muRecipe">def</span> find-next text:address:array:character, pattern:address:array:character, idx:number<span class="muRecipe"> -> </span>next-index:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> first:character<span class="Special"> <- </span>index *pattern, <span class="Constant">0</span> @@ -949,9 +939,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> find-next-text-1 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -960,9 +950,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> find-next-text-2 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">1</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">1</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -971,9 +961,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> find-next-no-match [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[bd]</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[bd]</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># not found</span> @@ -982,9 +972,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> find-next-suffix-match [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[cd]</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[cd]</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -993,9 +983,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> find-next-suffix-match-2 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[cde]</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[cde]</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># not found</span> @@ -1003,7 +993,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># checks if pattern matches at index 'idx'</span> -<span class="muRecipe">def</span> match-at text:address:shared:array:character, pattern:address:shared:array:character, idx:number<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> match-at text:address:array:character, pattern:address:array:character, idx:number<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> pattern-len:number<span class="Special"> <- </span>length *pattern @@ -1036,9 +1026,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-checks-pattern-at-index [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># match found</span> @@ -1047,8 +1037,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-reflexive [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">1</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># match found</span> @@ -1057,9 +1047,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-outside-bounds [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">4</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">4</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># never matches</span> @@ -1068,9 +1058,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-empty-pattern [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># always matches empty pattern given a valid index</span> @@ -1079,9 +1069,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-empty-pattern-outside-bound [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">4</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">4</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no match</span> @@ -1090,9 +1080,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-empty-text [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no match</span> @@ -1101,8 +1091,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-empty-against-empty [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">1</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># matches because pattern is also empty</span> @@ -1111,9 +1101,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-inside-bounds [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">1</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">1</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># match</span> @@ -1122,16 +1112,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> match-at-inside-bounds-2 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[bc]</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no match</span> ] ] -<span class="muRecipe">def</span> split s:address:shared:array:character, delim:character<span class="muRecipe"> -> </span>result:address:shared:array:address:shared:array:character [ +<span class="muRecipe">def</span> split s:address:array:character, delim:character<span class="muRecipe"> -> </span>result:address:array:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># empty text? return empty array</span> @@ -1139,7 +1129,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> empty?:boolean<span class="Special"> <- </span>equal len, <span class="Constant">0</span> <span class="muControl">break-unless</span> empty? - result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(address shared array character): type<span class="Delimiter">}</span>, <span class="Constant">0</span> + result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(address array character): type<span class="Delimiter">}</span>, <span class="Constant">0</span> <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># count #pieces we need room for</span> @@ -1154,7 +1144,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># allocate space</span> - result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(address shared array character): type<span class="Delimiter">}</span>, count + result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(address array character): type<span class="Delimiter">}</span>, count <span class="Comment"># repeatedly copy slices start..end until delimiter into result[curr-result]</span> curr-result:number<span class="Special"> <- </span>copy <span class="Constant">0</span> start:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -1164,8 +1154,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> done? end:number<span class="Special"> <- </span>find-next s, delim, start <span class="Comment"># copy start..end into result[curr-result]</span> - dest:address:address:shared:array:character<span class="Special"> <- </span>index-address *result, curr-result - *dest<span class="Special"> <- </span>copy-range s, start, end + dest:address:array:character<span class="Special"> <- </span>copy-range s, start, end + *result<span class="Special"> <- </span>put-index *result, curr-result, dest <span class="Comment"># slide over to next slice</span> start<span class="Special"> <- </span>add end, <span class="Constant">1</span> curr-result<span class="Special"> <- </span>add curr-result, <span class="Constant">1</span> @@ -1175,13 +1165,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-split-1 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b]</span> - <span class="Constant">2</span>:address:shared:array:address:shared:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:shared:array:address:shared:array:character - <span class="Constant">4</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">0</span> - <span class="Constant">5</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">1</span> - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:shared:array:character - <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b]</span> + <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:array:address:array:character + <span class="Constant">4</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span> + <span class="Constant">5</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">1</span> + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:array:character + <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># length of result</span> @@ -1192,15 +1182,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-split-2 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b/c]</span> - <span class="Constant">2</span>:address:shared:array:address:shared:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:shared:array:address:shared:array:character - <span class="Constant">4</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">0</span> - <span class="Constant">5</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">1</span> - <span class="Constant">6</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">2</span> - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:shared:array:character - <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:shared:array:character - <span class="Constant">30</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">6</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b/c]</span> + <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:array:address:array:character + <span class="Constant">4</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span> + <span class="Constant">5</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">1</span> + <span class="Constant">6</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">2</span> + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:array:character + <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:array:character + <span class="Constant">30</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">6</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># length of result</span> @@ -1212,11 +1202,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-split-missing [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:address:shared:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:shared:array:address:shared:array:character - <span class="Constant">4</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">0</span> - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:array:address:array:character + <span class="Constant">4</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span> + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># length of result</span> @@ -1226,9 +1216,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-split-empty [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:address:shared:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:shared:array:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:array:address:array:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty result</span> @@ -1237,17 +1227,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-split-empty-piece [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b//c]</span> - <span class="Constant">2</span>:address:shared:array:address:shared:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:shared:array:address:shared:array:character - <span class="Constant">4</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">0</span> - <span class="Constant">5</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">1</span> - <span class="Constant">6</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">2</span> - <span class="Constant">7</span>:address:shared:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:shared:array:address:shared:array:character, <span class="Constant">3</span> - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:shared:array:character - <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:shared:array:character - <span class="Constant">30</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">6</span>:address:shared:array:character - <span class="Constant">40</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">7</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b//c]</span> + <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> <- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>length *<span class="Constant">2</span>:address:array:address:array:character + <span class="Constant">4</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span> + <span class="Constant">5</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">1</span> + <span class="Constant">6</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">2</span> + <span class="Constant">7</span>:address:array:character<span class="Special"> <- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">3</span> + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:array:character + <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">5</span>:address:array:character + <span class="Constant">30</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">6</span>:address:array:character + <span class="Constant">40</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">7</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># length of result</span> @@ -1258,7 +1248,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> split-first text:address:shared:array:character, delim:character<span class="muRecipe"> -> </span>x:address:shared:array:character, y:address:shared:array:character [ +<span class="muRecipe">def</span> split-first text:address:array:character, delim:character<span class="muRecipe"> -> </span>x:address:array:character, y:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># empty text? return empty texts</span> @@ -1266,22 +1256,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> empty?:boolean<span class="Special"> <- </span>equal len, <span class="Constant">0</span> <span class="muControl">break-unless</span> empty? - x:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - y:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + x:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="muControl">return</span> <span class="Delimiter">}</span> idx:number<span class="Special"> <- </span>find-next text, delim, <span class="Constant">0</span> - x:address:shared:array:character<span class="Special"> <- </span>copy-range text, <span class="Constant">0</span>, idx + x:address:array:character<span class="Special"> <- </span>copy-range text, <span class="Constant">0</span>, idx idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> - y:address:shared:array:character<span class="Special"> <- </span>copy-range text, idx, len + y:address:array:character<span class="Special"> <- </span>copy-range text, idx, len ] <span class="muScenario">scenario</span> text-split-first [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b]</span> - <span class="Constant">2</span>:address:shared:array:character, <span class="Constant">3</span>:address:shared:array:character<span class="Special"> <- </span>split-first <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">47/slash</span> - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character - <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a/b]</span> + <span class="Constant">2</span>:address:array:character, <span class="Constant">3</span>:address:array:character<span class="Special"> <- </span>split-first <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span> + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character + <span class="Constant">20</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:array:character ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> <- </span><span class="Constant">[a]</span> @@ -1289,7 +1279,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> copy-range buf:address:shared:array:character, start:number, end:number<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> copy-range buf:address:array:character, start:number, end:number<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if end is out of bounds, trim it</span> @@ -1297,7 +1287,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color end:number<span class="Special"> <- </span>min len, end <span class="Comment"># allocate space for result</span> len<span class="Special"> <- </span>subtract end, start - result:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, len + result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, len <span class="Comment"># copy start..end into result[curr-result]</span> src-idx:number<span class="Special"> <- </span>copy start dest-idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -1305,8 +1295,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color done?:boolean<span class="Special"> <- </span>greater-or-equal src-idx, end <span class="muControl">break-if</span> done? src:character<span class="Special"> <- </span>index *buf, src-idx - dest:address:character<span class="Special"> <- </span>index-address *result, dest-idx - *dest<span class="Special"> <- </span>copy src + *result<span class="Special"> <- </span>put-index *result, dest-idx, src src-idx<span class="Special"> <- </span>add src-idx, <span class="Constant">1</span> dest-idx<span class="Special"> <- </span>add dest-idx, <span class="Constant">1</span> <span class="muControl">loop</span> @@ -1315,9 +1304,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-copy-copies-partial-text [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>copy-range <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">1</span>, <span class="Constant">3</span> - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>copy-range <span class="Constant">1</span>:address:array:character, <span class="Constant">1</span>, <span class="Constant">3</span> + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[bc]</span> @@ -1326,9 +1315,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-copy-out-of-bounds [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>copy-range <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>, <span class="Constant">4</span> - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>copy-range <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>, <span class="Constant">4</span> + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[c]</span> @@ -1337,9 +1326,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> text-copy-out-of-bounds-2 [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>copy-range <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">3</span>, <span class="Constant">3</span> - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>copy-range <span class="Constant">1</span>:address:array:character, <span class="Constant">3</span>, <span class="Constant">3</span> + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span>:array:character<span class="Special"> <- </span><span class="Constant">[]</span> diff --git a/html/071rewrite_stash.cc.html b/html/071rewrite_stash.cc.html index 689d8a1b..76a10045 100644 --- a/html/071rewrite_stash.cc.html +++ b/html/071rewrite_stash.cc.html @@ -42,8 +42,8 @@ recipe main [ <span class="Normal">n</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> stash n ] -<span class="traceContains">+transform: {stash_2_0: ("address" "shared" "array" "character")} <- to-text-line {n: "number"}</span> -<span class="traceContains">+transform: stash {stash_2_0: ("address" "shared" "array" "character")}</span> +<span class="traceContains">+transform: {stash_2_0: ("address" "array" "character")} <- to-text-line {n: "number"}</span> +<span class="traceContains">+transform: stash {stash_2_0: ("address" "array" "character")}</span> <span class="Comment">//: special case: rewrite attempts to stash contents of most arrays to avoid</span> <span class="Comment">//: passing addresses around</span> @@ -51,11 +51,19 @@ recipe main [ <span class="Delimiter">:(scenario rewrite_stashes_of_arrays)</span> recipe main [ local-scope - <span class="Normal">n</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">3</span> + <span class="Normal">n</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">3</span> stash *n ] -<span class="traceContains">+transform: {stash_2_0: ("address" "shared" "array" "character")} <- array-to-text-line {n: ("address" "shared" "array" "number")}</span> -<span class="traceContains">+transform: stash {stash_2_0: ("address" "shared" "array" "character")}</span> +<span class="traceContains">+transform: {stash_2_0: ("address" "array" "character")} <- array-to-text-line {n: ("address" "array" "number")}</span> +<span class="traceContains">+transform: stash {stash_2_0: ("address" "array" "character")}</span> + +<span class="Delimiter">:(scenario ignore_stashes_of_static_arrays)</span> +recipe main [ + local-scope + <span class="Normal">n</span>:array:number:<span class="Constant">3</span><span class="Special"> <- </span>create-array + stash n +] +<span class="traceContains">+transform: stash {n: ("array" "number" "3")}</span> <span class="Delimiter">:(before "End Instruction Inserting/Deleting Transforms")</span> Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>rewrite_stashes_to_text<span class="Delimiter">);</span> @@ -76,11 +84,16 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa instruction& inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"stash"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<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="Normal">if</span> <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> + <span class="Comment">// error; will be handled elsewhere</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Normal">if</span> <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>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// don't try to extend static arrays</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_static_array<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> instruction def<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_address_of_array<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_lookup_of_address_of_array<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Delimiter">{</span> def<span class="Delimiter">.</span>name = <span class="Constant">"array-to-text-line"</span><span class="Delimiter">;</span> reagent tmp = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> drop_one_lookup<span class="Delimiter">(</span>tmp<span class="Delimiter">);</span> @@ -91,7 +104,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa def<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">));</span> <span class="Delimiter">}</span> ostringstream ingredient_name<span class="Delimiter">;</span> - ingredient_name << <span class="Constant">"stash_"</span> << i << <span class="Constant">'_'</span> << j << <span class="Constant">":address:shared:array:character"</span><span class="Delimiter">;</span> + ingredient_name << <span class="Constant">"stash_"</span> << i << <span class="Constant">'_'</span> << j << <span class="Constant">":address:array:character"</span><span class="Delimiter">;</span> def<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">()));</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << to_string<span class="Delimiter">(</span>def<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> new_instructions<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>def<span class="Delimiter">);</span> @@ -105,11 +118,17 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>new_instructions<span class="Delimiter">);</span> <span class="Delimiter">}</span> -<span class="Normal">bool</span> is_address_of_array<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">bool</span> is_lookup_of_address_of_array<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name != <span class="Constant">"address"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Identifier">return</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"array"</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Normal">bool</span> is_static_array<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// no canonize_type()</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"array"</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Comment">//: Make sure that the new system is strictly better than just the 'stash'</span> <span class="Comment">//: primitive by itself.</span> diff --git a/html/072channel.mu.html b/html/072channel.mu.html index ef0ad41b..afda2035 100644 --- a/html/072channel.mu.html +++ b/html/072channel.mu.html @@ -45,9 +45,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - <span class="Constant">3</span>:number, <span class="Constant">1</span>:address:shared:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:shared:source:number + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + <span class="Constant">3</span>:number, <span class="Constant">1</span>:address:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:source:number ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">34</span> @@ -63,99 +63,97 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:_elem + data:address:array:_elem ] <span class="Comment"># Since channels have two ends, and since it's an error to use either end from</span> <span class="Comment"># multiple routines, let's distinguish the ends.</span> <span class="muData">container</span> source:_elem [ - chan:address:shared:channel:_elem + chan:address:channel:_elem ] <span class="muData">container</span> sink:_elem [ - chan:address:shared:channel:_elem + chan:address:channel:_elem ] -<span class="muRecipe">def</span> new-channel capacity:number<span class="muRecipe"> -> </span>in:address:shared:source:_elem, out:address:shared:sink:_elem [ +<span class="muRecipe">def</span> new-channel capacity:number<span class="muRecipe"> -> </span>in:address:source:_elem, out:address:sink:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - result:address:shared:channel:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(channel _elem): type<span class="Delimiter">}</span> - <span class="Comment"># result.first-full = 0</span> - full:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">first-full:offset</span> - *full<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Comment"># result.first-free = 0</span> - free:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">first-free:offset</span> - *free<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Comment"># result.data = new location[ingredient+1]</span> + result:address:channel:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(channel _elem): type<span class="Delimiter">}</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">first-full:offset</span>, <span class="Constant">0</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">first-free:offset</span>, <span class="Constant">0</span> capacity<span class="Special"> <- </span>add capacity, <span class="Constant">1</span> <span class="Comment"># unused slot for 'full?' below</span> - dest:address:address:shared:array:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *dest<span class="Special"> <- </span>new <span class="Constant">_elem:type</span>, capacity + data:address:array:_elem<span class="Special"> <- </span>new <span class="Constant">_elem:type</span>, capacity + *result<span class="Special"> <- </span>put *result, <span class="Constant">data:offset</span>, data in<span class="Special"> <- </span>new <span class="Delimiter">{</span>(source _elem): type<span class="Delimiter">}</span> - chan:address:address:shared:channel:_elem<span class="Special"> <- </span>get-address *in, <span class="Constant">chan:offset</span> - *chan<span class="Special"> <- </span>copy result + *in<span class="Special"> <- </span>put *in, <span class="Constant">chan:offset</span>, result out<span class="Special"> <- </span>new <span class="Delimiter">{</span>(sink _elem): type<span class="Delimiter">}</span> - chan:address:address:shared:channel:_elem<span class="Special"> <- </span>get-address *out, <span class="Constant">chan:offset</span> - *chan<span class="Special"> <- </span>copy result + *out<span class="Special"> <- </span>put *out, <span class="Constant">chan:offset</span>, result ] -<span class="muRecipe">def</span> write out:address:shared:sink:_elem, val:_elem<span class="muRecipe"> -> </span>out:address:shared:sink:_elem [ +<span class="muRecipe">def</span> write out:address:sink:_elem, val:_elem<span class="muRecipe"> -> </span>out:address:sink:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - chan:address:shared:channel:_elem<span class="Special"> <- </span>get *out, <span class="Constant">chan:offset</span> + chan:address:channel:_elem<span class="Special"> <- </span>get *out, <span class="Constant">chan:offset</span> <span class="Delimiter">{</span> <span class="Comment"># block if chan is full</span> full:boolean<span class="Special"> <- </span>channel-full? chan <span class="muControl">break-unless</span> full - full-address:address:number<span class="Special"> <- </span>get-address *chan, <span class="Constant">first-full:offset</span> - wait-for-location *full-address + full-address:location<span class="Special"> <- </span>get-location *chan, <span class="Constant">first-full:offset</span> + wait-for-location full-address <span class="Delimiter">}</span> <span class="Comment"># store val</span> - circular-buffer:address:shared:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> - free:address:number<span class="Special"> <- </span>get-address *chan, <span class="Constant">first-free:offset</span> - dest:address:_elem<span class="Special"> <- </span>index-address *circular-buffer, *free - *dest<span class="Special"> <- </span>copy val + circular-buffer:address:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> + free:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-free:offset</span> + *circular-buffer<span class="Special"> <- </span>put-index *circular-buffer, free, val <span class="Comment"># mark its slot as filled</span> - *free<span class="Special"> <- </span>add *free, <span class="Constant">1</span> + <span class="Comment"># todo: clear the slot itself</span> + free<span class="Special"> <- </span>add free, <span class="Constant">1</span> <span class="Delimiter">{</span> <span class="Comment"># wrap free around to 0 if necessary</span> len:number<span class="Special"> <- </span>length *circular-buffer - at-end?:boolean<span class="Special"> <- </span>greater-or-equal *free, len + at-end?:boolean<span class="Special"> <- </span>greater-or-equal free, len <span class="muControl">break-unless</span> at-end? - *free<span class="Special"> <- </span>copy <span class="Constant">0</span> + free<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> + <span class="Comment"># write back</span> + *chan<span class="Special"> <- </span>put *chan, <span class="Constant">first-free:offset</span>, free ] -<span class="muRecipe">def</span> read in:address:shared:source:_elem<span class="muRecipe"> -> </span>result:_elem, in:address:shared:source:_elem [ +<span class="muRecipe">def</span> read in:address:source:_elem<span class="muRecipe"> -> </span>result:_elem, in:address:source:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - chan:address:shared:channel:_elem<span class="Special"> <- </span>get *in, <span class="Constant">chan:offset</span> + chan:address:channel:_elem<span class="Special"> <- </span>get *in, <span class="Constant">chan:offset</span> <span class="Delimiter">{</span> <span class="Comment"># block if chan is empty</span> empty?:boolean<span class="Special"> <- </span>channel-empty? chan <span class="muControl">break-unless</span> empty? - free-address:address:number<span class="Special"> <- </span>get-address *chan, <span class="Constant">first-free:offset</span> - wait-for-location *free-address + free-address:location<span class="Special"> <- </span>get-location *chan, <span class="Constant">first-free:offset</span> + wait-for-location free-address <span class="Delimiter">}</span> - <span class="Comment"># read result</span> - full:address:number<span class="Special"> <- </span>get-address *chan, <span class="Constant">first-full:offset</span> - circular-buffer:address:shared:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> - result<span class="Special"> <- </span>index *circular-buffer, *full + <span class="Comment"># pull result off</span> + full:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-full:offset</span> + circular-buffer:address:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> + result<span class="Special"> <- </span>index *circular-buffer, full <span class="Comment"># mark its slot as empty</span> - *full<span class="Special"> <- </span>add *full, <span class="Constant">1</span> + <span class="Comment"># todo: clear the slot itself</span> + full<span class="Special"> <- </span>add full, <span class="Constant">1</span> <span class="Delimiter">{</span> <span class="Comment"># wrap full around to 0 if necessary</span> len:number<span class="Special"> <- </span>length *circular-buffer - at-end?:boolean<span class="Special"> <- </span>greater-or-equal *full, len + at-end?:boolean<span class="Special"> <- </span>greater-or-equal full, len <span class="muControl">break-unless</span> at-end? - *full<span class="Special"> <- </span>copy <span class="Constant">0</span> + full<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">}</span> + <span class="Comment"># write back</span> + *chan<span class="Special"> <- </span>put *chan, <span class="Constant">first-full:offset</span>, full ] -<span class="muRecipe">def</span> clear in:address:shared:source:_elem<span class="muRecipe"> -> </span>in:address:shared:source:_elem [ +<span class="muRecipe">def</span> clear in:address:source:_elem<span class="muRecipe"> -> </span>in:address:source:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - chan:address:shared:channel:_elem<span class="Special"> <- </span>get *in, <span class="Constant">chan:offset</span> + chan:address:channel:_elem<span class="Special"> <- </span>get *in, <span class="Constant">chan:offset</span> <span class="Delimiter">{</span> empty?:boolean<span class="Special"> <- </span>channel-empty? chan <span class="muControl">break-if</span> empty? @@ -165,10 +163,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-initialization [ run [ - <span class="Constant">1</span>:address:shared:source:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">2</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:channel:number, <span class="Constant">first-full:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:channel:number, <span class="Constant">first-free:offset</span> + <span class="Constant">1</span>:address:source:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> + <span class="Constant">2</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:channel:number, <span class="Constant">first-full:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:channel:number, <span class="Constant">first-free:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-full</span> @@ -178,11 +176,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-write-increments-free [ run [ - _, <span class="Constant">1</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">1</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">1</span>:address:shared:sink:number, <span class="Constant">34</span> - <span class="Constant">2</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:sink:number, <span class="Constant">chan:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:channel:character, <span class="Constant">first-full:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:channel:character, <span class="Constant">first-free:offset</span> + _, <span class="Constant">1</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> + <span class="Constant">1</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">1</span>:address:sink:number, <span class="Constant">34</span> + <span class="Constant">2</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:sink:number, <span class="Constant">chan:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:channel:character, <span class="Constant">first-full:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:channel:character, <span class="Constant">first-free:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-full</span> @@ -192,12 +190,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-read-increments-full [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - _, <span class="Constant">1</span>:address:shared:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:shared:source:number - <span class="Constant">3</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:channel:number, <span class="Constant">first-full:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:channel:number, <span class="Constant">first-free:offset</span> + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + _, <span class="Constant">1</span>:address:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:source:number + <span class="Constant">3</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:channel:number, <span class="Constant">first-full:offset</span> + <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:channel:number, <span class="Constant">first-free:offset</span> ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-full</span> @@ -208,20 +206,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-wrap [ run [ <span class="Comment"># channel with just 1 slot</span> - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> - <span class="Constant">3</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> + <span class="Constant">3</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> <span class="Comment"># write and read a value</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - _, <span class="Constant">1</span>:address:shared:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:shared:source:number + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + _, <span class="Constant">1</span>:address:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:source:number <span class="Comment"># first-free will now be 1</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:channel:number, <span class="Constant">first-free:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:channel:number, <span class="Constant">first-free:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:channel:number, <span class="Constant">first-free:offset</span> + <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:channel:number, <span class="Constant">first-free:offset</span> <span class="Comment"># write second value, verify that first-free wraps</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - <span class="Constant">6</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:channel:number, <span class="Constant">first-free:offset</span> + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + <span class="Constant">6</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:channel:number, <span class="Constant">first-free:offset</span> <span class="Comment"># read second value, verify that first-full wraps</span> - _, <span class="Constant">1</span>:address:shared:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:shared:source:number - <span class="Constant">7</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:channel:number, <span class="Constant">first-full:offset</span> + _, <span class="Constant">1</span>:address:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:source:number + <span class="Constant">7</span>:number<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:channel:number, <span class="Constant">first-full:offset</span> ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-free after first write</span> @@ -234,7 +232,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="SalientComment">## helpers</span> <span class="Comment"># An empty channel has first-empty and first-full both at the same value.</span> -<span class="muRecipe">def</span> channel-empty? chan:address:shared:channel:_elem<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> channel-empty? chan:address:channel:_elem<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># return chan.first-full == chan.first-free</span> @@ -245,7 +243,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># A full channel has first-empty just before first-full, wasting one slot.</span> <span class="Comment"># (Other alternatives: <a href="https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)">https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)</a></span> -<span class="muRecipe">def</span> channel-full? chan:address:shared:channel:_elem<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> channel-full? chan:address:channel:_elem<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># tmp = chan.first-free + 1</span> @@ -263,19 +261,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color result<span class="Special"> <- </span>equal full, tmp ] -<span class="muRecipe">def</span> capacity chan:address:shared:channel:_elem<span class="muRecipe"> -> </span>result:number [ +<span class="muRecipe">def</span> capacity chan:address:channel:_elem<span class="muRecipe"> -> </span>result:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - q:address:shared:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> + q:address:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> result<span class="Special"> <- </span>length *q ] <span class="muScenario">scenario</span> channel-new-empty-not-full [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">3</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:shared:channel:number - <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:shared:channel:number + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> + <span class="Constant">3</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:channel:number + <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:channel:number ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># empty?</span> @@ -285,11 +283,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-write-not-empty [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">3</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:shared:channel:number - <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:shared:channel:number + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> + <span class="Constant">3</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:channel:number + <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:channel:number ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty?</span> @@ -299,11 +297,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-write-full [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> - <span class="Constant">3</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:shared:channel:number - <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:shared:channel:number + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> + <span class="Constant">3</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:channel:number + <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:channel:number ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty?</span> @@ -313,12 +311,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> channel-read-not-full [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> - <span class="Constant">3</span>:address:shared:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:number, <span class="Constant">34</span> - _, <span class="Constant">1</span>:address:shared:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:shared:source:number - <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:shared:channel:number - <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:shared:channel:number + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> + <span class="Constant">3</span>:address:channel:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:number, <span class="Constant">34</span> + _, <span class="Constant">1</span>:address:source:number<span class="Special"> <- </span>read <span class="Constant">1</span>:address:source:number + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">3</span>:address:channel:number + <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">3</span>:address:channel:number ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># empty?</span> @@ -327,12 +325,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># helper for channels of characters in particular</span> -<span class="muRecipe">def</span> buffer-lines in:address:shared:source:character, buffered-out:address:shared:sink:character<span class="muRecipe"> -> </span>buffered-out:address:shared:sink:character, in:address:shared:source:character [ +<span class="muRecipe">def</span> buffer-lines in:address:source:character, buffered-out:address:sink:character<span class="muRecipe"> -> </span>buffered-out:address:sink:character, in:address:source:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># repeat forever</span> <span class="Delimiter">{</span> - line:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">30</span> + line:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">30</span> <span class="Comment"># read characters from 'in' until newline, copy into line</span> <span class="Delimiter">{</span> <span class="Constant"> +next-character</span> @@ -344,10 +342,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> backspace? <span class="Comment"># drop previous character</span> <span class="Delimiter">{</span> - buffer-length:address:number<span class="Special"> <- </span>get-address *line, <span class="Constant">length:offset</span> - buffer-empty?:boolean<span class="Special"> <- </span>equal *buffer-length, <span class="Constant">0</span> + buffer-length:number<span class="Special"> <- </span>get *line, <span class="Constant">length:offset</span> + buffer-empty?:boolean<span class="Special"> <- </span>equal buffer-length, <span class="Constant">0</span> <span class="muControl">break-if</span> buffer-empty? - *buffer-length<span class="Special"> <- </span>subtract *buffer-length, <span class="Constant">1</span> + buffer-length<span class="Special"> <- </span>subtract buffer-length, <span class="Constant">1</span> + *line<span class="Special"> <- </span>put *line, <span class="Constant">length:offset</span>, buffer-length <span class="Delimiter">}</span> <span class="Comment"># and don't append this one</span> <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> @@ -363,7 +362,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Comment"># copy line into 'buffered-out'</span> i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - line-contents:address:shared:array:character<span class="Special"> <- </span>get *line, <span class="Constant">data:offset</span> + line-contents:address:array:character<span class="Special"> <- </span>get *line, <span class="Constant">data:offset</span> max:number<span class="Special"> <- </span>get *line, <span class="Constant">length:offset</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>greater-or-equal i, max @@ -379,37 +378,37 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> buffer-lines-blocks-until-newline [ run [ - <span class="Constant">1</span>:address:shared:source:number, <span class="Constant">2</span>:address:shared:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> - _, <span class="Constant">3</span>:address:shared:sink:number/buffered-stdin<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> - <span class="Constant">4</span>:address:shared:channel:number/buffered-stdin<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:source:number, <span class="Constant">chan:offset</span> - <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:shared:channel:character/buffered-stdin + <span class="Constant">1</span>:address:source:number, <span class="Constant">2</span>:address:sink:number<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> + _, <span class="Constant">3</span>:address:sink:number/buffered-stdin<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> + <span class="Constant">4</span>:address:channel:number/buffered-stdin<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:source:number, <span class="Constant">chan:offset</span> + <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:channel:character/buffered-stdin assert <span class="Constant">5</span>:boolean, <span class="Constant">[ </span> <span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after init]</span> <span class="Comment"># buffer stdin into buffered-stdin, try to read from buffered-stdin</span> - <span class="Constant">6</span>:number/buffer-routine<span class="Special"> <- </span>start-running buffer-lines, <span class="Constant">1</span>:address:shared:source:character/stdin, <span class="Constant">3</span>:address:shared:sink:character/buffered-stdin + <span class="Constant">6</span>:number/buffer-routine<span class="Special"> <- </span>start-running buffer-lines, <span class="Constant">1</span>:address:source:character/stdin, <span class="Constant">3</span>:address:sink:character/buffered-stdin wait-for-routine <span class="Constant">6</span>:number/buffer-routine - <span class="Constant">7</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:shared:channel:character/buffered-stdin + <span class="Constant">7</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:channel:character/buffered-stdin assert <span class="Constant">7</span>:boolean, <span class="Constant">[ </span> <span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after buffer-lines bring-up]</span> <span class="Comment"># write 'a'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">97/a</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">97/a</span> restart <span class="Constant">6</span>:number/buffer-routine wait-for-routine <span class="Constant">6</span>:number/buffer-routine - <span class="Constant">8</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:shared:channel:character/buffered-stdin + <span class="Constant">8</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:channel:character/buffered-stdin assert <span class="Constant">8</span>:boolean, <span class="Constant">[ </span> <span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']</span> <span class="Comment"># write 'b'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">98/b</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">98/b</span> restart <span class="Constant">6</span>:number/buffer-routine wait-for-routine <span class="Constant">6</span>:number/buffer-routine - <span class="Constant">9</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:shared:channel:character/buffered-stdin + <span class="Constant">9</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:channel:character/buffered-stdin assert <span class="Constant">9</span>:boolean, <span class="Constant">[ </span> <span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']</span> <span class="Comment"># write newline</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">10/newline</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">10/newline</span> restart <span class="Constant">6</span>:number/buffer-routine wait-for-routine <span class="Constant">6</span>:number/buffer-routine - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:shared:channel:character/buffered-stdin + <span class="Constant">10</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">4</span>:address:channel:character/buffered-stdin <span class="Constant">11</span>:boolean/completed?<span class="Special"> <- </span>not <span class="Constant">10</span>:boolean assert <span class="Constant">11</span>:boolean/completed?, <span class="Constant">[ </span> <span class="Constant">F buffer-lines-blocks-until-newline: channel should contain data after writing newline]</span> diff --git a/html/073array.mu.html b/html/073array.mu.html index 8cafa8d5..433e2044 100644 --- a/html/073array.mu.html +++ b/html/073array.mu.html @@ -33,8 +33,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <pre id='vimCodeElement'> <span class="muScenario">scenario</span> array-from-args [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </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"> <- </span>copy *<span class="Constant">1</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </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"> <- </span>copy *<span class="Constant">1</span>:address:array:character ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># array length</span> @@ -45,7 +45,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># create an array out of a list of scalar args</span> -<span class="muRecipe">def</span> new-array<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> new-array<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> capacity:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> @@ -56,7 +56,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">loop</span> <span class="Delimiter">}</span> result<span class="Special"> <- </span>new <span class="Constant">character:type</span>, capacity - rewind-ingredients + <span class="Constant">rewind-ingredients</span> i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while read curr-value</span> @@ -64,8 +64,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> done? curr-value:character, exists?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> assert exists?, <span class="Constant">[error in rewinding ingredients to new-array]</span> - tmp:address:character<span class="Special"> <- </span>index-address *result, i - *tmp<span class="Special"> <- </span>copy curr-value + *result<span class="Special"> <- </span>put-index *result, i, curr-value i<span class="Special"> <- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> diff --git a/html/074list.mu.html b/html/074list.mu.html index 76b64ad5..bb619f3e 100644 --- a/html/074list.mu.html +++ b/html/074list.mu.html @@ -39,27 +39,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> list:_elem [ value:_elem - next:address:shared:list:_elem + next:address:list:_elem ] -<span class="muRecipe">def</span> push x:_elem, in:address:shared:list:_elem<span class="muRecipe"> -> </span>in:address:shared:list:_elem [ +<span class="muRecipe">def</span> push x:_elem, in:address:list:_elem<span class="muRecipe"> -> </span>in:address:list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - result:address:shared:list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> - val:address:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">value:offset</span> - *val<span class="Special"> <- </span>copy x - next:address:address:shared:list:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">next:offset</span> - *next<span class="Special"> <- </span>copy in + result:address:list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> + *result<span class="Special"> <- </span>merge x, in <span class="muControl">return</span> result <span class="Comment"># needed explicitly because we need to replace 'in' with 'result'</span> ] -<span class="muRecipe">def</span> first in:address:shared:list:_elem<span class="muRecipe"> -> </span>result:_elem [ +<span class="muRecipe">def</span> first in:address:list:_elem<span class="muRecipe"> -> </span>result:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> ] -<span class="muRecipe">def</span> rest in:address:shared:list:_elem<span class="muRecipe"> -> </span>result:address:shared:list:_elem/contained-in:in [ +<span class="muRecipe">def</span> rest in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem/contained-in:in [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> @@ -67,15 +64,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> list-handling [ run [ - <span class="Constant">1</span>:address:shared:list:number<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:list:number<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">1</span>:address:shared:list:number<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">2</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">1</span>:address:shared:list:number<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">1</span>:address:shared:list:number<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">4</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:shared:list:number - <span class="Constant">1</span>:address:shared:list:number<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:shared:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:list:number<span class="Special"> <- </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"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:list:number + <span class="Constant">2</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:list:number + <span class="Constant">3</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:list:number + <span class="Constant">4</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:list:number + <span class="Constant">1</span>:address:list:number<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:list:number ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty to empty, dust to dust..</span> @@ -85,24 +82,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> to-text in:address:shared:list:_elem<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> to-text in:address:list:_elem<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - buf:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> + buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> buf<span class="Special"> <- </span>to-buffer in, buf result<span class="Special"> <- </span>buffer-to-array buf ] <span class="Comment"># variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)</span> -<span class="muRecipe">def</span> to-text-line in:address:shared:list:_elem<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> to-text-line in:address:list:_elem<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - buf:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> + buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> buf<span class="Special"> <- </span>to-buffer in, buf, <span class="Constant">6</span> <span class="Comment"># max elements to display</span> result<span class="Special"> <- </span>buffer-to-array buf ] -<span class="muRecipe">def</span> to-buffer in:address:shared:list:_elem, buf:address:shared:buffer<span class="muRecipe"> -> </span>buf:address:shared:buffer [ +<span class="muRecipe">def</span> to-buffer in:address:list:_elem, buf:address:buffer<span class="muRecipe"> -> </span>buf:address:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -114,7 +111,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color val:_elem<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> buf<span class="Special"> <- </span>append buf, val <span class="Comment"># now prepare next</span> - next:address:shared:list:_elem<span class="Special"> <- </span>rest in + next:address:list:_elem<span class="Special"> <- </span>rest in nextn:number<span class="Special"> <- </span>copy next <span class="muControl">return-unless</span> next buf<span class="Special"> <- </span>append buf, <span class="Constant">[ -> ]</span> diff --git a/html/076duplex_list.mu.html b/html/076duplex_list.mu.html index 5b3e3b78..aebf00dd 100644 --- a/html/076duplex_list.mu.html +++ b/html/076duplex_list.mu.html @@ -36,42 +36,38 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> duplex-list:_elem [ value:_elem - next:address:shared:duplex-list:_elem - prev:address:shared:duplex-list:_elem + next:address:duplex-list:_elem + prev:address:duplex-list:_elem ] <span class="Comment"># should I say in/contained-in:result, allow ingredients to refer to products?</span> -<span class="muRecipe">def</span> push x:_elem, in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> push x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - result:address:shared:duplex-list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> - val:address:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">value:offset</span> - *val<span class="Special"> <- </span>copy x - next:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">next:offset</span> - *next<span class="Special"> <- </span>copy in + result:address:duplex-list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> + *result<span class="Special"> <- </span>merge x, in, <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> in - prev:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *in, <span class="Constant">prev:offset</span> - *prev<span class="Special"> <- </span>copy result + *in<span class="Special"> <- </span>put *in, <span class="Constant">prev:offset</span>, result <span class="Delimiter">}</span> <span class="muControl">return</span> result <span class="Comment"># needed explicitly because we need to replace 'in' with 'result'</span> ] -<span class="muRecipe">def</span> first in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>result:_elem [ +<span class="muRecipe">def</span> first in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> in, <span class="Constant">0</span> result<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> ] -<span class="muRecipe">def</span> next in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:shared:duplex-list:_elem/contained-in:in [ +<span class="muRecipe">def</span> next in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem/contained-in:in [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> in, <span class="Constant">0</span> result<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> ] -<span class="muRecipe">def</span> prev in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:shared:duplex-list:_elem/contained-in:in [ +<span class="muRecipe">def</span> prev in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem/contained-in:in [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> in, <span class="Constant">0</span> @@ -84,24 +80,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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"> <- </span>copy <span class="Constant">34</span> <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">3</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">3</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:address:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">3</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">8</span>:address:shared:duplex-list:character - <span class="Constant">10</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">8</span>:address:shared:duplex-list:character - <span class="Constant">11</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">8</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">12</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">13</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:shared:duplex-list:character - <span class="Constant">14</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">3</span>:address:shared:duplex-list:character, <span class="Constant">4</span>:address:shared:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>copy <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">8</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">8</span>:address:duplex-list:character + <span class="Constant">10</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">8</span>:address:duplex-list:character + <span class="Constant">11</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">8</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">12</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">13</span>:character<span class="Special"> <- </span>first <span class="Constant">4</span>:address:duplex-list:character + <span class="Constant">14</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">0</span> <span class="Comment"># no modifications to null pointers</span> @@ -121,52 +117,43 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># insert 'x' after 'in'</span> -<span class="muRecipe">def</span> insert x:_elem, in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> insert x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - new-node:address:shared:duplex-list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> - val:address:_elem<span class="Special"> <- </span>get-address *new-node, <span class="Constant">value:offset</span> - *val<span class="Special"> <- </span>copy x - next-node:address:shared:duplex-list:_elem<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> - <span class="Comment"># in.next = new-node</span> - y:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *in, <span class="Constant">next:offset</span> - *y<span class="Special"> <- </span>copy new-node - <span class="Comment"># new-node.prev = in</span> - y<span class="Special"> <- </span>get-address *new-node, <span class="Constant">prev:offset</span> - *y<span class="Special"> <- </span>copy in - <span class="Comment"># new-node.next = next-node</span> - y<span class="Special"> <- </span>get-address *new-node, <span class="Constant">next:offset</span> - *y<span class="Special"> <- </span>copy next-node - <span class="Comment"># if next-node is not null</span> + new-node:address:duplex-list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> + *new-node<span class="Special"> <- </span>put *new-node, <span class="Constant">value:offset</span>, x + <span class="Comment"># save old next before changing it</span> + next-node:address:duplex-list:_elem<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> + *in<span class="Special"> <- </span>put *in, <span class="Constant">next:offset</span>, new-node + *new-node<span class="Special"> <- </span>put *new-node, <span class="Constant">prev:offset</span>, in + *new-node<span class="Special"> <- </span>put *new-node, <span class="Constant">next:offset</span>, next-node <span class="muControl">return-unless</span> next-node - <span class="Comment"># next-node.prev = new-node</span> - y<span class="Special"> <- </span>get-address *next-node, <span class="Constant">prev:offset</span> - *y<span class="Special"> <- </span>copy new-node + *next-node<span class="Special"> <- </span>put *next-node, <span class="Constant">prev:offset</span>, new-node ] <span class="muScenario">scenario</span> inserting-into-duplex-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character <span class="Comment"># 2 points inside list</span> - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>insert <span class="Constant">6</span>, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>next <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"> <- </span>insert <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:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">10</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> @@ -182,28 +169,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> inserting-at-end-of-duplex-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character <span class="Comment"># 2 points inside list</span> - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character <span class="Comment"># now at end of list</span> - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>insert <span class="Constant">6</span>, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>next <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"> <- </span>next <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"> <- </span>insert <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:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">10</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> @@ -219,26 +206,26 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> inserting-after-start-of-duplex-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>insert <span class="Constant">6</span>, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>insert <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:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">9</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">10</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> @@ -256,53 +243,49 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">#</span> <span class="Comment"># Returns null if and only if list is empty. Beware: in that case any other</span> <span class="Comment"># pointers to the head are now invalid.</span> -<span class="muRecipe">def</span> remove x:address:shared:duplex-list:_elem/contained-in:in, in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> remove x:address:duplex-list:_elem/contained-in:in, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if 'x' is null, return</span> <span class="muControl">return-unless</span> x - next-node:address:shared:duplex-list:_elem<span class="Special"> <- </span>get *x, <span class="Constant">next:offset</span> - prev-node:address:shared:duplex-list:_elem<span class="Special"> <- </span>get *x, <span class="Constant">prev:offset</span> + next-node:address:duplex-list:_elem<span class="Special"> <- </span>get *x, <span class="Constant">next:offset</span> + prev-node:address:duplex-list:_elem<span class="Special"> <- </span>get *x, <span class="Constant">prev:offset</span> <span class="Comment"># null x's pointers</span> - tmp:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *x, <span class="Constant">next:offset</span> - *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> - tmp<span class="Special"> <- </span>get-address *x, <span class="Constant">prev:offset</span> - *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> + *x<span class="Special"> <- </span>put *x, <span class="Constant">next:offset</span>, <span class="Constant">0</span> + *x<span class="Special"> <- </span>put *x, <span class="Constant">prev:offset</span>, <span class="Constant">0</span> <span class="Comment"># if next-node is not null, set its prev pointer</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> next-node - tmp<span class="Special"> <- </span>get-address *next-node, <span class="Constant">prev:offset</span> - *tmp<span class="Special"> <- </span>copy prev-node + *next-node<span class="Special"> <- </span>put *next-node, <span class="Constant">prev:offset</span>, prev-node <span class="Delimiter">}</span> <span class="Comment"># if prev-node is not null, set its next pointer and return</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> prev-node - tmp<span class="Special"> <- </span>get-address *prev-node, <span class="Constant">next:offset</span> - *tmp<span class="Special"> <- </span>copy next-node + *prev-node<span class="Special"> <- </span>put *prev-node, <span class="Constant">next:offset</span>, next-node <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># if prev-node is null, then we removed the node at 'in'</span> + <span class="Comment"># if prev-node is null, then we removed the head node at 'in'</span> <span class="Comment"># return the new head rather than the old 'in'</span> <span class="muControl">return</span> next-node ] <span class="muScenario">scenario</span> removing-from-duplex-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character <span class="Comment"># 2 points at second element</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:shared:duplex-list:character, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:shared:duplex-list:character, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># 2 points at second element</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:boolean<span class="Special"> <- </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:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">0</span> <span class="Comment"># remove returned non-null</span> @@ -316,19 +299,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> removing-from-start-of-duplex-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">4</span> <span class="Comment"># scanning next, skipping deleted element</span> @@ -341,23 +324,23 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> removing-from-end-of-duplex-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:shared:duplex-list:character, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:shared:duplex-list:character, <span class="Constant">0</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">3</span>:boolean<span class="Special"> <- </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:shared:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">5</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">6</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>prev <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">7</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">8</span>:boolean<span class="Special"> <- </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"> <- </span><span class="Constant">0</span> <span class="Comment"># remove returned non-null</span> @@ -371,58 +354,60 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> removing-from-singleton-list [ run [ - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># back to an empty list</span> ] ] -<span class="Comment"># remove values between 'start' and 'end' (both exclusive)</span> -<span class="Comment"># also clear pointers back out from start/end for hygiene</span> -<span class="muRecipe">def</span> remove-between start:address:shared:duplex-list:_elem, end:address:shared:duplex-list:_elem/contained-in:start<span class="muRecipe"> -> </span>start:address:shared:duplex-list:_elem [ +<span class="Comment"># remove values between 'start' and 'end' (both exclusive).</span> +<span class="Comment"># also clear pointers back out from start/end for hygiene.</span> +<span class="Comment"># set end to 0 to delete everything past start.</span> +<span class="Comment"># can't set start to 0 to delete everything before end, because there's no</span> +<span class="Comment"># clean way to return the new head pointer.</span> +<span class="muRecipe">def</span> remove-between start:address:duplex-list:_elem, end:address:duplex-list:_elem/contained-in:start<span class="muRecipe"> -> </span>start:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="muControl">return-unless</span> start + next:address:duplex-list:_elem<span class="Special"> <- </span>get *start, <span class="Constant">next:offset</span> + nothing-to-delete?:boolean<span class="Special"> <- </span>equal next, end + <span class="muControl">return-if</span> nothing-to-delete? + assert next, <span class="Constant">[malformed duplex list]</span> <span class="Comment"># start->next->prev = 0</span> <span class="Comment"># start->next = end</span> - next:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *start, <span class="Constant">next:offset</span> - nothing-to-delete?:boolean<span class="Special"> <- </span>equal *next, end - <span class="muControl">return-if</span> nothing-to-delete? - prev:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address **next, <span class="Constant">prev:offset</span> - *prev<span class="Special"> <- </span>copy <span class="Constant">0</span> - *next<span class="Special"> <- </span>copy end + *next<span class="Special"> <- </span>put *next, <span class="Constant">prev:offset</span>, <span class="Constant">0</span> + *start<span class="Special"> <- </span>put *start, <span class="Constant">next:offset</span>, end <span class="muControl">return-unless</span> end <span class="Comment"># end->prev->next = 0</span> <span class="Comment"># end->prev = start</span> - prev<span class="Special"> <- </span>get-address *end, <span class="Constant">prev:offset</span> - next<span class="Special"> <- </span>get-address **prev, <span class="Constant">next:offset</span> - *next<span class="Special"> <- </span>copy <span class="Constant">0</span> - *prev<span class="Special"> <- </span>copy start + prev:address:duplex-list:_elem<span class="Special"> <- </span>get *end, <span class="Constant">prev:offset</span> + assert prev, <span class="Constant">[malformed duplex list - 2]</span> + *prev<span class="Special"> <- </span>put *prev, <span class="Constant">next:offset</span>, <span class="Constant">0</span> + *end<span class="Special"> <- </span>put *end, <span class="Constant">prev:offset</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:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">18</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">17</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">16</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">15</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">14</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">13</span>, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">18</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">2</span>:address:shared:duplex-list:character<span class="Special"> <- </span>remove-between <span class="Constant">2</span>:address:shared:duplex-list:character, <span class="Constant">0</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>remove-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>:character<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">5</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>get *<span class="Constant">5</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">7</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">5</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:character<span class="Special"> <- </span>get *<span class="Constant">7</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">9</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">7</span>:address:shared:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">5</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">7</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">13</span> @@ -432,31 +417,31 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muScenario">scenario</span> remove-range-to-end [ +<span class="muScenario">scenario</span> remove-range-to-final [ <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">18</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">17</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">16</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">15</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">14</span>, <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">13</span>, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">18</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Comment"># second pointer: to the fifth element</span> - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">3</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">3</span>:address:shared:duplex-list:character - <span class="Constant">3</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">3</span>:address:shared:duplex-list:character - remove-between <span class="Constant">2</span>:address:shared:duplex-list:character, <span class="Constant">3</span>:address:shared:duplex-list:character + <span class="Comment"># start pointer: to the second element</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Comment"># end pointer: to the last (sixth) element</span> + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">3</span>:address:duplex-list:character + <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">3</span>:address:duplex-list:character + remove-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>:character<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">5</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>get *<span class="Constant">5</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">7</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">5</span>:address:shared:duplex-list:character - <span class="Constant">8</span>:character<span class="Special"> <- </span>get *<span class="Constant">7</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">9</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">7</span>:address:shared:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">5</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">7</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">13</span> @@ -467,19 +452,48 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muScenario">scenario</span> remove-range-empty [ + <span class="Comment"># construct a duplex list with three elements [13, 14, 15]</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">15</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list:character + run [ + <span class="Comment"># delete between first and second element (i.e. nothing)</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + remove-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>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">5</span>:address:duplex-list:character + <span class="Constant">8</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">7</span>:address:duplex-list:character + ] + <span class="Comment"># no change</span> + memory-should-contain [ + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">13</span> + <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">14</span> + <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">15</span> + <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">0</span> + ] +] + +<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:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">14</span>, <span class="Constant">0</span> - <span class="Constant">1</span>:address:shared:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">13</span>, <span class="Constant">1</span>:address:shared:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">18</span>, <span class="Constant">0</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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"> <- </span>push <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:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - remove-between <span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">2</span>:address:shared:duplex-list:character + <span class="Comment"># remove the third element and beyond</span> + <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + remove-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>:character<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">5</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:shared:duplex-list:character - <span class="Constant">6</span>:character<span class="Special"> <- </span>get *<span class="Constant">5</span>:address:shared:duplex-list:character, <span class="Constant">value:offset</span> - <span class="Constant">7</span>:address:shared:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">5</span>:address:shared:duplex-list:character + <span class="Constant">4</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">6</span>:character<span class="Special"> <- </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"> <- </span>next <span class="Constant">5</span>:address:duplex-list:character ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">13</span> @@ -489,49 +503,43 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># insert list beginning at 'new' after 'in'</span> -<span class="muRecipe">def</span> insert-range in:address:shared:duplex-list:_elem, start:address:shared:duplex-list:_elem/contained-in:in<span class="muRecipe"> -> </span>in:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem/contained-in:in<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> in <span class="muControl">return-unless</span> start - end:address:shared:duplex-list:_elem<span class="Special"> <- </span>copy start + end:address:duplex-list:_elem<span class="Special"> <- </span>copy start <span class="Delimiter">{</span> - next:address:shared:duplex-list:_elem<span class="Special"> <- </span>next end/insert-range + next:address:duplex-list:_elem<span class="Special"> <- </span>next end/insert-range <span class="muControl">break-unless</span> next end<span class="Special"> <- </span>copy next <span class="muControl">loop</span> <span class="Delimiter">}</span> - next:address:shared:duplex-list:_elem<span class="Special"> <- </span>next in - dest:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *end, <span class="Constant">next:offset</span> - *dest<span class="Special"> <- </span>copy next + next:address:duplex-list:_elem<span class="Special"> <- </span>next in + *end<span class="Special"> <- </span>put *end, <span class="Constant">next:offset</span>, next <span class="Delimiter">{</span> <span class="muControl">break-unless</span> next - dest<span class="Special"> <- </span>get-address *next, <span class="Constant">prev:offset</span> - *dest<span class="Special"> <- </span>copy end + *next<span class="Special"> <- </span>put *next, <span class="Constant">prev:offset</span>, end <span class="Delimiter">}</span> - dest<span class="Special"> <- </span>get-address *in, <span class="Constant">next:offset</span> - *dest<span class="Special"> <- </span>copy start - dest<span class="Special"> <- </span>get-address *start, <span class="Constant">prev:offset</span> - *dest<span class="Special"> <- </span>copy in + *in<span class="Special"> <- </span>put *in, <span class="Constant">next:offset</span>, start + *start<span class="Special"> <- </span>put *start, <span class="Constant">prev:offset</span>, in ] -<span class="muRecipe">def</span> append in:address:shared:duplex-list:_elem, new:address:shared:duplex-list:_elem/contained-in:in<span class="muRecipe"> -> </span>in:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> append in:address:duplex-list:_elem, new:address:duplex-list:_elem/contained-in:in<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - last:address:shared:duplex-list:_elem<span class="Special"> <- </span>last in - dest:address:address:shared:duplex-list:_elem<span class="Special"> <- </span>get-address *last, <span class="Constant">next:offset</span> - *dest<span class="Special"> <- </span>copy new + last:address:duplex-list:_elem<span class="Special"> <- </span>last in + *last<span class="Special"> <- </span>put *last, <span class="Constant">next:offset</span>, new <span class="muControl">return-unless</span> new - dest<span class="Special"> <- </span>get-address *new, <span class="Constant">prev:offset</span> - *dest<span class="Special"> <- </span>copy last + *new<span class="Special"> <- </span>put *new, <span class="Constant">prev:offset</span>, last ] -<span class="muRecipe">def</span> last in:address:shared:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> last in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>copy in <span class="Delimiter">{</span> - next:address:shared:duplex-list:_elem<span class="Special"> <- </span>next result + next:address:duplex-list:_elem<span class="Special"> <- </span>next result <span class="muControl">break-unless</span> next result<span class="Special"> <- </span>copy next <span class="muControl">loop</span> @@ -539,7 +547,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># helper for debugging</span> -<span class="muRecipe">def</span> dump-from x:address:shared:duplex-list:_elem [ +<span class="muRecipe">def</span> dump-from x:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> $print x, <span class="Constant">[: ]</span> diff --git a/html/077stream.mu.html b/html/077stream.mu.html index 5bf82f66..9fcfa379 100644 --- a/html/077stream.mu.html +++ b/html/077stream.mu.html @@ -32,41 +32,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># new type to help incrementally read texts (arrays of characters)</span> <span class="muData">container</span> stream [ index:number - data:address:shared:array:character + data:address:array:character ] -<span class="muRecipe">def</span> new-stream s:address:shared:array:character<span class="muRecipe"> -> </span>result:address:shared:stream [ +<span class="muRecipe">def</span> new-stream s:address:array:character<span class="muRecipe"> -> </span>result:address:stream [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>new <span class="Constant">stream:type</span> - i:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">index:offset</span> - *i<span class="Special"> <- </span>copy <span class="Constant">0</span> - d:address:address:shared:array:character<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *d<span class="Special"> <- </span>copy s + *result<span class="Special"> <- </span>put *result, <span class="Constant">index:offset</span>, <span class="Constant">0</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">data:offset</span>, s ] -<span class="muRecipe">def</span> rewind-stream in:address:shared:stream<span class="muRecipe"> -> </span>in:address:shared:stream [ +<span class="muRecipe">def</span> rewind-stream in:address:stream<span class="muRecipe"> -> </span>in:address:stream [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - x:address:number<span class="Special"> <- </span>get-address *in, <span class="Constant">index:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">0</span> + *in<span class="Special"> <- </span>put *in, <span class="Constant">index:offset</span>, <span class="Constant">0</span> ] -<span class="muRecipe">def</span> read-line in:address:shared:stream<span class="muRecipe"> -> </span>result:address:shared:array:character, in:address:shared:stream [ +<span class="muRecipe">def</span> read-line in:address:stream<span class="muRecipe"> -> </span>result:address:array:character, in:address:stream [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - idx:address:number<span class="Special"> <- </span>get-address *in, <span class="Constant">index:offset</span> - s:address:shared:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> - next-idx:number<span class="Special"> <- </span>find-next s, <span class="Constant">10/newline</span>, *idx - result<span class="Special"> <- </span>copy-range s, *idx, next-idx - *idx<span class="Special"> <- </span>add next-idx, <span class="Constant">1</span> <span class="Comment"># skip newline</span> + idx:number<span class="Special"> <- </span>get *in, <span class="Constant">index:offset</span> + s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + next-idx:number<span class="Special"> <- </span>find-next s, <span class="Constant">10/newline</span>, idx + result<span class="Special"> <- </span>copy-range s, idx, next-idx + idx<span class="Special"> <- </span>add next-idx, <span class="Constant">1</span> <span class="Comment"># skip newline</span> + <span class="Comment"># write back</span> + *in<span class="Special"> <- </span>put *in, <span class="Constant">index:offset</span>, idx ] -<span class="muRecipe">def</span> end-of-stream? in:address:shared:stream<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> end-of-stream? in:address:stream<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> idx:number<span class="Special"> <- </span>get *in, <span class="Constant">index:offset</span> - s:address:shared:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> len:number<span class="Special"> <- </span>length *s result<span class="Special"> <- </span>greater-or-equal idx, len ] diff --git a/html/078hash.cc.html b/html/078hash.cc.html index 02349fc2..0f3153f7 100644 --- a/html/078hash.cc.html +++ b/html/078hash.cc.html @@ -90,12 +90,13 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">size_t</span> hash_mu_address<span class="Delimiter">(</span><span class="Normal">size_t</span> h<span class="Delimiter">,</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"location "</span> << r<span class="Delimiter">.</span>value << <span class="Constant">" is "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> r<span class="Delimiter">.</span>value<span class="Delimiter">))</span> << end<span class="Delimiter">();</span> r<span class="Delimiter">.</span>value = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> r<span class="Delimiter">.</span>value<span class="Delimiter">);</span> - drop_from_type<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"shared"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - ++r<span class="Delimiter">.</span>value<span class="Delimiter">;</span> - drop_from_type<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"shared"</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>value != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"skipping refcount at "</span> << r<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>r<span class="Delimiter">.</span>value+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// skip refcount</span> <span class="Delimiter">}</span> + drop_from_type<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">);</span> <span class="Identifier">return</span> hash<span class="Delimiter">(</span>h<span class="Delimiter">,</span> r<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -256,8 +257,8 @@ def main [ <span class="Constant">13</span>:number<span class="Special"> <- </span>copy <span class="Constant">99</span> <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">10</span>:array:number/unsafe <span class="Identifier">return</span>-unless <span class="Constant">2</span>:number - <span class="Constant">3</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - <span class="Constant">4</span>:number<span class="Special"> <- </span>hash <span class="Constant">3</span>:address:shared:array:character + <span class="Constant">3</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + <span class="Constant">4</span>:number<span class="Special"> <- </span>hash <span class="Constant">3</span>:address:array:character <span class="Identifier">return</span>-unless <span class="Constant">4</span>:number <span class="Constant">5</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number ] @@ -265,12 +266,12 @@ def main [ <span class="Delimiter">:(scenario hash_ignores_address_value)</span> def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - *<span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">1</span>:address:shared:number - <span class="Constant">3</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - *<span class="Constant">3</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>hash <span class="Constant">3</span>:address:shared:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *<span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">1</span>:address:number + <span class="Constant">3</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *<span class="Constant">3</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>hash <span class="Constant">3</span>:address:number <span class="Constant">5</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number ] <span class="Comment"># different addresses hash to the same result as long as the values the point to do so</span> @@ -278,13 +279,13 @@ def main [ <span class="Delimiter">:(scenario hash_ignores_address_refcount)</span> def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - *<span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">1</span>:address:shared:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *<span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">1</span>:address:number <span class="Identifier">return</span>-unless <span class="Constant">2</span>:number <span class="Comment"># increment refcount</span> - <span class="Constant">3</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:shared:number - <span class="Constant">4</span>:number<span class="Special"> <- </span>hash <span class="Constant">3</span>:address:shared:number + <span class="Constant">3</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:number + <span class="Constant">4</span>:number<span class="Special"> <- </span>hash <span class="Constant">3</span>:address:number <span class="Identifier">return</span>-unless <span class="Constant">4</span>:number <span class="Constant">5</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number ] @@ -316,17 +317,17 @@ def main [ container foo [ <span class="Normal">x</span>:number <span class="Normal">y</span>:character - <span class="Normal">z</span>:address:shared:number + <span class="Normal">z</span>:address:number ] def main [ - <span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - *<span class="Constant">1</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">2</span>:foo<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">1</span>:address:shared:number + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *<span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:foo<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">1</span>:address:number <span class="Constant">5</span>:number<span class="Special"> <- </span>hash <span class="Constant">2</span>:foo <span class="Identifier">return</span>-unless <span class="Constant">5</span>:number - <span class="Constant">6</span>:address:shared:number<span class="Special"> <- </span><span class="Normal">new</span> number:type - *<span class="Constant">6</span>:address:shared:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - <span class="Constant">7</span>:foo<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">6</span>:address:shared:number + <span class="Constant">6</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *<span class="Constant">6</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">7</span>:foo<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">97</span>/a<span class="Delimiter">,</span> <span class="Constant">6</span>:address:number <span class="Constant">10</span>:number<span class="Special"> <- </span>hash <span class="Constant">7</span>:foo <span class="Identifier">return</span>-unless <span class="Constant">10</span>:number <span class="Constant">11</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">5</span>:number<span class="Delimiter">,</span> <span class="Constant">10</span>:number @@ -383,9 +384,9 @@ def main [ <span class="Delimiter">:(scenario hash_matches_old_version)</span> def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] - <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:number<span class="Special"> <- </span>hash_old <span class="Constant">1</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + <span class="Constant">2</span>:number<span class="Special"> <- </span>hash <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:number<span class="Special"> <- </span>hash_old <span class="Constant">1</span>:address:array:character <span class="Constant">4</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span>:number ] <span class="traceContains">+mem: storing 1 in location 4</span> @@ -401,7 +402,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'hash_old' currently only supports strings (address:shared:array:character), but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'hash_old' currently only supports strings (address:array:character), but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> diff --git a/html/079table.mu.html b/html/079table.mu.html index ab009967..76d97082 100644 --- a/html/079table.mu.html +++ b/html/079table.mu.html @@ -37,9 +37,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> table-read-write [ run [ - <span class="Constant">1</span>:address:shared:table:number:number<span class="Special"> <- </span>new-table <span class="Constant">30</span> - put <span class="Constant">1</span>:address:shared:table:number:number, <span class="Constant">12</span>, <span class="Constant">34</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>index <span class="Constant">1</span>:address:shared:table:number:number, <span class="Constant">12</span> + <span class="Constant">1</span>:address:table:number:number<span class="Special"> <- </span>new-table <span class="Constant">30</span> + put <span class="Constant">1</span>:address:table:number:number, <span class="Constant">12</span>, <span class="Constant">34</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>index <span class="Constant">1</span>:address:table:number:number, <span class="Constant">12</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">34</span> @@ -48,10 +48,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> table-read-write-non-integer [ run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def]</span> - <span class="Delimiter">{</span><span class="Constant">2</span>: (address shared table (address shared array character) number)<span class="Delimiter">}</span><span class="Special"> <- </span>new-table <span class="Constant">30</span> - put <span class="Delimiter">{</span><span class="Constant">2</span>: (address shared table (address shared array character) number)<span class="Delimiter">}</span>, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">34</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>index <span class="Delimiter">{</span><span class="Constant">2</span>: (address shared table (address shared array character) number)<span class="Delimiter">}</span>, <span class="Constant">1</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def]</span> + <span class="Delimiter">{</span><span class="Constant">2</span>: (address table (address array character) number)<span class="Delimiter">}</span><span class="Special"> <- </span>new-table <span class="Constant">30</span> + put <span class="Delimiter">{</span><span class="Constant">2</span>: (address table (address array character) number)<span class="Delimiter">}</span>, <span class="Constant">1</span>:address:array:character, <span class="Constant">34</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>index <span class="Delimiter">{</span><span class="Constant">2</span>: (address table (address array character) number)<span class="Delimiter">}</span>, <span class="Constant">1</span>:address:array:character ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">34</span> @@ -61,7 +61,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> table:_key:_value [ length:number capacity:number - data:address:shared:array:table_row:_key:_value + data:address:array:table_row:_key:_value ] <span class="muData">container</span> table_row:_key:_value [ @@ -70,17 +70,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color value:_value ] -<span class="muRecipe">def</span> new-table capacity:number<span class="muRecipe"> -> </span>result:address:shared:table:_key:_value [ +<span class="muRecipe">def</span> new-table capacity:number<span class="muRecipe"> -> </span>result:address:table:_key:_value [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(table _key _value): type<span class="Delimiter">}</span> - tmp:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">capacity:offset</span> - *tmp<span class="Special"> <- </span>copy capacity - data:address:address:shared:array:table_row:_key:_value<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *data<span class="Special"> <- </span>new <span class="Delimiter">{</span>(table_row _key _value): type<span class="Delimiter">}</span>, capacity + data:address:array:table_row:_key:_value<span class="Special"> <- </span>new <span class="Delimiter">{</span>(table_row _key _value): type<span class="Delimiter">}</span>, capacity + *result<span class="Special"> <- </span>merge <span class="Constant">0/length</span>, capacity, data ] -<span class="muRecipe">def</span> put table:address:shared:table:_key:_value, key:_key, value:_value<span class="muRecipe"> -> </span>table:address:shared:table:_key:_value [ +<span class="muRecipe">def</span> put table:address:table:_key:_value, key:_key, value:_value<span class="muRecipe"> -> </span>table:address:table:_key:_value [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> hash:number<span class="Special"> <- </span>hash key @@ -88,12 +86,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color capacity:number<span class="Special"> <- </span>get *table, <span class="Constant">capacity:offset</span> _, hash<span class="Special"> <- </span>divide-with-remainder hash, capacity hash<span class="Special"> <- </span>abs hash <span class="Comment"># in case hash overflows into a negative integer</span> - table-data:address:shared:array:table_row:_key:_value<span class="Special"> <- </span>get *table, <span class="Constant">data:offset</span> - x:address:table_row:_key:_value<span class="Special"> <- </span>index-address *table-data, hash - occupied?:boolean<span class="Special"> <- </span>get *x, <span class="Constant">occupied?:offset</span> + table-data:address:array:table_row:_key:_value<span class="Special"> <- </span>get *table, <span class="Constant">data:offset</span> + x:table_row:_key:_value<span class="Special"> <- </span>index *table-data, hash + occupied?:boolean<span class="Special"> <- </span>get x, <span class="Constant">occupied?:offset</span> not-occupied?:boolean<span class="Special"> <- </span>not occupied?:boolean assert not-occupied?, <span class="Constant">[can't handle collisions yet]</span> - *x<span class="Special"> <- </span>merge <span class="Constant">1/true</span>, key, value + new-row:table_row:_key:_value<span class="Special"> <- </span>merge <span class="Constant">1/true</span>, key, value + *table-data<span class="Special"> <- </span>put-index *table-data, hash, new-row ] <span class="muRecipe">def</span> abs n:number<span class="muRecipe"> -> </span>result:number [ @@ -104,7 +103,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color result<span class="Special"> <- </span>multiply n, <span class="Constant">-1</span> ] -<span class="muRecipe">def</span> index table:address:shared:table:_key:_value, key:_key<span class="muRecipe"> -> </span>result:_value [ +<span class="muRecipe">def</span> index table:address:table:_key:_value, key:_key<span class="muRecipe"> -> </span>result:_value [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> hash:number<span class="Special"> <- </span>hash key @@ -112,7 +111,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color capacity:number<span class="Special"> <- </span>get *table, <span class="Constant">capacity:offset</span> _, hash<span class="Special"> <- </span>divide-with-remainder hash, capacity hash<span class="Special"> <- </span>abs hash <span class="Comment"># in case hash overflows into a negative integer</span> - table-data:address:shared:array:table_row:_key:_value<span class="Special"> <- </span>get *table, <span class="Constant">data:offset</span> + table-data:address:array:table_row:_key:_value<span class="Special"> <- </span>get *table, <span class="Constant">data:offset</span> x:table_row:_key:_value<span class="Special"> <- </span>index *table-data, hash occupied?:boolean<span class="Special"> <- </span>get x, <span class="Constant">occupied?:offset</span> assert occupied?, <span class="Constant">[can't handle missing elements yet]</span> diff --git a/html/081print.mu.html b/html/081print.mu.html index ba9a2b06..1c998733 100644 --- a/html/081print.mu.html +++ b/html/081print.mu.html @@ -41,7 +41,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color num-columns:number cursor-row:number cursor-column:number - data:address:shared:array:screen-cell + data:address:array:screen-cell ] <span class="muData">container</span> screen-cell [ @@ -49,57 +49,44 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color color:number ] -<span class="muRecipe">def</span> new-fake-screen w:number, h:number<span class="muRecipe"> -> </span>result:address:shared:screen [ +<span class="muRecipe">def</span> new-fake-screen w:number, h:number<span class="muRecipe"> -> </span>result:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>new <span class="Constant">screen:type</span> - width:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">num-columns:offset</span> - *width<span class="Special"> <- </span>copy w - height:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">num-rows:offset</span> - *height<span class="Special"> <- </span>copy h - row:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">cursor-row:offset</span> - *row<span class="Special"> <- </span>copy <span class="Constant">0</span> - column:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">cursor-column:offset</span> - *column<span class="Special"> <- </span>copy <span class="Constant">0</span> - bufsize:number<span class="Special"> <- </span>multiply *width, *height - buf:address:address:shared:array:screen-cell<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *buf<span class="Special"> <- </span>new <span class="Constant">screen-cell:type</span>, bufsize + bufsize:number<span class="Special"> <- </span>multiply w, h + data:address:array:screen-cell<span class="Special"> <- </span>new <span class="Constant">screen-cell:type</span>, bufsize + *result<span class="Special"> <- </span>merge h/num-rows, w/num-columns, <span class="Constant">0/cursor-row</span>, <span class="Constant">0/cursor-column</span>, data result<span class="Special"> <- </span>clear-screen result ] -<span class="muRecipe">def</span> clear-screen screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> clear-screen screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen <span class="Comment"># clear fake screen</span> - buf:address:shared:array:screen-cell<span class="Special"> <- </span>get *screen, <span class="Constant">data:offset</span> + buf:address:array:screen-cell<span class="Special"> <- </span>get *screen, <span class="Constant">data:offset</span> max:number<span class="Special"> <- </span>length *buf i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>greater-or-equal i, max <span class="muControl">break-if</span> done? - curr:address:screen-cell<span class="Special"> <- </span>index-address *buf, i - curr-content:address:character<span class="Special"> <- </span>get-address *curr, <span class="Constant">contents:offset</span> - *curr-content<span class="Special"> <- </span>copy <span class="Constant">0/empty</span> - curr-color:address:number<span class="Special"> <- </span>get-address *curr, <span class="Constant">color:offset</span> - *curr-color<span class="Special"> <- </span>copy <span class="Constant">7/white</span> + curr:screen-cell<span class="Special"> <- </span>merge <span class="Constant">0/empty</span>, <span class="Constant">7/white</span> + *buf<span class="Special"> <- </span>put-index *buf, i, curr i<span class="Special"> <- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># reset cursor</span> - x:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-row:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">0</span> - x<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-column:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">0</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-row:offset</span>, <span class="Constant">0</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, <span class="Constant">0</span> <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># otherwise, real screen</span> clear-display ] -<span class="muRecipe">def</span> sync-screen screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> sync-screen screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -109,11 +96,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># do nothing for fake screens</span> ] -<span class="muRecipe">def</span> fake-screen-is-empty? screen:address:shared:screen<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> fake-screen-is-empty? screen:address:screen<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> screen, <span class="Constant">1/true</span> - buf:address:shared:array:screen-cell<span class="Special"> <- </span>get *screen, <span class="Constant">data:offset</span> + buf:address:array:screen-cell<span class="Special"> <- </span>get *screen, <span class="Constant">data:offset</span> i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> len:number<span class="Special"> <- </span>length *buf <span class="Delimiter">{</span> @@ -129,7 +116,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">return</span> <span class="Constant">1/true</span> ] -<span class="muRecipe">def</span> print screen:address:shared:screen, c:character<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> print screen:address:screen, c:character<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> @@ -152,17 +139,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color width:number<span class="Special"> <- </span>get *screen, <span class="Constant">num-columns:offset</span> height:number<span class="Special"> <- </span>get *screen, <span class="Constant">num-rows:offset</span> <span class="Comment"># if cursor is out of bounds, silently exit</span> - row:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-row:offset</span> - legal?:boolean<span class="Special"> <- </span>greater-or-equal *row, <span class="Constant">0</span> + row:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-row:offset</span> + legal?:boolean<span class="Special"> <- </span>greater-or-equal row, <span class="Constant">0</span> <span class="muControl">return-unless</span> legal? - legal?<span class="Special"> <- </span>lesser-than *row, height + legal?<span class="Special"> <- </span>lesser-than row, height <span class="muControl">return-unless</span> legal? - column:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-column:offset</span> - legal?<span class="Special"> <- </span>greater-or-equal *column, <span class="Constant">0</span> + column:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-column:offset</span> + legal?<span class="Special"> <- </span>greater-or-equal column, <span class="Constant">0</span> <span class="muControl">return-unless</span> legal? - legal?<span class="Special"> <- </span>lesser-than *column, width + legal?<span class="Special"> <- </span>lesser-than column, width <span class="muControl">return-unless</span> legal? -<span class="CommentedCode">#? $print [print-character (], *row, [, ], *column, [): ], c, 10/newline</span> +<span class="CommentedCode">#? $print [print-character (], row, [, ], column, [): ], c, 10/newline</span> <span class="Comment"># special-case: newline</span> <span class="Delimiter">{</span> newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> @@ -170,18 +157,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="Comment"># unless cursor is already at bottom</span> bottom:number<span class="Special"> <- </span>subtract height, <span class="Constant">1</span> - at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *row, bottom + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal row, bottom <span class="muControl">break-if</span> at-bottom? <span class="Comment"># move it to the next row</span> - *column<span class="Special"> <- </span>copy <span class="Constant">0</span> - *row<span class="Special"> <- </span>add *row, <span class="Constant">1</span> + column<span class="Special"> <- </span>copy <span class="Constant">0</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, column + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-row:offset</span>, row <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># save character in fake screen</span> - index:number<span class="Special"> <- </span>multiply *row, width - index<span class="Special"> <- </span>add index, *column - buf:address:shared:array:screen-cell<span class="Special"> <- </span>get *screen, <span class="Constant">data:offset</span> + index:number<span class="Special"> <- </span>multiply row, width + index<span class="Special"> <- </span>add index, column + buf:address:array:screen-cell<span class="Special"> <- </span>get *screen, <span class="Constant">data:offset</span> len:number<span class="Special"> <- </span>length *buf <span class="Comment"># special-case: backspace</span> <span class="Delimiter">{</span> @@ -189,30 +178,26 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> backspace? <span class="Delimiter">{</span> <span class="Comment"># unless cursor is already at left margin</span> - at-left?:boolean<span class="Special"> <- </span>lesser-or-equal *column, <span class="Constant">0</span> + at-left?:boolean<span class="Special"> <- </span>lesser-or-equal column, <span class="Constant">0</span> <span class="muControl">break-if</span> at-left? <span class="Comment"># clear previous location</span> - *column<span class="Special"> <- </span>subtract *column, <span class="Constant">1</span> + column<span class="Special"> <- </span>subtract column, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, column index<span class="Special"> <- </span>subtract index, <span class="Constant">1</span> - cursor:address:screen-cell<span class="Special"> <- </span>index-address *buf, index - cursor-contents:address:character<span class="Special"> <- </span>get-address *cursor, <span class="Constant">contents:offset</span> - *cursor-contents<span class="Special"> <- </span>copy <span class="Constant">32/space</span> - cursor-color:address:number<span class="Special"> <- </span>get-address *cursor, <span class="Constant">color:offset</span> - *cursor-color<span class="Special"> <- </span>copy <span class="Constant">7/white</span> + cursor:screen-cell<span class="Special"> <- </span>merge <span class="Constant">32/space</span>, <span class="Constant">7/white</span> + *buf<span class="Special"> <- </span>put-index *buf, index, cursor <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> - cursor:address:screen-cell<span class="Special"> <- </span>index-address *buf, index - cursor-contents:address:character<span class="Special"> <- </span>get-address *cursor, <span class="Constant">contents:offset</span> - *cursor-contents<span class="Special"> <- </span>copy c - cursor-color:address:number<span class="Special"> <- </span>get-address *cursor, <span class="Constant">color:offset</span> - *cursor-color<span class="Special"> <- </span>copy color + cursor:screen-cell<span class="Special"> <- </span>merge c, color + *buf<span class="Special"> <- </span>put-index *buf, index, cursor <span class="Comment"># increment column unless it's already all the way to the right</span> <span class="Delimiter">{</span> right:number<span class="Special"> <- </span>subtract width, <span class="Constant">1</span> - at-right?:boolean<span class="Special"> <- </span>greater-or-equal *column, right + at-right?:boolean<span class="Special"> <- </span>greater-or-equal column, right <span class="muControl">break-if</span> at-right? - *column<span class="Special"> <- </span>add *column, <span class="Constant">1</span> + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, column <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -222,11 +207,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-character-at-top-left [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a - <span class="Constant">2</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">3</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a + <span class="Constant">2</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">3</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> @@ -238,11 +223,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-character-in-color [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a, <span class="Constant">1/red</span> - <span class="Constant">2</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">3</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a, <span class="Constant">1/red</span> + <span class="Constant">2</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">3</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> @@ -254,14 +239,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-backspace-character [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a <span class="Constant">12</span>:character<span class="Special"> <- </span>copy <span class="Constant">8/backspace</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">12</span>:character/backspace - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-column:offset</span> - <span class="Constant">3</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">12</span>:character/backspace + <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> @@ -274,16 +259,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-extra-backspace-character [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a <span class="Constant">12</span>:character<span class="Special"> <- </span>copy <span class="Constant">8/backspace</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">12</span>:character/backspace + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">12</span>:character/backspace <span class="Constant">12</span>:character<span class="Special"> <- </span>copy <span class="Constant">8/backspace</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">12</span>:character/backspace - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-column:offset</span> - <span class="Constant">3</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">12</span>:character/backspace + <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> @@ -296,16 +281,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-character-at-right-margin [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">2/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">2/width</span>, <span class="Constant">2/height</span> <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a <span class="Constant">12</span>:character<span class="Special"> <- </span>copy <span class="Constant">98/b</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">12</span>:character/b + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">12</span>:character/b <span class="Constant">13</span>:character<span class="Special"> <- </span>copy <span class="Constant">99/b</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">13</span>:character/c - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-column:offset</span> - <span class="Constant">3</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">13</span>:character/c + <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor column</span> @@ -320,15 +305,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-newline-character [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Constant">10</span>:character<span class="Special"> <- </span>copy <span class="Constant">10/newline</span> <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/newline - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-row:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-column:offset</span> - <span class="Constant">4</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">5</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/newline + <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-row:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span> + <span class="Constant">4</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">5</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> @@ -342,13 +327,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-newline-at-bottom-line [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Constant">10</span>:character<span class="Special"> <- </span>copy <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/newline - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/newline - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/newline - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-row:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-column:offset</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/newline + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/newline + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/newline + <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-row:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> @@ -358,22 +343,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-character-at-bottom-right [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">2/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">2/width</span>, <span class="Constant">2/height</span> <span class="Constant">10</span>:character<span class="Special"> <- </span>copy <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/newline + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/newline <span class="Constant">11</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">11</span>:character/a + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">11</span>:character/a <span class="Constant">12</span>:character<span class="Special"> <- </span>copy <span class="Constant">98/b</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">12</span>:character/b + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">12</span>:character/b <span class="Constant">13</span>:character<span class="Special"> <- </span>copy <span class="Constant">99/c</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">13</span>:character/c - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/newline + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">13</span>:character/c + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/newline <span class="Constant">14</span>:character<span class="Special"> <- </span>copy <span class="Constant">100/d</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">14</span>:character/d - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-row:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">cursor-column:offset</span> - <span class="Constant">4</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">20</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">14</span>:character/d + <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-row:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span> + <span class="Constant">4</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">20</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">4</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> @@ -391,7 +376,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> clear-line screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> clear-line screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> space:character<span class="Special"> <- </span>copy <span class="Constant">0/nul</span> @@ -399,25 +384,26 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen width:number<span class="Special"> <- </span>get *screen, <span class="Constant">num-columns:offset</span> - column:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-column:offset</span> - original-column:number<span class="Special"> <- </span>copy *column + column:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-column:offset</span> + original-column:number<span class="Special"> <- </span>copy column <span class="Comment"># space over the entire line</span> <span class="Delimiter">{</span> right:number<span class="Special"> <- </span>subtract width, <span class="Constant">1</span> - done?:boolean<span class="Special"> <- </span>greater-or-equal *column, right + done?:boolean<span class="Special"> <- </span>greater-or-equal column, right <span class="muControl">break-if</span> done? - print screen, space <span class="Comment"># implicitly updates 'column'</span> + print screen, space + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># now back to where the cursor was</span> - *column<span class="Special"> <- </span>copy original-column + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, original-column <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># otherwise, real screen</span> clear-line-on-display ] -<span class="muRecipe">def</span> cursor-position screen:address:shared:screen<span class="muRecipe"> -> </span>row:number, column:number [ +<span class="muRecipe">def</span> cursor-position screen:address:screen<span class="muRecipe"> -> </span>row:number, column:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, lookup cursor in fake screen</span> @@ -430,16 +416,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color row, column<span class="Special"> <- </span>cursor-position-on-display ] -<span class="muRecipe">def</span> move-cursor screen:address:shared:screen, new-row:number, new-column:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> move-cursor screen:address:screen, new-row:number, new-column:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen - row:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-row:offset</span> - *row<span class="Special"> <- </span>copy new-row - column:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-column:offset</span> - *column<span class="Special"> <- </span>copy new-column + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-row:offset</span>, new-row + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, new-column <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># otherwise, real screen</span> @@ -448,16 +432,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> clear-line-erases-printed-characters [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> <span class="Comment"># print a character</span> <span class="Constant">10</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">10</span>:character/a + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">10</span>:character/a <span class="Comment"># move cursor to start of line</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>move-cursor <span class="Constant">1</span>:address:shared:screen, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>move-cursor <span class="Constant">1</span>:address:screen, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> <span class="Comment"># clear line</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>clear-line <span class="Constant">1</span>:address:shared:screen - <span class="Constant">2</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">20</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>clear-line <span class="Constant">1</span>:address:screen + <span class="Constant">2</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">20</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:screen-cell ] <span class="Comment"># screen should be blank</span> memory-should-contain [ @@ -477,7 +461,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> cursor-down screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> cursor-down screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> @@ -486,11 +470,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="Comment"># increment row unless it's already all the way down</span> height:number<span class="Special"> <- </span>get *screen, <span class="Constant">num-rows:offset</span> - row:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-row:offset</span> + row:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-row:offset</span> max:number<span class="Special"> <- </span>subtract height, <span class="Constant">1</span> - at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *row, max + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal row, max <span class="muControl">break-if</span> at-bottom? - *row<span class="Special"> <- </span>add *row, <span class="Constant">1</span> + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-row:offset</span>, row <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -498,7 +483,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color move-cursor-down-on-display ] -<span class="muRecipe">def</span> cursor-up screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> cursor-up screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> @@ -506,10 +491,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> screen <span class="Delimiter">{</span> <span class="Comment"># decrement row unless it's already all the way up</span> - row:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-row:offset</span> - at-top?:boolean<span class="Special"> <- </span>lesser-or-equal *row, <span class="Constant">0</span> + row:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-row:offset</span> + at-top?:boolean<span class="Special"> <- </span>lesser-or-equal row, <span class="Constant">0</span> <span class="muControl">break-if</span> at-top? - *row<span class="Special"> <- </span>subtract *row, <span class="Constant">1</span> + row<span class="Special"> <- </span>subtract row, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-row:offset</span>, row <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -517,7 +503,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color move-cursor-up-on-display ] -<span class="muRecipe">def</span> cursor-right screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> cursor-right screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> @@ -526,11 +512,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="Comment"># increment column unless it's already all the way to the right</span> width:number<span class="Special"> <- </span>get *screen, <span class="Constant">num-columns:offset</span> - column:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-column:offset</span> + column:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-column:offset</span> max:number<span class="Special"> <- </span>subtract width, <span class="Constant">1</span> - at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *column, max + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal column, max <span class="muControl">break-if</span> at-bottom? - *column<span class="Special"> <- </span>add *column, <span class="Constant">1</span> + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, column <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -538,7 +525,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color move-cursor-right-on-display ] -<span class="muRecipe">def</span> cursor-left screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> cursor-left screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> @@ -546,10 +533,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> screen <span class="Delimiter">{</span> <span class="Comment"># decrement column unless it's already all the way to the left</span> - column:address:number<span class="Special"> <- </span>get-address *screen, <span class="Constant">cursor-column:offset</span> - at-top?:boolean<span class="Special"> <- </span>lesser-or-equal *column, <span class="Constant">0</span> + column:number<span class="Special"> <- </span>get *screen, <span class="Constant">cursor-column:offset</span> + at-top?:boolean<span class="Special"> <- </span>lesser-or-equal column, <span class="Constant">0</span> <span class="muControl">break-if</span> at-top? - *column<span class="Special"> <- </span>subtract *column, <span class="Constant">1</span> + column<span class="Special"> <- </span>subtract column, <span class="Constant">1</span> + *screen<span class="Special"> <- </span>put *screen, <span class="Constant">cursor-column:offset</span>, column <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -557,7 +545,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color move-cursor-left-on-display ] -<span class="muRecipe">def</span> cursor-to-start-of-line screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> cursor-to-start-of-line screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> row:number<span class="Special"> <- </span>cursor-position screen @@ -565,14 +553,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen<span class="Special"> <- </span>move-cursor screen, row, column ] -<span class="muRecipe">def</span> cursor-to-next-line screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> cursor-to-next-line screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> screen<span class="Special"> <- </span>cursor-down screen screen<span class="Special"> <- </span>cursor-to-start-of-line screen ] -<span class="muRecipe">def</span> screen-width screen:address:shared:screen<span class="muRecipe"> -> </span>width:number [ +<span class="muRecipe">def</span> screen-width screen:address:screen<span class="muRecipe"> -> </span>width:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> @@ -585,7 +573,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color width<span class="Special"> <- </span>display-width ] -<span class="muRecipe">def</span> screen-height screen:address:shared:screen<span class="muRecipe"> -> </span>height:number [ +<span class="muRecipe">def</span> screen-height screen:address:screen<span class="muRecipe"> -> </span>height:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists, move cursor in fake screen</span> @@ -598,7 +586,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color height<span class="Special"> <- </span>display-height ] -<span class="muRecipe">def</span> hide-cursor screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> hide-cursor screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists (not real display), do nothing</span> @@ -610,7 +598,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color hide-cursor-on-display ] -<span class="muRecipe">def</span> show-cursor screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> show-cursor screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists (not real display), do nothing</span> @@ -622,7 +610,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color show-cursor-on-display ] -<span class="muRecipe">def</span> hide-screen screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> hide-screen screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists (not real display), do nothing</span> @@ -635,7 +623,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color hide-display ] -<span class="muRecipe">def</span> show-screen screen:address:shared:screen<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> show-screen screen:address:screen<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if x exists (not real display), do nothing</span> @@ -648,7 +636,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color show-display ] -<span class="muRecipe">def</span> print screen:address:shared:screen, s:address:shared:array:character<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> print screen:address:screen, s:address:array:character<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> @@ -677,11 +665,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> print-text-stops-at-right-margin [ run [ - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> - <span class="Constant">1</span>:address:shared:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:shared:screen, <span class="Constant">2</span>:address:shared:array:character - <span class="Constant">3</span>:address:shared:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:shared:screen, <span class="Constant">data:offset</span> - <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:array:screen-cell + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> + <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print <span class="Constant">1</span>:address:screen, <span class="Constant">2</span>:address:array:character + <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span> + <span class="Constant">4</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:array:screen-cell ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> @@ -695,7 +683,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> print-integer screen:address:shared:screen, n:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> print-integer screen:address:screen, n:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> @@ -711,12 +699,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color bg-color<span class="Special"> <- </span>copy <span class="Constant">0/black</span> <span class="Delimiter">}</span> <span class="Comment"># todo: other bases besides decimal</span> - s:address:shared:array:character<span class="Special"> <- </span>to-text n + s:address:array:character<span class="Special"> <- </span>to-text n screen<span class="Special"> <- </span>print screen, s, color, bg-color ] <span class="Comment"># for now, we can only print integers</span> -<span class="muRecipe">def</span> print screen:address:shared:screen, n:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> print screen:address:screen, n:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> @@ -735,7 +723,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># addresses</span> -<span class="muRecipe">def</span> print screen:address:shared:screen, n:address:_elem<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> print screen:address:screen, n:address:_elem<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> diff --git a/html/082scenario_screen.cc.html b/html/082scenario_screen.cc.html index 5bf73b8d..43cf82d7 100644 --- a/html/082scenario_screen.cc.html +++ b/html/082scenario_screen.cc.html @@ -45,7 +45,7 @@ scenario screen-in-scenario [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">97</span>/a - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/a + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/a ] screen-should-contain [ <span class="Comment"># 01234</span> @@ -60,9 +60,9 @@ 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 [ <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">955</span>/greek-small-lambda - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red <span class="Constant">2</span>:character<span class="Special"> <- </span>copy <span class="Constant">97</span>/a - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">2</span>:character/a + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">2</span>:character/a ] screen-should-contain [ <span class="Comment"># 01234</span> @@ -78,9 +78,9 @@ scenario screen-in-scenario-color [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">955</span>/greek-small-lambda - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/lambda<span class="Delimiter">,</span> <span class="Constant">1</span>/red <span class="Constant">2</span>:character<span class="Special"> <- </span>copy <span class="Constant">97</span>/a - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">2</span>:character/a<span class="Delimiter">,</span> <span class="Constant">7</span>/white + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">2</span>:character/a<span class="Delimiter">,</span> <span class="Constant">7</span>/white ] <span class="Comment"># screen-should-contain shows everything</span> screen-should-contain [ @@ -113,7 +113,7 @@ scenario screen-in-scenario-error [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">97</span>/a - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/a + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/a ] screen-should-contain [ <span class="Comment"># 01234</span> @@ -132,7 +132,7 @@ scenario screen-in-scenario-color [ assume-screen <span class="Constant">5</span>/width<span class="Delimiter">,</span> <span class="Constant">3</span>/height run [ <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">97</span>/a - <span class="Normal">screen</span>:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/a<span class="Delimiter">,</span> <span class="Constant">1</span>/red + <span class="Normal">screen</span>:address:screen<span class="Special"> <- </span>print screen:address:screen<span class="Delimiter">,</span> <span class="Constant">1</span>:character/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> @@ -180,11 +180,11 @@ Name[r][<span class="Constant">"screen"</span>] = SCREEN<span class="D <span class="Delimiter">:(before "End Rewrite Instruction(curr, recipe result)")</span> <span class="Comment">// rewrite `assume-screen width, height` to</span> -<span class="Comment">// `screen:address:shared:screen <- new-fake-screen width, height`</span> +<span class="Comment">// `screen:address:screen <- new-fake-screen width, height`</span> <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"assume-screen"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> curr<span class="Delimiter">.</span>name = <span class="Constant">"new-fake-screen"</span><span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"screen:address:shared:screen"</span><span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"screen:address:screen"</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> @@ -242,7 +242,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">int</span> screen_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> SCREEN<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Normal">int</span> data_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"screen"</span><span class="Delimiter">),</span> <span class="Constant">"data"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>data_offset >= <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">int</span> screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:shared:array:character</span> + <span class="Normal">int</span> screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:array:character</span> <span class="Normal">int</span> 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">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// type: array:character</span> <span class="Normal">int</span> width_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"screen"</span><span class="Delimiter">),</span> <span class="Constant">"num-columns"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Normal">int</span> screen_width = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+width_offset<span class="Delimiter">);</span> @@ -381,7 +381,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">int</span> screen_height = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+height_offset<span class="Delimiter">);</span> <span class="Normal">int</span> data_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"screen"</span><span class="Delimiter">),</span> <span class="Constant">"data"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>data_offset >= <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">int</span> screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:shared:array:character</span> + <span class="Normal">int</span> screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:array:character</span> <span class="Normal">int</span> 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">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><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> <span class="Normal">int</span> curr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// skip length</span> diff --git a/html/083scenario_screen_test.mu.html b/html/083scenario_screen_test.mu.html index d5c7b2f5..63afa9bf 100644 --- a/html/083scenario_screen_test.mu.html +++ b/html/083scenario_screen_test.mu.html @@ -34,7 +34,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assume-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> run [ <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - screen:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen, <span class="Constant">1</span>:character/a + screen:address:screen<span class="Special"> <- </span>print screen:address:screen, <span class="Constant">1</span>:character/a ] screen-should-contain [ <span class="Constant"> .a .</span> @@ -47,11 +47,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color run [ <span class="Comment"># print a character</span> <span class="Constant">1</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> - screen:address:shared:screen<span class="Special"> <- </span>print screen:address:shared:screen, <span class="Constant">1</span>:character/a + screen:address:screen<span class="Special"> <- </span>print screen:address:screen, <span class="Constant">1</span>:character/a <span class="Comment"># move cursor to start of line</span> - screen:address:shared:screen<span class="Special"> <- </span>move-cursor screen:address:shared:screen, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> + screen:address:screen<span class="Special"> <- </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:shared:screen<span class="Special"> <- </span>clear-line screen:address:shared:screen + screen:address:screen<span class="Special"> <- </span>clear-line screen:address:screen ] screen-should-contain [ <span class="Constant"> . .</span> diff --git a/html/084console.mu.html b/html/084console.mu.html index 13bc38b6..157e7504 100644 --- a/html/084console.mu.html +++ b/html/084console.mu.html @@ -55,35 +55,33 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> console [ current-event-index:number - events:address:shared:array:event + events:address:array:event ] -<span class="muRecipe">def</span> new-fake-console events:address:shared:array:event<span class="muRecipe"> -> </span>result:address:shared:console [ +<span class="muRecipe">def</span> new-fake-console events:address:array:event<span class="muRecipe"> -> </span>result:address:console [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - result:address:shared:console<span class="Special"> <- </span>new <span class="Constant">console:type</span> - buf:address:address:shared:array:event<span class="Special"> <- </span>get-address *result, <span class="Constant">events:offset</span> - *buf<span class="Special"> <- </span>copy events - idx:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">current-event-index:offset</span> - *idx<span class="Special"> <- </span>copy <span class="Constant">0</span> + result:address:console<span class="Special"> <- </span>new <span class="Constant">console:type</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">events:offset</span>, events ] -<span class="muRecipe">def</span> read-event console:address:shared:console<span class="muRecipe"> -> </span>result:event, console:address:shared:console, found?:boolean, quit?:boolean [ +<span class="muRecipe">def</span> read-event console:address:console<span class="muRecipe"> -> </span>result:event, console:address:console, found?:boolean, quit?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> console - current-event-index:address:number<span class="Special"> <- </span>get-address *console, <span class="Constant">current-event-index:offset</span> - buf:address:shared:array:event<span class="Special"> <- </span>get *console, <span class="Constant">events:offset</span> + current-event-index:number<span class="Special"> <- </span>get *console, <span class="Constant">current-event-index:offset</span> + buf:address:array:event<span class="Special"> <- </span>get *console, <span class="Constant">events:offset</span> <span class="Delimiter">{</span> max:number<span class="Special"> <- </span>length *buf - done?:boolean<span class="Special"> <- </span>greater-or-equal *current-event-index, max + done?:boolean<span class="Special"> <- </span>greater-or-equal current-event-index, max <span class="muControl">break-unless</span> done? - dummy:address:shared:event<span class="Special"> <- </span>new <span class="Constant">event:type</span> + dummy:address:event<span class="Special"> <- </span>new <span class="Constant">event:type</span> <span class="muControl">return</span> *dummy, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">1/quit</span> <span class="Delimiter">}</span> - result<span class="Special"> <- </span>index *buf, *current-event-index - *current-event-index<span class="Special"> <- </span>add *current-event-index, <span class="Constant">1</span> + result<span class="Special"> <- </span>index *buf, current-event-index + current-event-index<span class="Special"> <- </span>add current-event-index, <span class="Constant">1</span> + *console<span class="Special"> <- </span>put *console, <span class="Constant">current-event-index:offset</span>, current-event-index <span class="muControl">return</span> result, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> <span class="Delimiter">}</span> switch <span class="Comment"># real event source is infrequent; avoid polling it too much</span> @@ -94,18 +92,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># variant of read-event for just keyboard events. Discards everything that</span> <span class="Comment"># isn't unicode, so no arrow keys, page-up/page-down, etc. But you still get</span> <span class="Comment"># newlines, tabs, ctrl-d..</span> -<span class="muRecipe">def</span> read-key console:address:shared:console<span class="muRecipe"> -> </span>result:character, console:address:shared:console, found?:boolean, quit?:boolean [ +<span class="muRecipe">def</span> read-key console:address:console<span class="muRecipe"> -> </span>result:character, console:address:console, found?:boolean, quit?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> x:event, console, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-event console <span class="muControl">return-if</span> quit?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit? <span class="muControl">return-unless</span> found?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit? - c:address:character<span class="Special"> <- </span>maybe-convert x, <span class="Constant">text:variant</span> - <span class="muControl">return-unless</span> c, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/found</span>, <span class="Constant">0/quit</span> - <span class="muControl">return</span> *c, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> + c:character, converted?:boolean<span class="Special"> <- </span>maybe-convert x, <span class="Constant">text:variant</span> + <span class="muControl">return-unless</span> converted?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/found</span>, <span class="Constant">0/quit</span> + <span class="muControl">return</span> c, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> ] -<span class="muRecipe">def</span> send-keys-to-channel console:address:shared:console, chan:address:shared:sink:character, screen:address:shared:screen<span class="muRecipe"> -> </span>console:address:shared:console, chan:address:shared:sink:character, screen:address:shared:screen [ +<span class="muRecipe">def</span> send-keys-to-channel console:address:console, chan:address:sink:character, screen:address:screen<span class="muRecipe"> -> </span>console:address:console, chan:address:sink:character, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -119,7 +117,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> wait-for-event console:address:shared:console<span class="muRecipe"> -> </span>console:address:shared:console [ +<span class="muRecipe">def</span> wait-for-event console:address:console<span class="muRecipe"> -> </span>console:address:console [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -129,7 +127,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># use this helper to skip rendering if there's lots of other events queued up</span> -<span class="muRecipe">def</span> has-more-events? console:address:shared:console<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> has-more-events? console:address:console<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> diff --git a/html/085scenario_console.cc.html b/html/085scenario_console.cc.html index 66ca7b81..f0d114d6 100644 --- a/html/085scenario_console.cc.html +++ b/html/085scenario_console.cc.html @@ -44,10 +44,10 @@ scenario keyboard-in-scenario [ type [abc] ] run [ - <span class="Constant">1</span>:character<span class="Delimiter">,</span> console:address:shared:console<span class="Delimiter">,</span> <span class="Constant">2</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console - <span class="Constant">3</span>:character<span class="Delimiter">,</span> console:address:shared:console<span class="Delimiter">,</span> <span class="Constant">4</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console - <span class="Constant">5</span>:character<span class="Delimiter">,</span> console:address:shared:console<span class="Delimiter">,</span> <span class="Constant">6</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console - <span class="Constant">7</span>:character<span class="Delimiter">,</span> console:address:shared:console<span class="Delimiter">,</span> <span class="Constant">8</span>:boolean<span class="Delimiter">,</span> <span class="Constant">9</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console + <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"> <- </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"> <- </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"> <- </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"> <- </span>read-key console:address:console ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> @@ -227,15 +227,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"> <- </span>read-event console:address:shared:console - <span class="Constant">5</span>:event<span class="Special"> <- </span>read-event console:address:shared:console - <span class="Constant">9</span>:event<span class="Special"> <- </span>read-event console:address:shared:console + <span class="Constant">1</span>:event<span class="Special"> <- </span>read-event console:address:console + <span class="Constant">5</span>:event<span class="Special"> <- </span>read-event console:address:console + <span class="Constant">9</span>:event<span class="Special"> <- </span>read-event console:address:console <span class="Comment"># mouse click</span> - <span class="Constant">13</span>:event<span class="Special"> <- </span>read-event console:address:shared:console + <span class="Constant">13</span>:event<span class="Special"> <- </span>read-event console:address:console <span class="Comment"># non-character keycode</span> - <span class="Constant">17</span>:event<span class="Special"> <- </span>read-event console:address:shared:console + <span class="Constant">17</span>:event<span class="Special"> <- </span>read-event console:address:console <span class="Comment"># final keyboard event</span> - <span class="Constant">21</span>:event<span class="Special"> <- </span>read-event console:address:shared:console + <span class="Constant">21</span>:event<span class="Special"> <- </span>read-event console:address:console ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># 'text'</span> diff --git a/html/086scenario_console_test.mu.html b/html/086scenario_console_test.mu.html index f2f5bc91..d431548b 100644 --- a/html/086scenario_console_test.mu.html +++ b/html/086scenario_console_test.mu.html @@ -37,10 +37,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[abc]</span> ] run [ - <span class="Constant">1</span>:character, console:address:shared:console, <span class="Constant">2</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console - <span class="Constant">3</span>:character, console:address:shared:console, <span class="Constant">4</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console - <span class="Constant">5</span>:character, console:address:shared:console, <span class="Constant">6</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console - <span class="Constant">7</span>:character, console:address:shared:console, <span class="Constant">8</span>:boolean<span class="Special"> <- </span>read-key console:address:shared:console + <span class="Constant">1</span>:character, console:address:console, <span class="Constant">2</span>:boolean<span class="Special"> <- </span>read-key console:address:console + <span class="Constant">3</span>:character, console:address:console, <span class="Constant">4</span>:boolean<span class="Special"> <- </span>read-key console:address:console + <span class="Constant">5</span>:character, console:address:console, <span class="Constant">6</span>:boolean<span class="Special"> <- </span>read-key console:address:console + <span class="Constant">7</span>:character, console:address:console, <span class="Constant">8</span>:boolean<span class="Special"> <- </span>read-key console:address:console ] memory-should-contain [ <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> diff --git a/html/091run_interactive.cc.html b/html/091run_interactive.cc.html index 101756eb..45ad9f18 100644 --- a/html/091run_interactive.cc.html +++ b/html/091run_interactive.cc.html @@ -38,16 +38,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">:(scenario run_interactive_code)</span> def main [ <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">0</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [<span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">34</span>] - run-interactive <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [<span class="Constant">1</span>:number/<span class="Special">raw <- </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 <- </span>copy <span class="Constant">1</span>:number/<span class="Special">raw</span> ] <span class="traceContains">+mem: storing 34 in location 3</span> <span class="Delimiter">:(scenario run_interactive_empty)</span> def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>copy <span class="Constant">0</span>/unsafe - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>copy <span class="Constant">0</span>/unsafe + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </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 2</span> @@ -120,7 +120,7 @@ Track_most_recent_products = <span class="Constant">false</span><span class="Del <span class="Comment">// call run(string) but without the scheduling</span> load<span class="Delimiter">(</span>string<span class="Delimiter">(</span><span class="Constant">"recipe! interactive [</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">)</span> + <span class="Constant">"local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> + - <span class="Constant">"screen:address:shared:screen <- next-ingredient</span><span class="cSpecial">\n</span><span class="Constant">"</span> + + <span class="Constant">"screen:address:screen <- next-ingredient</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"$start-tracking-products</span><span class="cSpecial">\n</span><span class="Constant">"</span> + command + <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"$stop-tracking-products</span><span class="cSpecial">\n</span><span class="Constant">"</span> + @@ -202,15 +202,15 @@ load<span class="Delimiter">(</span>string<span class="Delimiter">(</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"recipe sandbox [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> + - <span class="Constant">"screen:address:shared:screen <- new-fake-screen 30, 5</span><span class="cSpecial">\n</span><span class="Constant">"</span> + + <span class="Constant">"screen:address:screen <- new-fake-screen 30, 5</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"r:number/routine_id <- start-running interactive, screen</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"limit-time r, 100000/instructions</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"wait-for-routine r</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"sandbox-state:number <- routine-state r/routine_id</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"completed?:boolean <- equal sandbox-state, 1/completed</span><span class="cSpecial">\n</span><span class="Constant">"</span> + - <span class="Constant">"output:address:shared:array:character <- $most-recent-products</span><span class="cSpecial">\n</span><span class="Constant">"</span> + - <span class="Constant">"errors:address:shared:array:character <- save-errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> + - <span class="Constant">"stashes:address:shared:array:character <- save-app-trace</span><span class="cSpecial">\n</span><span class="Constant">"</span> + + <span class="Constant">"output:address:array:character <- $most-recent-products</span><span class="cSpecial">\n</span><span class="Constant">"</span> + + <span class="Constant">"errors:address:array:character <- save-errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> + + <span class="Constant">"stashes:address:array:character <- save-app-trace</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"$cleanup-run-interactive</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"return output, errors, screen, stashes, completed?</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> @@ -221,10 +221,10 @@ load<span class="Delimiter">(</span>string<span class="Delimiter">(</span> <span class="Delimiter">:(scenario run_interactive_comments)</span> def main [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [<span class="Comment"># ab</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [<span class="Comment"># ab</span> add <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">2</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:array:character + <span class="Constant">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character ] <span class="traceContains">+mem: storing 52 in location 4</span> @@ -318,9 +318,9 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(scenario "run_interactive_converts_result_to_text")</span> def main [ <span class="Comment"># try to interactively add 2 and 2</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [add <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">2</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy <span class="Constant">2</span>:address:shared:array:character/lookup + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [add <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">2</span>] + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:array:character + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy <span class="Constant">2</span>:address:array:character/lookup ] <span class="Comment"># first letter in the output should be '4' in unicode</span> <span class="traceContains">+mem: storing 52 in location 11</span> @@ -328,13 +328,13 @@ def main [ <span class="Delimiter">:(scenario "run_interactive_returns_text")</span> def main [ <span class="Comment"># try to interactively add 2 and 2</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [ - <span class="Normal">x</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [a] - <span class="Normal">y</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [b] - <span class="Normal">z</span>:address:shared:array:character<span class="Special"> <- </span>append x:address:shared:array:character<span class="Delimiter">,</span> y:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [ + <span class="Normal">x</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [a] + <span class="Normal">y</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [b] + <span class="Normal">z</span>:address:array:character<span class="Special"> <- </span>append x:address:array:character<span class="Delimiter">,</span> y:address:array:character ] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy <span class="Constant">2</span>:address:shared:array:character/lookup + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:array:character + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy <span class="Constant">2</span>:address:array:character/lookup ] <span class="Comment"># output contains "ab"</span> <span class="traceContains">+mem: storing 97 in location 11</span> @@ -343,10 +343,10 @@ def main [ <span class="Delimiter">:(scenario "run_interactive_returns_errors")</span> def main [ <span class="Comment"># run a command that generates an error</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [x:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [x:number<span class="Special"> <- </span>copy <span class="Constant">34</span> get x:number<span class="Delimiter">,</span> foo:offset] - <span class="Constant">2</span>:address:shared:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:shared:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:shared:array:character - <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy <span class="Constant">3</span>:address:shared:array:character/lookup + <span class="Constant">2</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:array:character + <span class="Constant">10</span>:array:character<span class="Special"> <- </span>copy <span class="Constant">3</span>:address:array:character/lookup ] <span class="Comment"># error should be "unknown element foo in container number"</span> <span class="traceContains">+mem: storing 117 in location 11</span> @@ -358,10 +358,10 @@ get x:number<span class="Delimiter">,</span> foo:offset] <span class="Delimiter">:(scenario run_interactive_with_comment)</span> def main [ <span class="Comment"># 2 instructions, with a comment after the first</span> - <span class="Constant">1</span>:address:shared:array:number<span class="Special"> <- </span><span class="Normal">new</span> [a:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># abc</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> [a:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># abc</span> <span class="Normal">b</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] - <span class="Constant">2</span>:address:shared:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:shared:array:character<span class="Special"> <- </span>run-interactive <span class="Constant">1</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">3</span>:address:array:character<span class="Special"> <- </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> @@ -510,7 +510,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(scenario reload_continues_past_error)</span> def main [ local-scope - <span class="Normal">x</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [recipe foo [ + <span class="Normal">x</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [recipe foo [ get <span class="Constant">1234</span>:number<span class="Delimiter">,</span> foo:offset ]] reload x @@ -522,7 +522,7 @@ def main [ <span class="Comment"># define a container and try to create it (merge requires knowing container size)</span> def main [ local-scope - <span class="Normal">x</span>:address:shared:array:character<span class="Special"> <- </span><span class="Normal">new</span> [ + <span class="Normal">x</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [ container foo [ <span class="Normal">x</span>:number <span class="Normal">y</span>:number diff --git a/html/channel.mu.html b/html/channel.mu.html index c320fdf2..30c5b5b7 100644 --- a/html/channel.mu.html +++ b/html/channel.mu.html @@ -32,7 +32,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <pre id='vimCodeElement'> <span class="Comment"># example program: communicating between routines using channels</span> -<span class="muRecipe">def</span> producer chan:address:shared:channel:character<span class="muRecipe"> -> </span>chan:address:shared:channel:character [ +<span class="muRecipe">def</span> producer sink:address:sink:character<span class="muRecipe"> -> </span>sink:address:sink:character [ <span class="Comment"># produce characters 1 to 5 on a channel</span> <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> @@ -44,19 +44,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># other threads might get between these prints</span> $print <span class="Constant">[produce: ]</span>, n, <span class="Constant">[ </span> <span class="Constant">]</span> - chan<span class="Special"> <- </span>write chan, n + sink<span class="Special"> <- </span>write sink, n n<span class="Special"> <- </span>add n, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> consumer chan:address:shared:channel:character<span class="muRecipe"> -> </span>chan:address:shared:channel:character [ +<span class="muRecipe">def</span> consumer source:address:source:character<span class="muRecipe"> -> </span>source:address:source:character [ <span class="Comment"># consume and print integers from a channel</span> <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="Comment"># read an integer from the channel</span> - n:character, chan<span class="Special"> <- </span>read chan + n:character, source<span class="Special"> <- </span>read source <span class="Comment"># other threads might get between these prints</span> $print <span class="Constant">[consume: ]</span>, n:character, <span class="Constant">[ </span> <span class="Constant">]</span> @@ -66,10 +66,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> main [ <span class="Constant">local-scope</span> - chan:address:shared:channel:character<span class="Special"> <- </span>new-channel <span class="Constant">3</span> + source:address:source:character, sink:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> <span class="Comment"># create two background 'routines' that communicate by a channel</span> - routine1:number<span class="Special"> <- </span>start-running producer, chan - routine2:number<span class="Special"> <- </span>start-running consumer, chan + routine1:number<span class="Special"> <- </span>start-running producer, sink + routine2:number<span class="Special"> <- </span>start-running consumer, source wait-for-routine routine1 wait-for-routine routine2 ] diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html index 6ab2dc38..357c33ff 100644 --- a/html/chessboard.mu.html +++ b/html/chessboard.mu.html @@ -69,7 +69,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">]</span> ] run [ - screen:address:shared:screen, console:address:shared:console<span class="Special"> <- </span>chessboard screen:address:shared:screen, console:address:shared:console + screen:address:screen, console:address:console<span class="Special"> <- </span>chessboard screen:address:screen, console:address:console <span class="Comment"># icon for the cursor</span> screen<span class="Special"> <- </span>print screen, <span class="Constant">9251/␣</span> ] @@ -101,15 +101,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="SalientComment">## Here's how 'chessboard' is implemented.</span> -<span class="muRecipe">def</span> chessboard screen:address:shared:screen, console:address:shared:console<span class="muRecipe"> -> </span>screen:address:shared:screen, console:address:shared:console [ +<span class="muRecipe">def</span> chessboard screen:address:screen, console:address:console<span class="muRecipe"> -> </span>screen:address:screen, console:address:console [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - board:address:shared:array:address:shared:array:character<span class="Special"> <- </span>initial-position + board:address:array:address:array:character<span class="Special"> <- </span>initial-position <span class="Comment"># hook up stdin</span> - stdin-in:address:shared:source:character, stdin-out:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> + stdin-in:address:source:character, stdin-out:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> start-running send-keys-to-channel, console, stdin-out, screen <span class="Comment"># buffer lines in stdin</span> - buffered-stdin-in:address:shared:source:character, buffered-stdin-out:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> + buffered-stdin-in:address:source:character, buffered-stdin-out:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> start-running buffer-lines, stdin-in, buffered-stdin-out <span class="Delimiter">{</span> print screen, <span class="Constant">[Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.</span> @@ -125,7 +125,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> cursor-to-next-line screen screen<span class="Special"> <- </span>print screen, <span class="Constant">[move: ]</span> - m:address:shared:move, quit:boolean, error:boolean<span class="Special"> <- </span>read-move buffered-stdin-in, screen + m:address:move, quit:boolean, error:boolean<span class="Special"> <- </span>read-move buffered-stdin-in, screen <span class="muControl">break-if</span> quit, <span class="Constant">+quit:label</span> buffered-stdin-in<span class="Special"> <- </span>clear buffered-stdin-in <span class="Comment"># cleanup after error. todo: test this?</span> <span class="muControl">loop-if</span> error @@ -139,7 +139,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="SalientComment">## a board is an array of files, a file is an array of characters (squares)</span> -<span class="muRecipe">def</span> new-board initial-position:address:shared:array:character<span class="muRecipe"> -> </span>board:address:shared:array:address:shared:array:character [ +<span class="muRecipe">def</span> new-board initial-position:address:array:character<span class="muRecipe"> -> </span>board:address:array:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># assert(length(initial-position) == 64)</span> @@ -147,19 +147,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color correct-length?:boolean<span class="Special"> <- </span>equal len, <span class="Constant">64</span> assert correct-length?, <span class="Constant">[chessboard had incorrect size]</span> <span class="Comment"># board is an array of pointers to files; file is an array of characters</span> - board<span class="Special"> <- </span>new <span class="Delimiter">{</span>(address shared array character): type<span class="Delimiter">}</span>, <span class="Constant">8</span> + board<span class="Special"> <- </span>new <span class="Delimiter">{</span>(address array character): type<span class="Delimiter">}</span>, <span class="Constant">8</span> col:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>equal col, <span class="Constant">8</span> <span class="muControl">break-if</span> done? - file:address:address:shared:array:character<span class="Special"> <- </span>index-address *board, col - *file<span class="Special"> <- </span>new-file initial-position, col + file:address:array:character<span class="Special"> <- </span>new-file initial-position, col + *board<span class="Special"> <- </span>put-index *board, col, file col<span class="Special"> <- </span>add col, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> new-file position:address:shared:array:character, index:number<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> new-file position:address:array:character, index:number<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> index<span class="Special"> <- </span>multiply index, <span class="Constant">8</span> @@ -168,15 +168,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>equal row, <span class="Constant">8</span> <span class="muControl">break-if</span> done? - dest:address:character<span class="Special"> <- </span>index-address *result, row - *dest<span class="Special"> <- </span>index *position, index + square:character<span class="Special"> <- </span>index *position, index + *result<span class="Special"> <- </span>put-index *result, row, square row<span class="Special"> <- </span>add row, <span class="Constant">1</span> index<span class="Special"> <- </span>add index, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> print-board screen:address:shared:screen, board:address:shared:array:address:shared:array:character<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> print-board screen:address:screen, board:address:array:address:array:character<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> row:number<span class="Special"> <- </span>copy <span class="Constant">7</span> <span class="Comment"># start printing from the top of the board</span> @@ -194,7 +194,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>equal col:number, <span class="Constant">8</span> <span class="muControl">break-if</span> done?:boolean - f:address:shared:array:character<span class="Special"> <- </span>index *board, col + f:address:array:character<span class="Special"> <- </span>index *board, col c:character<span class="Special"> <- </span>index *f, row print screen, c print screen, space @@ -212,7 +212,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color cursor-to-next-line screen ] -<span class="muRecipe">def</span> initial-position<span class="muRecipe"> -> </span>board:address:shared:array:address:shared:array:character [ +<span class="muRecipe">def</span> initial-position<span class="muRecipe"> -> </span>board:address:array:address:array:character [ <span class="Constant">local-scope</span> <span class="Comment"># layout in memory (in raster order):</span> <span class="Comment"># R P _ _ _ _ p r</span> @@ -223,7 +223,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </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"> <- </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> @@ -238,8 +238,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> printing-the-board [ assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span> run [ - <span class="Constant">1</span>:address:shared:array:address:shared:array:character/board<span class="Special"> <- </span>initial-position - screen:address:shared:screen<span class="Special"> <- </span>print-board screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:address:shared:array:character/board + <span class="Constant">1</span>:address:array:address:array:character/board<span class="Special"> <- </span>initial-position + screen:address:screen<span class="Special"> <- </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> @@ -269,37 +269,35 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># prints only error messages to screen</span> -<span class="muRecipe">def</span> read-move stdin:address:shared:source:character, screen:address:shared:screen<span class="muRecipe"> -> </span>result:address:shared:move, quit?:boolean, error?:boolean, stdin:address:shared:source:character, screen:address:shared:screen [ +<span class="muRecipe">def</span> read-move stdin:address:source:character, screen:address:screen<span class="muRecipe"> -> </span>result:address:move, quit?:boolean, error?:boolean, stdin:address:source:character, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> from-file:number, quit?:boolean, error?:boolean<span class="Special"> <- </span>read-file stdin, screen <span class="muControl">return-if</span> quit?, <span class="Constant">0/dummy</span> <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span> <span class="Comment"># construct the move object</span> - result:address:shared:move<span class="Special"> <- </span>new <span class="Constant">move:type</span> - x:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">from-file:offset</span> - *x<span class="Special"> <- </span>copy from-file - x<span class="Special"> <- </span>get-address *result, <span class="Constant">from-rank:offset</span> - *x, quit?, error?<span class="Special"> <- </span>read-rank stdin, screen + result:address:move<span class="Special"> <- </span>new <span class="Constant">move:type</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">from-file:offset</span>, from-file + from-rank:number, quit?, error?<span class="Special"> <- </span>read-rank stdin, screen <span class="muControl">return-if</span> quit?, <span class="Constant">0/dummy</span> <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">from-rank:offset</span>, from-rank error?<span class="Special"> <- </span>expect-from-channel stdin, <span class="Constant">45/dash</span>, screen <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span> - x<span class="Special"> <- </span>get-address *result, <span class="Constant">to-file:offset</span> - *x, quit?, error?<span class="Special"> <- </span>read-file stdin, screen + to-file:number, quit?, error?<span class="Special"> <- </span>read-file stdin, screen <span class="muControl">return-if</span> quit?:boolean, <span class="Constant">0/dummy</span> <span class="muControl">return-if</span> error?:boolean, <span class="Constant">0/dummy</span> - x:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">to-rank:offset</span> - *x, quit?, error?<span class="Special"> <- </span>read-rank stdin, screen + *result<span class="Special"> <- </span>put *result, <span class="Constant">to-file:offset</span>, to-file + to-rank:number, quit?, error?<span class="Special"> <- </span>read-rank stdin, screen <span class="muControl">return-if</span> quit?, <span class="Constant">0/dummy</span> <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">to-rank:offset</span>, to-file error?<span class="Special"> <- </span>expect-from-channel stdin, <span class="Constant">10/newline</span>, screen <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span> - <span class="muControl">return</span> result, quit?, error? ] <span class="Comment"># valid values for file: 0-7</span> -<span class="muRecipe">def</span> read-file stdin:address:shared:source:character, screen:address:shared:screen<span class="muRecipe"> -> </span>file:number, quit:boolean, error:boolean, stdin:address:shared:source:character, screen:address:shared:screen [ +<span class="muRecipe">def</span> read-file stdin:address:source:character, screen:address:screen<span class="muRecipe"> -> </span>file:number, quit:boolean, error:boolean, stdin:address:source:character, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> c:character, stdin<span class="Special"> <- </span>read stdin @@ -345,7 +343,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># valid values: 0-7, -1 (quit), -2 (error)</span> -<span class="muRecipe">def</span> read-rank stdin:address:shared:source:character, screen:address:shared:screen<span class="muRecipe"> -> </span>rank:number, quit?:boolean, error?:boolean, stdin:address:shared:source:character, screen:address:shared:screen [ +<span class="muRecipe">def</span> read-rank stdin:address:source:character, screen:address:screen<span class="muRecipe"> -> </span>rank:number, quit?:boolean, error?:boolean, stdin:address:source:character, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> c:character, stdin<span class="Special"> <- </span>read stdin @@ -386,7 +384,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># read a character from the given channel and check that it's what we expect</span> <span class="Comment"># return true on error</span> -<span class="muRecipe">def</span> expect-from-channel stdin:address:shared:source:character, expected:character, screen:address:shared:screen<span class="muRecipe"> -> </span>result:boolean, stdin:address:shared:source:character, screen:address:shared:screen [ +<span class="muRecipe">def</span> expect-from-channel stdin:address:source:character, expected:character, screen:address:screen<span class="muRecipe"> -> </span>result:boolean, stdin:address:source:character, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> c:character, stdin<span class="Special"> <- </span>read stdin @@ -401,8 +399,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> read-move-blocking [ assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ - <span class="Constant">1</span>:address:shared:source:character, <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> - <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:shared:source:character, screen:address:shared:screen + <span class="Constant">1</span>:address:source:character, <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> + <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:source:character, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">3</span>:number <span class="Constant">4</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">3</span>:number/id @@ -410,7 +408,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-blocking: routine failed to pause after coming up (before any keys were pressed)]</span> <span class="Comment"># press 'a'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">97/a</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">97/a</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' still waiting for input</span> wait-for-routine <span class="Constant">3</span>:number @@ -419,7 +417,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-blocking: routine failed to pause after rank 'a']</span> <span class="Comment"># press '2'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">50/'2'</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">50/'2'</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' still waiting for input</span> wait-for-routine <span class="Constant">3</span>:number @@ -428,7 +426,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-blocking: routine failed to pause after file 'a2']</span> <span class="Comment"># press '-'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">45/'-'</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">45/'-'</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' still waiting for input</span> wait-for-routine <span class="Constant">3</span>:number @@ -437,7 +435,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?/routine-state, <span class="Constant">[ </span> <span class="Constant">F read-move-blocking: routine failed to pause after hyphen 'a2-']</span> <span class="Comment"># press 'a'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">97/a</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">97/a</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' still waiting for input</span> wait-for-routine <span class="Constant">3</span>:number @@ -446,7 +444,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?/routine-state, <span class="Constant">[ </span> <span class="Constant">F read-move-blocking: routine failed to pause after rank 'a2-a']</span> <span class="Comment"># press '4'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">52/'4'</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">52/'4'</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' still waiting for input</span> wait-for-routine <span class="Constant">3</span>:number @@ -455,7 +453,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-blocking: routine failed to pause after file 'a2-a4']</span> <span class="Comment"># press 'newline'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">10</span> <span class="Comment"># newline</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">10</span> <span class="Comment"># newline</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' now completes</span> wait-for-routine <span class="Constant">3</span>:number @@ -473,8 +471,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> read-move-quit [ assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ - <span class="Constant">1</span>:address:shared:source:character, <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> - <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:shared:channel:character, screen:address:shared:screen + <span class="Constant">1</span>:address:source:character, <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> + <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:channel:character, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">3</span>:number <span class="Constant">4</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">3</span>:number/id @@ -482,7 +480,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-quit: routine failed to pause after coming up (before any keys were pressed)]</span> <span class="Comment"># press 'q'</span> - <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:shared:sink:character, <span class="Constant">113/q</span> + <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">2</span>:address:sink:character, <span class="Constant">113/q</span> restart <span class="Constant">3</span>:number/routine <span class="Comment"># 'read-move' completes</span> wait-for-routine <span class="Constant">3</span>:number @@ -500,15 +498,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> read-move-illegal-file [ assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ - <span class="Constant">1</span>:address:shared:source:character, <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> - <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:shared:source:character, screen:address:shared:screen + <span class="Constant">1</span>:address:source:character, <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> + <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:source:character, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">3</span>:number <span class="Constant">4</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">3</span>:number/id <span class="Constant">5</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">4</span>:number/routine-state, <span class="Constant">3/waiting</span> assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-file: routine failed to pause after coming up (before any keys were pressed)]</span> - <span class="Constant">1</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:shared:sink:character, <span class="Constant">50/'2'</span> + <span class="Constant">1</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:sink:character, <span class="Constant">50/'2'</span> restart <span class="Constant">3</span>:number/routine wait-for-routine <span class="Constant">3</span>:number ] @@ -521,16 +519,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> read-move-illegal-rank [ assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ - <span class="Constant">1</span>:address:shared:source:character, <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> - <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:shared:source:character, screen:address:shared:screen + <span class="Constant">1</span>:address:source:character, <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> + <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:source:character, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">3</span>:number <span class="Constant">4</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">3</span>:number/id <span class="Constant">5</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">4</span>:number/routine-state, <span class="Constant">3/waiting</span> assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-file: routine failed to pause after coming up (before any keys were pressed)]</span> - <span class="Constant">1</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:shared:sink:character, <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:shared:sink:character, <span class="Constant">97/a</span> + <span class="Constant">1</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:sink:character, <span class="Constant">97/a</span> + <span class="Constant">1</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:sink:character, <span class="Constant">97/a</span> restart <span class="Constant">3</span>:number/routine wait-for-routine <span class="Constant">3</span>:number ] @@ -543,16 +541,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> read-move-empty [ assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> run [ - <span class="Constant">1</span>:address:shared:source:character, <span class="Constant">2</span>:address:shared:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> - <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:shared:source:character, screen:address:shared:screen + <span class="Constant">1</span>:address:source:character, <span class="Constant">2</span>:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">2/capacity</span> + <span class="Constant">3</span>:number/routine<span class="Special"> <- </span>start-running read-move, <span class="Constant">1</span>:address:source:character, screen:address:screen <span class="Comment"># 'read-move' is waiting for input</span> wait-for-routine <span class="Constant">3</span>:number <span class="Constant">4</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">3</span>:number/id <span class="Constant">5</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">4</span>:number/routine-state, <span class="Constant">3/waiting</span> assert <span class="Constant">5</span>:boolean/waiting?, <span class="Constant">[ </span> <span class="Constant">F read-move-file: routine failed to pause after coming up (before any keys were pressed)]</span> - <span class="Constant">1</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:shared:sink:character, <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:shared:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:shared:sink:character, <span class="Constant">97/a</span> + <span class="Constant">1</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:sink:character, <span class="Constant">10/newline</span> + <span class="Constant">1</span>:address:sink:character<span class="Special"> <- </span>write <span class="Constant">1</span>:address:sink:character, <span class="Constant">97/a</span> restart <span class="Constant">3</span>:number/routine wait-for-routine <span class="Constant">3</span>:number ] @@ -562,36 +560,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> make-move board:address:shared:array:address:shared:array:character, m:address:shared:move<span class="muRecipe"> -> </span>board:address:shared:array:address:shared:array:character [ +<span class="muRecipe">def</span> make-move board:address:array:address:array:character, m:address:move<span class="muRecipe"> -> </span>board:address:array:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> from-file:number<span class="Special"> <- </span>get *m, <span class="Constant">from-file:offset</span> from-rank:number<span class="Special"> <- </span>get *m, <span class="Constant">from-rank:offset</span> to-file:number<span class="Special"> <- </span>get *m, <span class="Constant">to-file:offset</span> to-rank:number<span class="Special"> <- </span>get *m, <span class="Constant">to-rank:offset</span> - f:address:shared:array:character<span class="Special"> <- </span>index *board, from-file - src:address:character/square<span class="Special"> <- </span>index-address *f, from-rank - f<span class="Special"> <- </span>index *board, to-file - dest:address:character/square<span class="Special"> <- </span>index-address *f, to-rank - *dest<span class="Special"> <- </span>copy *src - *src<span class="Special"> <- </span>copy <span class="Constant">32/space</span> + from-f:address:array:character<span class="Special"> <- </span>index *board, from-file + to-f:address:array:character<span class="Special"> <- </span>index *board, to-file + src:character/square<span class="Special"> <- </span>index *from-f, from-rank + *to-f<span class="Special"> <- </span>put-index *to-f, to-rank, src + *from-f<span class="Special"> <- </span>put-index *from-f, from-rank, <span class="Constant">32/space</span> ] <span class="muScenario">scenario</span> making-a-move [ assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span> run [ - <span class="Constant">2</span>:address:shared:array:address:shared:array:character/board<span class="Special"> <- </span>initial-position - <span class="Constant">3</span>:address:shared:move<span class="Special"> <- </span>new <span class="Constant">move:type</span> - <span class="Constant">4</span>:address:number<span class="Special"> <- </span>get-address *<span class="Constant">3</span>:address:shared:move, <span class="Constant">from-file:offset</span> - *<span class="Constant">4</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">6/g</span> - <span class="Constant">5</span>:address:number<span class="Special"> <- </span>get-address *<span class="Constant">3</span>:address:shared:move, <span class="Constant">from-rank:offset</span> - *<span class="Constant">5</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">1/'2'</span> - <span class="Constant">6</span>:address:number<span class="Special"> <- </span>get-address *<span class="Constant">3</span>:address:shared:move, <span class="Constant">to-file:offset</span> - *<span class="Constant">6</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">6/g</span> - <span class="Constant">7</span>:address:number<span class="Special"> <- </span>get-address *<span class="Constant">3</span>:address:shared:move, <span class="Constant">to-rank:offset</span> - *<span class="Constant">7</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">3/'4'</span> - <span class="Constant">2</span>:address:shared:array:address:shared:array:character/board<span class="Special"> <- </span>make-move <span class="Constant">2</span>:address:shared:array:address:shared:array:character/board, <span class="Constant">3</span>:address:shared:move - screen:address:shared:screen<span class="Special"> <- </span>print-board screen:address:shared:screen, <span class="Constant">2</span>:address:shared:array:address:shared:array:character/board + <span class="Constant">2</span>:address:array:address:array:character/board<span class="Special"> <- </span>initial-position + <span class="Constant">3</span>:address:move<span class="Special"> <- </span>new <span class="Constant">move:type</span> + *<span class="Constant">3</span>:address:move<span class="Special"> <- </span>merge <span class="Constant">6/g</span>, <span class="Constant">1/'2'</span>, <span class="Constant">6/g</span>, <span class="Constant">3/'4'</span> + <span class="Constant">2</span>:address:array:address:array:character/board<span class="Special"> <- </span>make-move <span class="Constant">2</span>:address:array:address:array:character/board, <span class="Constant">3</span>:address:move + screen:address:screen<span class="Special"> <- </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/counters.mu.html b/html/counters.mu.html index bdb9cf58..e59b934c 100644 --- a/html/counters.mu.html +++ b/html/counters.mu.html @@ -31,24 +31,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># example program: maintain multiple counters with isolated lexical scopes</span> <span class="Comment"># (spaces)</span> -<span class="muRecipe">def</span> new-counter n:number<span class="muRecipe"> -> </span><span class="Constant">default-space</span>:address:shared:array:location [ +<span class="muRecipe">def</span> new-counter n:number<span class="muRecipe"> -> </span><span class="Constant">default-space</span>:address:array:location [ <span class="Constant">default-space</span><span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> <span class="Constant">load-ingredients</span> ] -<span class="muRecipe">def</span> increment-counter outer:address:shared:array:location/names:new-counter, x:number<span class="muRecipe"> -> </span>n:number/space:<span class="Constant">1</span> [ +<span class="muRecipe">def</span> increment-counter outer:address:array:location/names:new-counter, x:number<span class="muRecipe"> -> </span>n:number/space:<span class="Constant">1</span> [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Constant">0</span>:address:shared:array:location/names:new-counter<span class="Special"> <- </span>copy outer <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span> + <span class="Constant">0</span>:address:array:location/names:new-counter<span class="Special"> <- </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"> <- </span>add n/space:<span class="Constant">1</span>, x ] <span class="muRecipe">def</span> main [ <span class="Constant">local-scope</span> <span class="Comment"># counter A</span> - a:address:shared:array:location<span class="Special"> <- </span>new-counter <span class="Constant">34</span> + a:address:array:location<span class="Special"> <- </span>new-counter <span class="Constant">34</span> <span class="Comment"># counter B</span> - b:address:shared:array:location<span class="Special"> <- </span>new-counter <span class="Constant">23</span> + b:address:array:location<span class="Special"> <- </span>new-counter <span class="Constant">23</span> <span class="Comment"># increment both by 2 but in different ways</span> increment-counter a, <span class="Constant">1</span> b-value:number<span class="Special"> <- </span>increment-counter b, <span class="Constant">2</span> diff --git a/html/edit/001-editor.mu.html b/html/edit/001-editor.mu.html index ce68b7be..62f21806 100644 --- a/html/edit/001-editor.mu.html +++ b/html/edit/001-editor.mu.html @@ -37,7 +37,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># temporary main for this layer: just render the given text at the given</span> <span class="Comment"># screen dimensions, then stop</span> -<span class="muRecipe">def!</span> main text:address:shared:array:character [ +<span class="muRecipe">def!</span> main text:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> open-console @@ -51,8 +51,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initially-prints-text-to-screen [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</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> @@ -64,11 +64,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> editor-data [ <span class="Comment"># editable text: doubly linked list of characters (head contains a special sentinel)</span> - data:address:shared:duplex-list:character - top-of-screen:address:shared:duplex-list:character - bottom-of-screen:address:shared:duplex-list:character + data:address:duplex-list:character + top-of-screen:address:duplex-list:character + bottom-of-screen:address:duplex-list:character <span class="Comment"># location before cursor inside data</span> - before-cursor:address:shared:duplex-list:character + before-cursor:address:duplex-list:character <span class="Comment"># raw bounds of display area on screen</span> <span class="Comment"># always displays from row 1 (leaving row 0 for a menu) and at most until bottom of screen</span> @@ -83,38 +83,30 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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">def</span> new-editor s:address:shared:array:character, screen:address:shared:screen, left:number, right:number<span class="muRecipe"> -> </span>result:address:shared:editor-data, screen:address:shared:screen [ +<span class="muRecipe">def</span> new-editor s:address:array:character, screen:address:screen, left:number, right:number<span class="muRecipe"> -> </span>result:address:editor-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># no clipping of bounds</span> right<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> result<span class="Special"> <- </span>new <span class="Constant">editor-data:type</span> <span class="Comment"># initialize screen-related fields</span> - x:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">left:offset</span> - *x<span class="Special"> <- </span>copy left - x<span class="Special"> <- </span>get-address *result, <span class="Constant">right:offset</span> - *x<span class="Special"> <- </span>copy right - <span class="Comment"># initialize cursor</span> - x<span class="Special"> <- </span>get-address *result, <span class="Constant">cursor-row:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">1/top</span> - x<span class="Special"> <- </span>get-address *result, <span class="Constant">cursor-column:offset</span> - *x<span class="Special"> <- </span>copy left - init:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *init<span class="Special"> <- </span>push <span class="Constant">167/§</span>, <span class="Constant">0/tail</span> - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *result, <span class="Constant">top-of-screen:offset</span> - *top-of-screen<span class="Special"> <- </span>copy *init - y:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *result, <span class="Constant">before-cursor:offset</span> - *y<span class="Special"> <- </span>copy *init + *result<span class="Special"> <- </span>put *result, <span class="Constant">left:offset</span>, left + *result<span class="Special"> <- </span>put *result, <span class="Constant">right:offset</span>, right + <span class="Comment"># initialize cursor coordinates</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">cursor-row:offset</span>, <span class="Constant">1/top</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">cursor-column:offset</span>, left + <span class="Comment"># initialize empty contents</span> + init:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">167/§</span>, <span class="Constant">0/tail</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">data:offset</span>, init + *result<span class="Special"> <- </span>put *result, <span class="Constant">top-of-screen:offset</span>, init + *result<span class="Special"> <- </span>put *result, <span class="Constant">before-cursor:offset</span>, init result<span class="Special"> <- </span>insert-text result, s - <span class="Comment"># initialize cursor to top of screen</span> - y<span class="Special"> <- </span>get-address *result, <span class="Constant">before-cursor:offset</span> - *y<span class="Special"> <- </span>copy *init <span class="Comment"># initial render to screen, just for some old tests</span> _, _, screen, result<span class="Special"> <- </span>render screen, result <span class="Constant"> <editor-initialization></span> ] -<span class="muRecipe">def</span> insert-text editor:address:shared:editor-data, text:address:shared:array:character<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> insert-text editor:address:editor-data, text:address:array:character<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># early exit if text is empty</span> @@ -123,7 +115,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">return-unless</span> len, editor/same-as-ingredient:<span class="Constant">0</span> idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># now we can start appending the rest, character by character</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + curr:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>greater-or-equal idx, len <span class="muControl">break-if</span> done? @@ -140,8 +132,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">0/data</span>, screen:address:shared:screen, <span class="Constant">2/left</span>, <span class="Constant">5/right</span> - <span class="Constant">2</span>:editor-data<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:shared:editor-data + <span class="Constant">1</span>:address:editor-data<span class="Special"> <- </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"> <- </span>copy *<span class="Constant">1</span>:address:editor-data ] memory-should-contain [ <span class="Comment"># 2 (data) <- just the § sentinel</span> @@ -164,7 +156,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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">def</span> render screen:address:shared:screen, editor:address:shared:editor-data<span class="muRecipe"> -> </span>last-row:number, last-column:number, screen:address:shared:screen, editor:address:shared:editor-data [ +<span class="muRecipe">def</span> render screen:address:screen, editor:address:editor-data<span class="muRecipe"> -> </span>last-row:number, last-column:number, screen:address:screen, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> editor, <span class="Constant">1/top</span>, <span class="Constant">0/left</span>, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span> @@ -172,17 +164,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen-height:number<span class="Special"> <- </span>screen-height screen right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> <span class="Comment"># traversing editor</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - prev:address:shared:duplex-list:character<span class="Special"> <- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev</span> + curr:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + prev:address:duplex-list:character<span class="Special"> <- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev</span> curr<span class="Special"> <- </span>next curr <span class="Comment"># traversing screen</span> <span class="Constant"> +render-loop-initialization</span> color:number<span class="Special"> <- </span>copy <span class="Constant">7/white</span> row:number<span class="Special"> <- </span>copy <span class="Constant">1/top</span> column:number<span class="Special"> <- </span>copy left - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> screen<span class="Special"> <- </span>move-cursor screen, row, column <span class="Delimiter">{</span> <span class="Constant"> +next-character</span> @@ -193,11 +185,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span> <span class="Comment"># the current character.</span> <span class="Delimiter">{</span> - at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, cursor-row <span class="muControl">break-unless</span> at-cursor-row? - at-cursor?:boolean<span class="Special"> <- </span>equal column, *cursor-column + at-cursor?:boolean<span class="Special"> <- </span>equal column, cursor-column <span class="muControl">break-unless</span> at-cursor? - *before-cursor<span class="Special"> <- </span>copy prev + before-cursor<span class="Special"> <- </span>copy prev <span class="Delimiter">}</span> c:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> <span class="Constant"> <character-c-received></span> @@ -207,12 +199,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> newline? <span class="Comment"># adjust cursor if necessary</span> <span class="Delimiter">{</span> - at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, cursor-row <span class="muControl">break-unless</span> at-cursor-row? - left-of-cursor?:boolean<span class="Special"> <- </span>lesser-than column, *cursor-column + left-of-cursor?:boolean<span class="Special"> <- </span>lesser-than column, cursor-column <span class="muControl">break-unless</span> left-of-cursor? - *cursor-column<span class="Special"> <- </span>copy column - *before-cursor<span class="Special"> <- </span>prev curr + cursor-column<span class="Special"> <- </span>copy column + before-cursor<span class="Special"> <- </span>prev curr <span class="Delimiter">}</span> <span class="Comment"># clear rest of line in this window</span> clear-line-delimited screen, column, right @@ -245,26 +237,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># save first character off-screen</span> - bottom-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">bottom-of-screen:offset</span> - *bottom-of-screen<span class="Special"> <- </span>copy curr + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">bottom-of-screen:offset</span>, curr <span class="Comment"># is cursor to the right of the last line? move to end</span> <span class="Delimiter">{</span> - at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row - cursor-outside-line?:boolean<span class="Special"> <- </span>lesser-or-equal column, *cursor-column + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, cursor-row + cursor-outside-line?:boolean<span class="Special"> <- </span>lesser-or-equal column, cursor-column before-cursor-on-same-line?:boolean<span class="Special"> <- </span>and at-cursor-row?, cursor-outside-line? - above-cursor-row?:boolean<span class="Special"> <- </span>lesser-than row, *cursor-row + above-cursor-row?:boolean<span class="Special"> <- </span>lesser-than row, cursor-row before-cursor?:boolean<span class="Special"> <- </span>or before-cursor-on-same-line?, above-cursor-row? <span class="muControl">break-unless</span> before-cursor? - *cursor-row<span class="Special"> <- </span>copy row - *cursor-column<span class="Special"> <- </span>copy column - *before-cursor<span class="Special"> <- </span>copy prev + cursor-row<span class="Special"> <- </span>copy row + cursor-column<span class="Special"> <- </span>copy column + before-cursor<span class="Special"> <- </span>copy prev <span class="Delimiter">}</span> - bottom:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">bottom:offset</span> - *bottom<span class="Special"> <- </span>copy row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">bottom:offset</span>, row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor <span class="muControl">return</span> row, column, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span> ] -<span class="muRecipe">def</span> clear-line-delimited screen:address:shared:screen, column:number, right:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> clear-line-delimited screen:address:screen, column:number, right:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> space:character<span class="Special"> <- </span>copy <span class="Constant">32/space</span> @@ -283,7 +276,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> clear-screen-from screen:address:shared:screen, row:number, column:number, left:number, right:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> clear-screen-from screen:address:screen, row:number, column:number, left:number, right:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if it's the real screen, use the optimized primitive</span> @@ -299,7 +292,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">return</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">def</span> clear-rest-of-screen screen:address:shared:screen, row:number, left:number, right:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> clear-rest-of-screen screen:address:screen, row:number, left:number, right:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> row<span class="Special"> <- </span>add row, <span class="Constant">1</span> @@ -318,9 +311,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initially-prints-multiple-lines [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <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> @@ -333,8 +326,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initially-handles-offsets [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <span class="Constant">1/left</span>, <span class="Constant">5/right</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</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> @@ -346,9 +339,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initially-prints-multiple-lines-at-offset [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <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> @@ -361,8 +354,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initially-wraps-long-lines [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def]</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> @@ -381,8 +374,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initially-wraps-barely-long-lines [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</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> @@ -403,10 +396,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-initializes-empty-text [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -424,10 +417,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> render-colors-comments [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant"># de</span> <span class="Constant">f]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <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> @@ -505,10 +498,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> render-colors-assignment [ assume-screen <span class="Constant">8/width</span>, <span class="Constant">5/height</span> run [ - s:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d <- e</span> <span class="Constant">f]</span> - new-editor s:address:shared:array:character, screen:address:shared:screen, <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 c13b901b..a9f02220 100644 --- a/html/edit/002-typing.mu.html +++ b/html/edit/002-typing.mu.html @@ -37,16 +37,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># temporary main: interactive editor</span> <span class="Comment"># hit ctrl-c to exit</span> -<span class="muRecipe">def!</span> main text:address:shared:array:character [ +<span class="muRecipe">def!</span> main text:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> open-console - editor:address:shared:editor-data<span class="Special"> <- </span>new-editor text, <span class="Constant">0/screen</span>, <span class="Constant">5/left</span>, <span class="Constant">45/right</span> + editor:address:editor-data<span class="Special"> <- </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">def</span> editor-event-loop screen:address:shared:screen, console:address:shared:console, editor:address:shared:editor-data<span class="muRecipe"> -> </span>screen:address:shared:screen, console:address:shared:console, editor:address:shared:editor-data [ +<span class="muRecipe">def</span> editor-event-loop screen:address:screen, console:address:console, editor:address:editor-data<span class="muRecipe"> -> </span>screen:address:screen, console:address:console, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -55,20 +55,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> screen<span class="Special"> <- </span>move-cursor screen, cursor-row, cursor-column - e:event, console:address:shared:console, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-event console + e:event, console:address:console, found?:boolean, quit?:boolean<span class="Special"> <- </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> <span class="Comment"># 'touch' event</span> - t:address:touch-event<span class="Special"> <- </span>maybe-convert e, <span class="Constant">touch:variant</span> + t:touch-event, is-touch?:boolean<span class="Special"> <- </span>maybe-convert e, <span class="Constant">touch:variant</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> t - move-cursor-in-editor screen, editor, *t + <span class="muControl">break-unless</span> is-touch? + move-cursor-in-editor screen, editor, t <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> <span class="Comment"># keyboard events</span> <span class="Delimiter">{</span> - <span class="muControl">break-if</span> t + <span class="muControl">break-if</span> is-touch? screen, editor, go-render?:boolean<span class="Special"> <- </span>handle-keyboard-event screen, editor, e <span class="Delimiter">{</span> <span class="muControl">break-unless</span> go-render? @@ -80,7 +80,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># process click, return if it was on current editor</span> -<span class="muRecipe">def</span> move-cursor-in-editor screen:address:shared:screen, editor:address:shared:editor-data, t:touch-event<span class="muRecipe"> -> </span>in-focus?:boolean, editor:address:shared:editor-data [ +<span class="muRecipe">def</span> move-cursor-in-editor screen:address:screen, editor:address:editor-data, t:touch-event<span class="muRecipe"> -> </span>in-focus?:boolean, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> editor, <span class="Constant">0/false</span> @@ -105,7 +105,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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">def</span> snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, target-row:number, target-column:number<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> snap-cursor screen:address:screen, editor:address:editor-data, target-row:number, target-column:number<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> editor @@ -113,16 +113,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> screen-height:number<span class="Special"> <- </span>screen-height screen <span class="Comment"># count newlines until screen row</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - prev:address:shared:duplex-list:character<span class="Special"> <- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev</span> + curr:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + prev:address:duplex-list:character<span class="Special"> <- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev</span> curr<span class="Special"> <- </span>next curr row:number<span class="Special"> <- </span>copy <span class="Constant">1/top</span> column:number<span class="Special"> <- </span>copy left - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - *cursor-row<span class="Special"> <- </span>copy target-row - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - *cursor-column<span class="Special"> <- </span>copy target-column - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, target-row + cursor-row:number<span class="Special"> <- </span>copy target-row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, target-column + cursor-column:number<span class="Special"> <- </span>copy target-column + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *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 @@ -132,11 +132,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span> <span class="Comment"># the current character.</span> <span class="Delimiter">{</span> - at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, cursor-row <span class="muControl">break-unless</span> at-cursor-row? - at-cursor?:boolean<span class="Special"> <- </span>equal column, *cursor-column + at-cursor?:boolean<span class="Special"> <- </span>equal column, cursor-column <span class="muControl">break-unless</span> at-cursor? - *before-cursor<span class="Special"> <- </span>copy prev + before-cursor<span class="Special"> <- </span>copy prev + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor <span class="Delimiter">}</span> c:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> <span class="Delimiter">{</span> @@ -145,12 +146,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> newline? <span class="Comment"># adjust cursor if necessary</span> <span class="Delimiter">{</span> - at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, cursor-row <span class="muControl">break-unless</span> at-cursor-row? - left-of-cursor?:boolean<span class="Special"> <- </span>lesser-than column, *cursor-column + left-of-cursor?:boolean<span class="Special"> <- </span>lesser-than column, cursor-column <span class="muControl">break-unless</span> left-of-cursor? - *cursor-column<span class="Special"> <- </span>copy column - *before-cursor<span class="Special"> <- </span>copy prev + cursor-column<span class="Special"> <- </span>copy column + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + before-cursor<span class="Special"> <- </span>copy prev + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor <span class="Delimiter">}</span> <span class="Comment"># skip to next line</span> row<span class="Special"> <- </span>add row, <span class="Constant">1</span> @@ -176,21 +179,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Comment"># is cursor to the right of the last line? move to end</span> <span class="Delimiter">{</span> - at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row - cursor-outside-line?:boolean<span class="Special"> <- </span>lesser-or-equal column, *cursor-column + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, cursor-row + cursor-outside-line?:boolean<span class="Special"> <- </span>lesser-or-equal column, cursor-column before-cursor-on-same-line?:boolean<span class="Special"> <- </span>and at-cursor-row?, cursor-outside-line? - above-cursor-row?:boolean<span class="Special"> <- </span>lesser-than row, *cursor-row + above-cursor-row?:boolean<span class="Special"> <- </span>lesser-than row, cursor-row before-cursor?:boolean<span class="Special"> <- </span>or before-cursor-on-same-line?, above-cursor-row? <span class="muControl">break-unless</span> before-cursor? - *cursor-row<span class="Special"> <- </span>copy row - *cursor-column<span class="Special"> <- </span>copy column - *before-cursor<span class="Special"> <- </span>copy prev + cursor-row<span class="Special"> <- </span>copy row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>copy column + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + before-cursor<span class="Special"> <- </span>copy prev + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor <span class="Delimiter">}</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">def</span> handle-keyboard-event screen:address:shared:screen, editor:address:shared:editor-data, e:event<span class="muRecipe"> -> </span>screen:address:shared:screen, editor:address:shared:editor-data, go-render?:boolean [ +<span class="muRecipe">def</span> handle-keyboard-event screen:address:screen, editor:address:editor-data, e:event<span class="muRecipe"> -> </span>screen:address:screen, editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> @@ -199,56 +205,58 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen-height:number<span class="Special"> <- </span>screen-height screen left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - save-row:number<span class="Special"> <- </span>copy *cursor-row - save-column:number<span class="Special"> <- </span>copy *cursor-column + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + save-row:number<span class="Special"> <- </span>copy cursor-row + save-column:number<span class="Special"> <- </span>copy cursor-column <span class="Comment"># character</span> <span class="Delimiter">{</span> - c:address:character<span class="Special"> <- </span>maybe-convert e, <span class="Constant">text:variant</span> - <span class="muControl">break-unless</span> c + c:character, is-unicode?:boolean<span class="Special"> <- </span>maybe-convert e, <span class="Constant">text:variant</span> + <span class="muControl">break-unless</span> is-unicode? trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[handle-keyboard-event: special character]</span> <span class="Comment"># exceptions for special characters go here</span> <span class="Constant"> <handle-special-character></span> <span class="Comment"># ignore any other special characters</span> - regular-character?:boolean<span class="Special"> <- </span>greater-or-equal *c, <span class="Constant">32/space</span> + regular-character?:boolean<span class="Special"> <- </span>greater-or-equal c, <span class="Constant">32/space</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-unless</span> regular-character? <span class="Comment"># otherwise type it in</span> <span class="Constant"> <insert-character-begin></span> - editor, screen, go-render?:boolean<span class="Special"> <- </span>insert-at-cursor editor, *c, screen + editor, screen, go-render?:boolean<span class="Special"> <- </span>insert-at-cursor editor, c, screen <span class="Constant"> <insert-character-end></span> <span class="muControl">return</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"> <- </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> + k:number, is-keycode?:boolean<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span> + assert is-keycode?, <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"> <handle-special-key></span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> ] -<span class="muRecipe">def</span> insert-at-cursor editor:address:shared:editor-data, c:character, screen:address:shared:screen<span class="muRecipe"> -> </span>editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [ +<span class="muRecipe">def</span> insert-at-cursor editor:address:editor-data, c:character, screen:address:screen<span class="muRecipe"> -> </span>editor:address:editor-data, screen:address:screen, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - insert c, *before-cursor - *before-cursor<span class="Special"> <- </span>next *before-cursor - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + insert c, before-cursor + before-cursor<span class="Special"> <- </span>next before-cursor + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> - save-row:number<span class="Special"> <- </span>copy *cursor-row - save-column:number<span class="Special"> <- </span>copy *cursor-column + save-row:number<span class="Special"> <- </span>copy cursor-row + save-column:number<span class="Special"> <- </span>copy cursor-column screen-width:number<span class="Special"> <- </span>screen-width screen screen-height:number<span class="Special"> <- </span>screen-height screen <span class="Comment"># occasionally we'll need to mess with the cursor</span> <span class="Constant"> <insert-character-special-case></span> <span class="Comment"># but mostly we'll just move the cursor right</span> - *cursor-column<span class="Special"> <- </span>add *cursor-column, <span class="Constant">1</span> - next:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + cursor-column<span class="Special"> <- </span>add cursor-column, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + next:address:duplex-list:character<span class="Special"> <- </span>next 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"> <- </span>equal next, <span class="Constant">0/null</span> @@ -266,9 +274,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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"> <- </span>greater-or-equal *cursor-column, screen-width + at-right?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column, screen-width <span class="muControl">break-if</span> at-right? - curr:address:shared:duplex-list:character<span class="Special"> <- </span>copy *before-cursor + curr:address:duplex-list:character<span class="Special"> <- </span>copy before-cursor move-cursor screen, save-row, save-column curr-column:number<span class="Special"> <- </span>copy save-column <span class="Delimiter">{</span> @@ -294,7 +302,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># helper for tests</span> -<span class="muRecipe">def</span> editor-render screen:address:shared:screen, editor:address:shared:editor-data<span class="muRecipe"> -> </span>screen:address:shared:screen, editor:address:shared:editor-data [ +<span class="muRecipe">def</span> editor-render screen:address:screen, editor:address:editor-data<span class="muRecipe"> -> </span>screen:address:screen, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> @@ -309,12 +317,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -326,17 +334,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -353,16 +361,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> @@ -373,17 +381,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> @@ -394,17 +402,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> @@ -415,19 +423,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Comment"># editor occupies only left half of screen</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ <span class="Comment"># click on right half of screen</span> left-click <span class="Constant">3</span>, <span class="Constant">8</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -444,18 +452,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ <span class="Comment"># click on first, 'menu' row</span> left-click <span class="Constant">0</span>, <span class="Constant">3</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># no change to cursor</span> memory-should-contain [ @@ -466,15 +474,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -487,9 +495,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -498,7 +506,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[d]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -511,16 +519,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">5</span> <span class="Comment"># right of last line</span> type <span class="Constant">[d]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -533,17 +541,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">5</span> <span class="Comment"># right of non-last line</span> type <span class="Constant">[e]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -557,16 +565,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">3</span>, <span class="Constant">5</span> <span class="Comment"># below all text</span> type <span class="Constant">[d]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -579,17 +587,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-4 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">3</span>, <span class="Constant">5</span> <span class="Comment"># below all text</span> type <span class="Constant">[e]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -603,17 +611,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-6 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">3</span>, <span class="Constant">5</span> <span class="Comment"># below all text</span> type <span class="Constant">[ef]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -627,14 +635,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -648,15 +656,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -671,7 +679,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[f]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -686,19 +694,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-wraps-line-on-insert-2 [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefg</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefg</span> <span class="Constant">defg]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Comment"># type more text at the start</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">0</span> type <span class="Constant">[abc]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor is not wrapped</span> memory-should-contain [ @@ -720,14 +728,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="Comment"># if we're at the column just before the wrap indicator</span> wrap-column:number<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> - at-wrap?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-column, wrap-column + at-wrap?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column, wrap-column <span class="muControl">break-unless</span> at-wrap? - *cursor-column<span class="Special"> <- </span>subtract *cursor-column, wrap-column - *cursor-column<span class="Special"> <- </span>add *cursor-column, left - *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> + cursor-column<span class="Special"> <- </span>subtract cursor-column, wrap-column + cursor-column<span class="Special"> <- </span>add cursor-column, left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + cursor-row<span class="Special"> <- </span>add cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row <span class="Comment"># if we're out of the screen, scroll down</span> <span class="Delimiter">{</span> - below-screen?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, screen-height + below-screen?:boolean<span class="Special"> <- </span>greater-or-equal cursor-row, screen-height <span class="muControl">break-unless</span> below-screen? <span class="Constant"> <scroll-down></span> <span class="Delimiter">}</span> @@ -738,16 +748,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">4</span> <span class="Comment"># line is full; no wrap icon yet</span> type <span class="Constant">[f]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -764,16 +774,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">3</span> <span class="Comment"># right before the wrap icon</span> type <span class="Constant">[f]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -790,16 +800,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">2/left</span>, <span class="Constant">7/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -821,20 +831,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">after</span> <span class="Constant"><editor-initialization></span> [ - indent?:address:boolean<span class="Special"> <- </span>get-address *result, <span class="Constant">indent?:offset</span> - *indent?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">indent?:offset</span>, <span class="Constant">1/true</span> ] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> assume-console [ type <span class="Constant">[0</span> <span class="Constant">1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -847,7 +856,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - newline?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">10/newline</span> + newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> <span class="muControl">break-unless</span> newline? <span class="Constant"> <insert-enter-begin></span> editor<span class="Special"> <- </span>insert-new-line-and-indent editor, screen @@ -857,33 +866,37 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> insert-new-line-and-indent editor:address:shared:editor-data, screen:address:shared:screen<span class="muRecipe"> -> </span>editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [ +<span class="muRecipe">def</span> insert-new-line-and-indent editor:address:editor-data, screen:address:screen<span class="muRecipe"> -> </span>editor:address:editor-data, screen:address:screen, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> screen-height:number<span class="Special"> <- </span>screen-height screen <span class="Comment"># insert newline</span> - insert <span class="Constant">10/newline</span>, *before-cursor - *before-cursor<span class="Special"> <- </span>next *before-cursor - *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> - *cursor-column<span class="Special"> <- </span>copy left + insert <span class="Constant">10/newline</span>, before-cursor + before-cursor<span class="Special"> <- </span>next before-cursor + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + cursor-row<span class="Special"> <- </span>add cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="Comment"># maybe scroll</span> <span class="Delimiter">{</span> - below-screen?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, screen-height <span class="Comment"># must be equal, never greater</span> + below-screen?:boolean<span class="Special"> <- </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"> <scroll-down></span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> - *cursor-row<span class="Special"> <- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + cursor-row<span class="Special"> <- </span>subtract cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row <span class="Delimiter">}</span> <span class="Comment"># indent if necessary</span> indent?:boolean<span class="Special"> <- </span>get *editor, <span class="Constant">indent?:offset</span> <span class="muControl">return-unless</span> indent? - d:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> - end-of-previous-line:address:shared:duplex-list:character<span class="Special"> <- </span>prev *before-cursor + d:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + end-of-previous-line:address:duplex-list:character<span class="Special"> <- </span>prev before-cursor indent:number<span class="Special"> <- </span>line-indent end-of-previous-line, d i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> @@ -897,7 +910,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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">def</span> line-indent curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character<span class="muRecipe"> -> </span>result:number [ +<span class="muRecipe">def</span> line-indent curr:address:duplex-list:character, start:address:duplex-list:character<span class="muRecipe"> -> </span>result:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -929,14 +942,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -949,8 +962,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> assume-console [ press enter ] @@ -962,7 +975,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> . .</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -976,10 +989,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-inserts-indent-after-newline [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> <span class="Constant"> cd</span> <span class="Constant">ef]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> @@ -987,9 +1000,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor should be below start of previous line</span> memory-should-contain [ @@ -1000,10 +1013,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-skips-indent-around-paste [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> <span class="Constant"> cd</span> <span class="Constant">ef]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> @@ -1012,9 +1025,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press <span class="Constant">65506</span> <span class="Comment"># end paste</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor should be below start of previous line</span> memory-should-contain [ @@ -1025,10 +1038,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - paste-start?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65507/paste-start</span> + paste-start?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65507/paste-start</span> <span class="muControl">break-unless</span> paste-start? - indent?:address:boolean<span class="Special"> <- </span>get-address *editor, <span class="Constant">indent?:offset</span> - *indent?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">indent?:offset</span>, <span class="Constant">0/false</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -1036,10 +1048,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - paste-end?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65506/paste-end</span> + paste-end?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65506/paste-end</span> <span class="muControl">break-unless</span> paste-end? - indent?:address:boolean<span class="Special"> <- </span>get-address *editor, <span class="Constant">indent?:offset</span> - *indent?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">indent?:offset</span>, <span class="Constant">1/true</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -1047,7 +1058,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="SalientComment">## helpers</span> -<span class="muRecipe">def</span> draw-horizontal screen:address:shared:screen, row:number, x:number, right:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> draw-horizontal screen:address:screen, row:number, x:number, right:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> style:character, style-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> diff --git a/html/edit/003-shortcuts.mu.html b/html/edit/003-shortcuts.mu.html index 28d802b2..61a2f538 100644 --- a/html/edit/003-shortcuts.mu.html +++ b/html/edit/003-shortcuts.mu.html @@ -41,14 +41,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-inserts-two-spaces-on-tab [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># just one character in final line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> <span class="Constant">cd]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> assume-console [ press tab ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -59,7 +59,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - tab?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">9/tab</span> + tab?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">9/tab</span> <span class="muControl">break-unless</span> tab? <span class="Constant"> <insert-character-begin></span> editor, screen, go-render?:boolean<span class="Special"> <- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen @@ -74,18 +74,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> press backspace ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -102,10 +102,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - delete-previous-character?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">8/backspace</span> + delete-previous-character?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">8/backspace</span> <span class="muControl">break-unless</span> delete-previous-character? <span class="Constant"> <backspace-character-begin></span> - editor, screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character<span class="Special"> <- </span>delete-before-cursor editor, screen + editor, screen, go-render?:boolean, backspaced-cell:address:duplex-list:character<span class="Special"> <- </span>delete-before-cursor editor, screen <span class="Constant"> <backspace-character-end></span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -114,21 +114,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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">def</span> delete-before-cursor editor:address:shared:editor-data, screen:address:shared:screen<span class="muRecipe"> -> </span>editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character [ +<span class="muRecipe">def</span> delete-before-cursor editor:address:editor-data, screen:address:screen<span class="muRecipe"> -> </span>editor:address:editor-data, screen:address:screen, go-render?:boolean, backspaced-cell:address:duplex-list:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - data:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + data:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> <span class="Comment"># if at start of text (before-cursor at § sentinel), return</span> - prev:address:shared:duplex-list:character<span class="Special"> <- </span>prev *before-cursor + prev:address:duplex-list:character<span class="Special"> <- </span>prev before-cursor go-render?, backspaced-cell<span class="Special"> <- </span>copy <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span> <span class="muControl">return-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"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> editor, scroll?:boolean<span class="Special"> <- </span>move-cursor-coordinates-left editor - backspaced-cell:address:shared:duplex-list:character<span class="Special"> <- </span>copy *before-cursor - data<span class="Special"> <- </span>remove *before-cursor, data <span class="Comment"># will also neatly trim next/prev pointers in backspaced-cell/*before-cursor</span> - *before-cursor<span class="Special"> <- </span>copy prev + backspaced-cell:address:duplex-list:character<span class="Special"> <- </span>copy before-cursor + data<span class="Special"> <- </span>remove before-cursor, data <span class="Comment"># will also neatly trim next/prev pointers in backspaced-cell/before-cursor</span> + before-cursor<span class="Special"> <- </span>copy prev + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return-if</span> scroll? screen-width:number<span class="Special"> <- </span>screen-width screen @@ -140,7 +141,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">return-unless</span> same-row? left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + curr:address:duplex-list:character<span class="Special"> <- </span>next before-cursor screen<span class="Special"> <- </span>move-cursor screen, cursor-row, cursor-column curr-column:number<span class="Special"> <- </span>copy cursor-column <span class="Delimiter">{</span> @@ -164,28 +165,30 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> ] -<span class="muRecipe">def</span> move-cursor-coordinates-left editor:address:shared:editor-data<span class="muRecipe"> -> </span>editor:address:shared:editor-data, go-render?:boolean [ +<span class="muRecipe">def</span> move-cursor-coordinates-left editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - before-cursor:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> <span class="Comment"># if not at left margin, move one character left</span> <span class="Delimiter">{</span> - at-left-margin?:boolean<span class="Special"> <- </span>equal *cursor-column, left + at-left-margin?:boolean<span class="Special"> <- </span>equal cursor-column, left <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"> <- </span>subtract *cursor-column, <span class="Constant">1</span> + cursor-column<span class="Special"> <- </span>subtract cursor-column, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return</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"> <- </span>equal *cursor-row, <span class="Constant">1</span> <span class="Comment"># exclude menu bar</span> + top-of-screen?:boolean<span class="Special"> <- </span>equal cursor-row, <span class="Constant">1</span> <span class="Comment"># exclude menu bar</span> go-render?:boolean<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> top-of-screen? - *cursor-row<span class="Special"> <- </span>subtract *cursor-row, <span class="Constant">1</span> + cursor-row<span class="Special"> <- </span>subtract cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> top-of-screen? @@ -199,7 +202,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + d:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> end-of-line:number<span class="Special"> <- </span>previous-line-length before-cursor, d right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> width:number<span class="Special"> <- </span>subtract right, left @@ -207,23 +210,26 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="muControl">break-unless</span> wrap? _, column-offset:number<span class="Special"> <- </span>divide-with-remainder end-of-line, width - *cursor-column<span class="Special"> <- </span>add left, column-offset + cursor-column<span class="Special"> <- </span>add left, column-offset + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> wrap? - *cursor-column<span class="Special"> <- </span>add left, end-of-line + cursor-column<span class="Special"> <- </span>add left, end-of-line + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="Delimiter">}</span> <span class="muControl">return</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"> <- </span>get *editor, <span class="Constant">right:offset</span> - *cursor-column<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> <span class="Comment"># leave room for wrap icon</span> + cursor-column<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> <span class="Comment"># leave room for wrap icon</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column ] <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">def</span> previous-line-length curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character<span class="muRecipe"> -> </span>result:number [ +<span class="muRecipe">def</span> previous-line-length curr:address:duplex-list:character, start:address:duplex-list:character<span class="muRecipe"> -> </span>result:number [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -246,17 +252,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-clears-last-line-on-backspace [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># just one character in final line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> <span class="Constant">cd]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -273,10 +279,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def</span> <span class="Constant">ghi jkl]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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 [ @@ -284,7 +290,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press backspace ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data + 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 [ @@ -299,9 +305,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def ghij]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">8/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def ghij]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> @@ -316,7 +322,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press backspace ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data + 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 [ @@ -332,15 +338,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -354,7 +360,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press delete ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -367,21 +373,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - delete-next-character?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65522/delete</span> + delete-next-character?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65522/delete</span> <span class="muControl">break-unless</span> delete-next-character? <span class="Constant"> <delete-character-begin></span> - editor, screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character<span class="Special"> <- </span>delete-at-cursor editor, screen + editor, screen, go-render?:boolean, deleted-cell:address:duplex-list:character<span class="Special"> <- </span>delete-at-cursor editor, screen <span class="Constant"> <delete-character-end></span> <span class="muControl">return</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> delete-at-cursor editor:address:shared:editor-data, screen:address:shared:screen<span class="muRecipe"> -> </span>editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character [ +<span class="muRecipe">def</span> delete-at-cursor editor:address:editor-data, screen:address:screen<span class="muRecipe"> -> </span>editor:address:editor-data, screen:address:screen, go-render?:boolean, deleted-cell:address:duplex-list:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - data:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> - deleted-cell:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + data:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + deleted-cell:address:duplex-list:character<span class="Special"> <- </span>next before-cursor go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-unless</span> deleted-cell currc:character<span class="Special"> <- </span>get *deleted-cell, <span class="Constant">value:offset</span> @@ -390,11 +396,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return-if</span> deleted-newline? <span class="Comment"># wasn't a newline? render rest of line</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor <span class="Comment"># refresh after remove above</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - screen<span class="Special"> <- </span>move-cursor screen, *cursor-row, *cursor-column - curr-column:number<span class="Special"> <- </span>copy *cursor-column + curr:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="Comment"># refresh after remove above</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + screen<span class="Special"> <- </span>move-cursor screen, cursor-row, cursor-column + curr-column:number<span class="Special"> <- </span>copy cursor-column screen-width:number<span class="Special"> <- </span>screen-width screen <span class="Delimiter">{</span> <span class="Comment"># hit right margin? give up and let caller render</span> @@ -421,16 +427,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> assume-console [ press right-arrow type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -443,28 +449,29 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - move-to-next-character?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65514/right-arrow</span> + move-to-next-character?:boolean<span class="Special"> <- </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:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + next-cursor:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="muControl">break-unless</span> next-cursor <span class="Comment"># scan to next character</span> <span class="Constant"> <move-cursor-begin></span> - *before-cursor<span class="Special"> <- </span>copy next-cursor + before-cursor<span class="Special"> <- </span>copy next-cursor + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor editor, go-render?:boolean<span class="Special"> <- </span>move-cursor-coordinates-right editor, screen-height - screen<span class="Special"> <- </span>move-cursor screen, *cursor-row, *cursor-column + screen<span class="Special"> <- </span>move-cursor screen, cursor-row, cursor-column undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">2/right-arrow</span> <span class="Constant"> <move-cursor-end></span> <span class="muControl">return</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> move-cursor-coordinates-right editor:address:shared:editor-data, screen-height:number<span class="muRecipe"> -> </span>editor:address:shared:editor-data, go-render?:boolean [ +<span class="muRecipe">def</span> move-cursor-coordinates-right editor:address:editor-data, screen-height:number<span class="muRecipe"> -> </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - before-cursor:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor <span class="Constant">before-cursor:offset</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> <span class="Comment"># if crossed a newline, move cursor to start of next row</span> @@ -472,13 +479,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color old-cursor-character:character<span class="Special"> <- </span>get *before-cursor, <span class="Constant">value:offset</span> was-at-newline?:boolean<span class="Special"> <- </span>equal old-cursor-character, <span class="Constant">10/newline</span> <span class="muControl">break-unless</span> was-at-newline? - *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> - *cursor-column<span class="Special"> <- </span>copy left - below-screen?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, screen-height <span class="Comment"># must be equal</span> + cursor-row<span class="Special"> <- </span>add cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + below-screen?:boolean<span class="Special"> <- </span>greater-or-equal cursor-row, screen-height <span class="Comment"># must be equal</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-unless</span> below-screen? <span class="Constant"> <scroll-down></span> - *cursor-row<span class="Special"> <- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + cursor-row<span class="Special"> <- </span>subtract cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -486,34 +496,38 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="Comment"># if we're at the column just before the wrap indicator</span> wrap-column:number<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> - at-wrap?:boolean<span class="Special"> <- </span>equal *cursor-column, wrap-column + at-wrap?:boolean<span class="Special"> <- </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:shared:duplex-list:character<span class="Special"> <- </span>next before-cursor + next:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="muControl">break-unless</span> next next-character:character<span class="Special"> <- </span>get *next, <span class="Constant">value:offset</span> newline?:boolean<span class="Special"> <- </span>equal next-character, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> newline? - *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> - *cursor-column<span class="Special"> <- </span>copy left - below-screen?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, screen-height <span class="Comment"># must be equal</span> + cursor-row<span class="Special"> <- </span>add cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + below-screen?:boolean<span class="Special"> <- </span>greater-or-equal cursor-row, screen-height <span class="Comment"># must be equal</span> <span class="muControl">return-unless</span> below-screen?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span> <span class="Constant"> <scroll-down></span> - *cursor-row<span class="Special"> <- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + cursor-row<span class="Special"> <- </span>subtract cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># otherwise move cursor one character right</span> - *cursor-column<span class="Special"> <- </span>add *cursor-column, <span class="Constant">1</span> + cursor-column<span class="Special"> <- </span>add cursor-column, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column go-render?<span class="Special"> <- </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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -523,7 +537,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press right-arrow <span class="Comment"># next line</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -531,7 +545,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -545,10 +559,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">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 press right-arrow @@ -557,7 +571,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -570,18 +584,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + 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">3</span> press right-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -600,9 +614,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + 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> assume-console [ @@ -610,9 +624,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press right-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -623,9 +637,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press right-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -636,18 +650,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">1/left</span>, <span class="Constant">6/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">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 [ left-click <span class="Constant">1</span>, <span class="Constant">4</span> press right-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -665,10 +679,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-at-end-of-line [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -677,7 +691,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -696,9 +710,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">2</span> @@ -706,7 +720,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -719,16 +733,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - move-to-previous-character?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65515/left-arrow</span> + move-to-previous-character?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65515/left-arrow</span> <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:shared:duplex-list:character<span class="Special"> <- </span>prev *before-cursor + prev:address:duplex-list:character<span class="Special"> <- </span>prev before-cursor go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-unless</span> prev <span class="Constant"> <move-cursor-begin></span> editor, go-render?<span class="Special"> <- </span>move-cursor-coordinates-left editor - *before-cursor<span class="Special"> <- </span>copy prev + before-cursor<span class="Special"> <- </span>copy prev + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">1/left-arrow</span> <span class="Constant"> <move-cursor-end></span> <span class="muControl">return</span> @@ -738,10 +753,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize editor with two lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -749,9 +764,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press left-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -763,11 +778,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize editor with three lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> <span class="Comment"># the cursor)</span> @@ -777,7 +792,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -791,11 +806,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-3 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -804,7 +819,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -820,11 +835,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-4 [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> d] - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -833,7 +848,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -848,9 +863,9 @@ d] <span class="muScenario">scenario</span> editor-moves-across-screen-lines-across-wrap-with-left-arrow [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize editor with a wrapping line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -865,9 +880,9 @@ d] press left-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># previous row</span> @@ -879,10 +894,10 @@ d] <span class="muScenario">scenario</span> editor-moves-across-screen-lines-to-wrapping-line-with-left-arrow [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize editor with a wrapping line followed by a second line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -897,9 +912,9 @@ d] press left-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># previous row</span> @@ -911,10 +926,10 @@ d] <span class="muScenario">scenario</span> editor-moves-across-screen-lines-to-non-wrapping-line-with-left-arrow [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize editor with a line on the verge of wrapping, followed by a second line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd</span> <span class="Constant">e]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data <span class="Constant"> $clear-trace</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -929,9 +944,9 @@ d] press left-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># previous row</span> @@ -946,19 +961,19 @@ d] <span class="muScenario">scenario</span> editor-moves-to-previous-line-with-up-arrow [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">2</span>, <span class="Constant">1</span> press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -969,7 +984,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -982,7 +997,7 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - move-to-previous-line?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65517/up-arrow</span> + move-to-previous-line?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65517/up-arrow</span> <span class="muControl">break-unless</span> move-to-previous-line? <span class="Constant"> <move-cursor-begin></span> editor, go-render?<span class="Special"> <- </span>move-to-previous-line editor @@ -992,28 +1007,28 @@ d] <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> move-to-previous-line editor:address:shared:editor-data<span class="muRecipe"> -> </span>editor:address:shared:editor-data, go-render?:boolean [ +<span class="muRecipe">def</span> move-to-previous-line editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> - already-at-top?:boolean<span class="Special"> <- </span>lesser-or-equal *cursor-row, <span class="Constant">1/top</span> + already-at-top?:boolean<span class="Special"> <- </span>lesser-or-equal cursor-row, <span class="Constant">1/top</span> <span class="Delimiter">{</span> <span class="Comment"># if cursor not at top, move it</span> <span class="muControl">break-if</span> already-at-top? <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:shared:duplex-list:character<span class="Special"> <- </span>copy *before-cursor + curr:address:duplex-list:character<span class="Special"> <- </span>copy before-cursor <span class="Delimiter">{</span> - old:address:shared:duplex-list:character<span class="Special"> <- </span>copy curr + old:address:duplex-list:character<span class="Special"> <- </span>copy curr c2:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> at-newline?:boolean<span class="Special"> <- </span>equal c2, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> at-newline? - curr:address:shared:duplex-list:character<span class="Special"> <- </span>before-previous-line curr, editor + curr:address:duplex-list:character<span class="Special"> <- </span>before-previous-line curr, editor no-motion?:boolean<span class="Special"> <- </span>equal curr, old go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-if</span> no-motion? @@ -1025,22 +1040,27 @@ d] go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-if</span> no-motion? <span class="Delimiter">}</span> - *before-cursor<span class="Special"> <- </span>copy curr - *cursor-row<span class="Special"> <- </span>subtract *cursor-row, <span class="Constant">1</span> + before-cursor<span class="Special"> <- </span>copy curr + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + cursor-row<span class="Special"> <- </span>subtract cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row <span class="Comment"># scan ahead to right column or until end of line</span> - target-column:number<span class="Special"> <- </span>copy *cursor-column - *cursor-column<span class="Special"> <- </span>copy left + target-column:number<span class="Special"> <- </span>copy cursor-column + cursor-column<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-column, target-column + done?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column, target-column <span class="muControl">break-if</span> done? - curr:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + curr:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="muControl">break-unless</span> curr currc:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> at-newline?:boolean<span class="Special"> <- </span>equal currc, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> at-newline? <span class="Comment">#</span> - *before-cursor<span class="Special"> <- </span>copy curr - *cursor-column<span class="Special"> <- </span>add *cursor-column, <span class="Constant">1</span> + before-cursor<span class="Special"> <- </span>copy curr + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + cursor-column<span class="Special"> <- </span>add cursor-column, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="muControl">loop</span> <span class="Delimiter">}</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> @@ -1057,19 +1077,19 @@ d] <span class="muScenario">scenario</span> editor-adjusts-column-at-previous-line [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">2</span>, <span class="Constant">3</span> press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1080,7 +1100,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1093,19 +1113,19 @@ d] <span class="muScenario">scenario</span> editor-adjusts-column-at-empty-line [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new [ <span class="muRecipe">def</span>] - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">2</span>, <span class="Constant">3</span> press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1116,7 +1136,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1130,11 +1150,11 @@ d] <span class="muScenario">scenario</span> editor-moves-to-previous-line-from-left-margin [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># start out with three lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1142,9 +1162,9 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -1155,7 +1175,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1170,19 +1190,19 @@ d] <span class="muScenario">scenario</span> editor-moves-to-next-line-with-down-arrow [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># ..and ends at (2, 0)</span> memory-should-contain [ @@ -1194,7 +1214,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1207,7 +1227,7 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - move-to-next-line?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65516/down-arrow</span> + move-to-next-line?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65516/down-arrow</span> <span class="muControl">break-unless</span> move-to-next-line? <span class="Constant"> <move-cursor-begin></span> editor, go-render?<span class="Special"> <- </span>move-to-next-line editor, screen-height @@ -1217,47 +1237,52 @@ d] <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> move-to-next-line editor:address:shared:editor-data, screen-height:number<span class="muRecipe"> -> </span>editor:address:shared:editor-data, go-render?:boolean [ +<span class="muRecipe">def</span> move-to-next-line editor:address:editor-data, screen-height:number<span class="muRecipe"> -> </span>editor:address:editor-data, go-render?:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> last-line:number<span class="Special"> <- </span>subtract screen-height, <span class="Constant">1</span> - already-at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, last-line + already-at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal cursor-row, last-line <span class="Delimiter">{</span> <span class="Comment"># if cursor not at bottom, move it</span> <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"> <- </span>subtract right, left - next-line:address:shared:duplex-list:character<span class="Special"> <- </span>before-start-of-next-line *before-cursor, max + next-line:address:duplex-list:character<span class="Special"> <- </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> - no-motion?:boolean<span class="Special"> <- </span>equal next-line, *before-cursor + no-motion?:boolean<span class="Special"> <- </span>equal next-line, before-cursor <span class="muControl">break-unless</span> no-motion? - scroll?:boolean<span class="Special"> <- </span>greater-than *cursor-row, <span class="Constant">1</span> + scroll?:boolean<span class="Special"> <- </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> go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return</span> <span class="Delimiter">}</span> - *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> - *before-cursor<span class="Special"> <- </span>copy next-line - target-column:number<span class="Special"> <- </span>copy *cursor-column - *cursor-column<span class="Special"> <- </span>copy left + cursor-row<span class="Special"> <- </span>add cursor-row, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + before-cursor<span class="Special"> <- </span>copy next-line + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + target-column:number<span class="Special"> <- </span>copy cursor-column + cursor-column<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-column, target-column + done?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column, target-column <span class="muControl">break-if</span> done? - curr:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + curr:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="muControl">break-unless</span> curr currc:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> at-newline?:boolean<span class="Special"> <- </span>equal currc, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> at-newline? <span class="Comment">#</span> - *before-cursor<span class="Special"> <- </span>copy curr - *cursor-column<span class="Special"> <- </span>add *cursor-column, <span class="Constant">1</span> + before-cursor<span class="Special"> <- </span>copy curr + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + cursor-column<span class="Special"> <- </span>add cursor-column, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="muControl">loop</span> <span class="Delimiter">}</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> @@ -1270,19 +1295,19 @@ d] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">de]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">3</span> press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -1293,7 +1318,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1308,10 +1333,10 @@ d] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1319,9 +1344,9 @@ d] press ctrl-a ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to start of line</span> memory-should-contain [ @@ -1333,7 +1358,7 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - move-to-start-of-line?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">1/ctrl-a</span> + move-to-start-of-line?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">1/ctrl-a</span> <span class="muControl">break-unless</span> move-to-start-of-line? <span class="Constant"> <move-cursor-begin></span> move-to-start-of-line editor @@ -1346,7 +1371,7 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - move-to-start-of-line?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65521/home</span> + move-to-start-of-line?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65521/home</span> <span class="muControl">break-unless</span> move-to-start-of-line? <span class="Constant"> <move-cursor-begin></span> move-to-start-of-line editor @@ -1357,35 +1382,36 @@ d] <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> move-to-start-of-line editor:address:shared:editor-data<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> move-to-start-of-line editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># update cursor column</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - *cursor-column<span class="Special"> <- </span>copy left + cursor-column:number<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="Comment"># update before-cursor</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - init:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + init:address:duplex-list:character<span class="Special"> <- </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"> <- </span>equal *before-cursor, init + at-start-of-text?:boolean<span class="Special"> <- </span>equal before-cursor, init <span class="muControl">break-if</span> at-start-of-text? - prev:character<span class="Special"> <- </span>get **before-cursor, <span class="Constant">value:offset</span> + prev:character<span class="Special"> <- </span>get *before-cursor, <span class="Constant">value:offset</span> at-start-of-line?:boolean<span class="Special"> <- </span>equal prev, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> at-start-of-line? - *before-cursor<span class="Special"> <- </span>prev *before-cursor - assert *before-cursor, <span class="Constant">[move-to-start-of-line tried to move before start of text]</span> + before-cursor<span class="Special"> <- </span>prev before-cursor + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + assert before-cursor, <span class="Constant">[move-to-start-of-line tried to move before start of text]</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1393,9 +1419,9 @@ d] press ctrl-a ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to start of line</span> memory-should-contain [ @@ -1407,9 +1433,9 @@ d] <span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> <span class="Constant"> $clear-trace</span> <span class="Comment"># start on second line, press 'home'</span> assume-console [ @@ -1417,9 +1443,9 @@ d] press home ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to start of line</span> memory-should-contain [ @@ -1431,10 +1457,10 @@ d] <span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1442,9 +1468,9 @@ d] press home ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to start of line</span> memory-should-contain [ @@ -1458,10 +1484,10 @@ d] <span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1469,9 +1495,9 @@ d] press ctrl-e ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to end of line</span> memory-should-contain [ @@ -1484,9 +1510,9 @@ d] type <span class="Constant">[z]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1504,7 +1530,7 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - move-to-end-of-line?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">5/ctrl-e</span> + move-to-end-of-line?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">5/ctrl-e</span> <span class="muControl">break-unless</span> move-to-end-of-line? <span class="Constant"> <move-cursor-begin></span> move-to-end-of-line editor @@ -1517,7 +1543,7 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - move-to-end-of-line?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65520/end</span> + move-to-end-of-line?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65520/end</span> <span class="muControl">break-unless</span> move-to-end-of-line? <span class="Constant"> <move-cursor-begin></span> move-to-end-of-line editor @@ -1528,30 +1554,32 @@ d] <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> move-to-end-of-line editor:address:shared:editor-data<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> move-to-end-of-line editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + cursor-column:number<span class="Special"> <- </span>get *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:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + next:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="muControl">break-unless</span> next <span class="Comment"># end of text</span> nextc:character<span class="Special"> <- </span>get *next, <span class="Constant">value:offset</span> at-end-of-line?:boolean<span class="Special"> <- </span>equal nextc, <span class="Constant">10/newline</span> <span class="muControl">break-if</span> at-end-of-line? - *before-cursor<span class="Special"> <- </span>copy next - *cursor-column<span class="Special"> <- </span>add *cursor-column, <span class="Constant">1</span> + before-cursor<span class="Special"> <- </span>copy next + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + cursor-column<span class="Special"> <- </span>add cursor-column, <span class="Constant">1</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1559,9 +1587,9 @@ d] press ctrl-e ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to end of line</span> memory-should-contain [ @@ -1573,10 +1601,10 @@ d] <span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1584,9 +1612,9 @@ d] press end ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to end of line</span> memory-should-contain [ @@ -1598,10 +1626,10 @@ d] <span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end-2 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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> assume-console [ @@ -1609,9 +1637,9 @@ d] press end ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves to end of line</span> memory-should-contain [ @@ -1625,16 +1653,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1648,24 +1676,24 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - delete-to-start-of-line?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">21/ctrl-u</span> + delete-to-start-of-line?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">21/ctrl-u</span> <span class="muControl">break-unless</span> delete-to-start-of-line? <span class="Constant"> <delete-to-start-of-line-begin></span> - deleted-cells:address:shared:duplex-list:character<span class="Special"> <- </span>delete-to-start-of-line editor + deleted-cells:address:duplex-list:character<span class="Special"> <- </span>delete-to-start-of-line editor <span class="Constant"> <delete-to-start-of-line-end></span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> delete-to-start-of-line editor:address:shared:editor-data<span class="muRecipe"> -> </span>result:address:shared:duplex-list:character, editor:address:shared:editor-data [ +<span class="muRecipe">def</span> delete-to-start-of-line editor:address:editor-data<span class="muRecipe"> -> </span>result:address:duplex-list:character, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># compute range to delete</span> - init:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - start:address:shared:duplex-list:character<span class="Special"> <- </span>copy *before-cursor - end:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor + init:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + start:address:duplex-list:character<span class="Special"> <- </span>copy before-cursor + end:address:duplex-list:character<span class="Special"> <- </span>next before-cursor <span class="Delimiter">{</span> at-start-of-text?:boolean<span class="Special"> <- </span>equal start, init <span class="muControl">break-if</span> at-start-of-text? @@ -1677,27 +1705,27 @@ d] <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># snip it out</span> - result:address:shared:duplex-list:character<span class="Special"> <- </span>next start + result:address:duplex-list:character<span class="Special"> <- </span>next start remove-between start, end <span class="Comment"># adjust cursor</span> - *before-cursor<span class="Special"> <- </span>copy start + before-cursor<span class="Special"> <- </span>copy start + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> - *cursor-column<span class="Special"> <- </span>copy left + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, left ] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1711,16 +1739,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-3 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1734,16 +1762,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-start-of-final-line-with-ctrl-u [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1759,16 +1787,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1782,22 +1810,22 @@ d] <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - delete-to-end-of-line?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">11/ctrl-k</span> + delete-to-end-of-line?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">11/ctrl-k</span> <span class="muControl">break-unless</span> delete-to-end-of-line? <span class="Constant"> <delete-to-end-of-line-begin></span> - deleted-cells:address:shared:duplex-list:character<span class="Special"> <- </span>delete-to-end-of-line editor + deleted-cells:address:duplex-list:character<span class="Special"> <- </span>delete-to-end-of-line editor <span class="Constant"> <delete-to-end-of-line-end></span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> delete-to-end-of-line editor:address:shared:editor-data<span class="muRecipe"> -> </span>result:address:shared:duplex-list:character, editor:address:shared:editor-data [ +<span class="muRecipe">def</span> delete-to-end-of-line editor:address:editor-data<span class="muRecipe"> -> </span>result:address:duplex-list:character, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># compute range to delete</span> - start:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> - end:address:shared:duplex-list:character<span class="Special"> <- </span>next start + start:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + end:address:duplex-list:character<span class="Special"> <- </span>next start <span class="Delimiter">{</span> at-end-of-text?:boolean<span class="Special"> <- </span>equal end, <span class="Constant">0/null</span> <span class="muControl">break-if</span> at-end-of-text? @@ -1814,16 +1842,16 @@ d] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1837,16 +1865,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-3 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1860,16 +1888,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-4 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1883,16 +1911,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-5 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1906,16 +1934,16 @@ d] <span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-6 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[123</span> <span class="Constant">456]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1933,11 +1961,11 @@ d] <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> <span class="Comment"># initialize editor with >3 lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -1950,7 +1978,7 @@ d] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1963,13 +1991,14 @@ d] <span class="muRecipe">after</span> <span class="Constant"><scroll-down></span> [ trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[scroll down]</span> - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> max:number<span class="Special"> <- </span>subtract right, left - old-top:address:shared:duplex-list:character<span class="Special"> <- </span>copy *top-of-screen - *top-of-screen<span class="Special"> <- </span>before-start-of-next-line *top-of-screen, max - no-movement?:boolean<span class="Special"> <- </span>equal old-top, *top-of-screen + old-top:address:duplex-list:character<span class="Special"> <- </span>copy top-of-screen + top-of-screen<span class="Special"> <- </span>before-start-of-next-line top-of-screen, max + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top-of-screen + no-movement?:boolean<span class="Special"> <- </span>equal old-top, top-of-screen go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-if</span> no-movement? ] @@ -1977,11 +2006,11 @@ d] <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">def</span> before-start-of-next-line original:address:shared:duplex-list:character, max:number<span class="muRecipe"> -> </span>curr:address:shared:duplex-list:character [ +<span class="muRecipe">def</span> before-start-of-next-line original:address:duplex-list:character, max:number<span class="muRecipe"> -> </span>curr:address:duplex-list:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> count:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>copy original + curr:address:duplex-list:character<span class="Special"> <- </span>copy original <span class="Comment"># skip the initial newline if it exists</span> <span class="Delimiter">{</span> c:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> @@ -2010,11 +2039,11 @@ d] assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span> <span class="Comment"># other lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> <span class="Constant">g</span> <span class="Constant">h</span> <span class="Constant">i]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> @@ -2027,7 +2056,7 @@ d] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2042,18 +2071,18 @@ d] <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> <span class="Comment"># editor starts with a long line wrapping twice</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefghij</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefghij</span> <span class="Constant">k</span> <span class="Constant">l</span> <span class="Constant">m]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2067,7 +2096,7 @@ d] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2082,19 +2111,19 @@ d] <span class="Comment"># screen has 1 line for menu + 3 lines</span> assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains a long line in the third line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdef]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen scrolls</span> screen-should-contain [ @@ -2112,19 +2141,19 @@ d] <span class="muScenario">scenario</span> editor-scrolls-down-on-newline [ assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span> <span class="Comment"># position cursor after last line and type newline</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">4</span> type [ ] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen scrolls</span> screen-should-contain [ @@ -2143,19 +2172,19 @@ d] <span class="Comment"># screen has 1 line for menu + 3 lines</span> assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains a wrapped line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdefgh]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen scrolls</span> screen-should-contain [ @@ -2174,20 +2203,20 @@ d] <span class="Comment"># screen has 1 line for menu + 3 lines</span> assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains more lines than can fit on screen</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen scrolls</span> screen-should-contain [ @@ -2204,10 +2233,10 @@ d] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">de]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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 [ @@ -2215,9 +2244,9 @@ d] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen should scroll, moving cursor to end of text</span> memory-should-contain [ @@ -2228,7 +2257,7 @@ d] type <span class="Constant">[0]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2243,9 +2272,9 @@ d] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen stops scrolling because cursor is already at top</span> memory-should-contain [ @@ -2257,7 +2286,7 @@ d] type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2271,14 +2300,14 @@ d] <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> <span class="Comment"># initialize editor with a few pages of lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f</span> <span class="Constant">g]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># scroll down one page and one line</span> assume-console [ press page-down @@ -2286,7 +2315,7 @@ d] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2303,11 +2332,11 @@ d] <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> <span class="Comment"># initialize editor with >3 lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2320,7 +2349,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2333,10 +2362,11 @@ d] <span class="muRecipe">after</span> <span class="Constant"><scroll-up></span> [ trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[scroll up]</span> - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:shared:duplex-list:character<span class="Special"> <- </span>copy *top-of-screen - *top-of-screen<span class="Special"> <- </span>before-previous-line *top-of-screen, editor - no-movement?:boolean<span class="Special"> <- </span>equal old-top, *top-of-screen + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + old-top:address:duplex-list:character<span class="Special"> <- </span>copy top-of-screen + top-of-screen<span class="Special"> <- </span>before-previous-line top-of-screen, editor + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top-of-screen + no-movement?:boolean<span class="Special"> <- </span>equal old-top, top-of-screen go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">return-if</span> no-movement? ] @@ -2344,10 +2374,10 @@ d] <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">def</span> before-previous-line in:address:shared:duplex-list:character, editor:address:shared:editor-data<span class="muRecipe"> -> </span>out:address:shared:duplex-list:character [ +<span class="muRecipe">def</span> before-previous-line in:address:duplex-list:character, editor:address:editor-data<span class="muRecipe"> -> </span>out:address:duplex-list:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>copy in + curr:address:duplex-list:character<span class="Special"> <- </span>copy in c:character<span class="Special"> <- </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> @@ -2355,12 +2385,12 @@ d] left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> max-line-length:number<span class="Special"> <- </span>subtract right, left, <span class="Constant">-1/exclusive-right</span>, <span class="Constant">1/wrap-icon</span> - sentinel:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + sentinel:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> len:number<span class="Special"> <- </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:shared:duplex-list:character<span class="Special"> <- </span>prev curr + prev:address:duplex-list:character<span class="Special"> <- </span>prev curr <span class="muControl">return-unless</span> prev, curr <span class="muControl">return</span> prev <span class="Delimiter">}</span> @@ -2376,7 +2406,7 @@ d] <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>greater-or-equal count, max <span class="muControl">break-if</span> done? - prev:address:shared:duplex-list:character<span class="Special"> <- </span>prev curr + prev:address:duplex-list:character<span class="Special"> <- </span>prev curr <span class="muControl">break-unless</span> prev curr<span class="Special"> <- </span>copy prev count<span class="Special"> <- </span>add count, <span class="Constant">1</span> @@ -2390,11 +2420,11 @@ d] assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span> <span class="Comment"># other lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> <span class="Constant">g</span> <span class="Constant">h</span> <span class="Constant">i]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> @@ -2406,7 +2436,7 @@ d] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2419,7 +2449,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2434,17 +2464,17 @@ d] <span class="Comment"># screen has 1 line for menu + 4 lines</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Comment"># editor starts with a long line wrapping twice, occupying 3 of the 4 lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefghij</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefghij</span> <span class="Constant">k</span> <span class="Constant">l</span> <span class="Constant">m]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># position cursor at top of second page</span> assume-console [ press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2458,7 +2488,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2473,7 +2503,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2488,7 +2518,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2507,11 +2537,11 @@ d] assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span> <span class="Comment"># other lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef</span> <span class="Constant">g</span> <span class="Constant">h</span> <span class="Constant">i]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .abcde↩ .</span> @@ -2523,7 +2553,7 @@ d] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2536,7 +2566,7 @@ d] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2551,18 +2581,18 @@ d] <span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-4 [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># initialize editor with some lines around an empty line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> c d e] - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">6/right</span> assume-console [ press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2574,7 +2604,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2586,7 +2616,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2600,18 +2630,18 @@ e] <span class="Comment"># screen has 1 line for menu + 3 lines</span> assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains >3 lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># position cursor at top of second page</span> assume-console [ press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2624,9 +2654,9 @@ e] press left-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen scrolls</span> screen-should-contain [ @@ -2645,11 +2675,11 @@ e] <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> <span class="Comment"># initialize editor with >3 lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2664,7 +2694,7 @@ e] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2678,7 +2708,7 @@ e] press up-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2693,11 +2723,11 @@ e] <span class="muScenario">scenario</span> editor-can-scroll [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2709,7 +2739,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2722,15 +2752,15 @@ e] <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - page-down?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">6/ctrl-f</span> + page-down?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">6/ctrl-f</span> <span class="muControl">break-unless</span> page-down? - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:shared:duplex-list:character<span class="Special"> <- </span>copy *top-of-screen + old-top:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Constant"> <move-cursor-begin></span> page-down editor undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">0/never</span> <span class="Constant"> <move-cursor-end></span> - no-movement?:boolean<span class="Special"> <- </span>equal *top-of-screen, old-top + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + no-movement?:boolean<span class="Special"> <- </span>equal top-of-screen, old-top go-render?<span class="Special"> <- </span>not no-movement? <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -2738,15 +2768,15 @@ e] <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - page-down?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65518/page-down</span> + page-down?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65518/page-down</span> <span class="muControl">break-unless</span> page-down? - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:shared:duplex-list:character<span class="Special"> <- </span>copy *top-of-screen + old-top:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Constant"> <move-cursor-begin></span> page-down editor undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">0/never</span> <span class="Constant"> <move-cursor-end></span> - no-movement?:boolean<span class="Special"> <- </span>equal *top-of-screen, old-top + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + no-movement?:boolean<span class="Special"> <- </span>equal top-of-screen, old-top go-render?<span class="Special"> <- </span>not no-movement? <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -2754,34 +2784,36 @@ e] <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">def</span> page-down editor:address:shared:editor-data<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> page-down editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if editor contents don't overflow screen, do nothing</span> - bottom-of-screen:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">bottom-of-screen:offset</span> + bottom-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">bottom-of-screen:offset</span> <span class="muControl">return-unless</span> bottom-of-screen <span class="Comment"># if not, position cursor at final character</span> - before-cursor:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> - *before-cursor<span class="Special"> <- </span>prev bottom-of-screen + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>prev bottom-of-screen + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor <span class="Comment"># keep one line in common with previous page</span> <span class="Delimiter">{</span> - last:character<span class="Special"> <- </span>get **before-cursor, <span class="Constant">value:offset</span> + last:character<span class="Special"> <- </span>get *before-cursor, <span class="Constant">value:offset</span> newline?:boolean<span class="Special"> <- </span>equal last, <span class="Constant">10/newline</span> <span class="muControl">break-unless</span> newline?:boolean - *before-cursor<span class="Special"> <- </span>prev *before-cursor + before-cursor<span class="Special"> <- </span>prev before-cursor + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor <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:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *top-of-screen<span class="Special"> <- </span>copy *before-cursor + before-cursor<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, before-cursor ] <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2793,7 +2825,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2808,11 +2840,11 @@ e] <span class="Comment"># screen has 1 line for menu + 3 lines for text</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains a long last line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <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:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -2825,7 +2857,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2841,9 +2873,9 @@ e] assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains a very long line that occupies last two lines of screen</span> <span class="Comment"># and still has something left over</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">bcdefgh]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -2856,7 +2888,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2871,11 +2903,11 @@ e] <span class="muScenario">scenario</span> editor-can-scroll-up [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2887,7 +2919,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2901,7 +2933,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2914,15 +2946,15 @@ e] <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - page-up?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">2/ctrl-b</span> + page-up?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">2/ctrl-b</span> <span class="muControl">break-unless</span> page-up? - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:shared:duplex-list:character<span class="Special"> <- </span>copy *top-of-screen + old-top:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Constant"> <move-cursor-begin></span> editor<span class="Special"> <- </span>page-up editor, screen-height undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">0/never</span> <span class="Constant"> <move-cursor-end></span> - no-movement?:boolean<span class="Special"> <- </span>equal *top-of-screen, old-top + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + no-movement?:boolean<span class="Special"> <- </span>equal top-of-screen, old-top go-render?<span class="Special"> <- </span>not no-movement? <span class="muControl">return</span> <span class="Delimiter">}</span> @@ -2930,33 +2962,34 @@ e] <span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ <span class="Delimiter">{</span> - page-up?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65519/page-up</span> + page-up?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65519/page-up</span> <span class="muControl">break-unless</span> page-up? - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - old-top:address:shared:duplex-list:character<span class="Special"> <- </span>copy *top-of-screen + old-top:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Constant"> <move-cursor-begin></span> editor<span class="Special"> <- </span>page-up editor, screen-height undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">0/never</span> <span class="Constant"> <move-cursor-end></span> - no-movement?:boolean<span class="Special"> <- </span>equal *top-of-screen, old-top + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + no-movement?:boolean<span class="Special"> <- </span>equal top-of-screen, old-top <span class="Comment"># don't bother re-rendering if nothing changed. todo: test this</span> go-render?<span class="Special"> <- </span>not no-movement? <span class="muControl">return</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> page-up editor:address:shared:editor-data, screen-height:number<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> page-up editor:address:editor-data, screen-height:number<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> max:number<span class="Special"> <- </span>subtract screen-height, <span class="Constant">1/menu-bar</span>, <span class="Constant">1/overlapping-line</span> count:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> <span class="Delimiter">{</span> done?:boolean<span class="Special"> <- </span>greater-or-equal count, max <span class="muControl">break-if</span> done? - prev:address:shared:duplex-list:character<span class="Special"> <- </span>before-previous-line *top-of-screen, editor + prev:address:duplex-list:character<span class="Special"> <- </span>before-previous-line top-of-screen, editor <span class="muControl">break-unless</span> prev - *top-of-screen<span class="Special"> <- </span>copy prev + top-of-screen<span class="Special"> <- </span>copy prev + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top-of-screen count<span class="Special"> <- </span>add count, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> @@ -2966,7 +2999,7 @@ e] <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> <span class="Comment"># initialize editor with 8 lines</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> @@ -2974,7 +3007,7 @@ e] <span class="Constant">f</span> <span class="Constant">g</span> <span class="Constant">h]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .a .</span> @@ -2987,7 +3020,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3001,7 +3034,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3015,7 +3048,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3030,7 +3063,7 @@ e] <span class="Comment"># screen has 1 line for menu + 5 lines for text</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">6/height</span> <span class="Comment"># editor contains a long line in the first page</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdefgh</span> <span class="Constant">i</span> @@ -3041,7 +3074,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:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -3058,7 +3091,7 @@ e] press down-arrow ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3074,7 +3107,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3092,9 +3125,9 @@ e] assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains a very long line that occupies last two lines of screen</span> <span class="Comment"># and still has something left over</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">bcdefgh]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> <span class="Comment"># some part of last line is not displayed</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -3107,7 +3140,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3121,7 +3154,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -3135,7 +3168,7 @@ e] <span class="muScenario">scenario</span> editor-can-scroll-up-past-nonempty-lines [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># text with empty line in second screen</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[axx</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[axx</span> <span class="Constant">bxx</span> <span class="Constant">cxx</span> <span class="Constant">dxx</span> @@ -3144,7 +3177,7 @@ e] <span class="Constant">gxx</span> <span class="Constant">hxx</span> <span class="Constant">]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .axx .</span> @@ -3155,7 +3188,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -3167,7 +3200,7 @@ e] press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -3180,7 +3213,7 @@ e] press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -3193,7 +3226,7 @@ e] <span class="muScenario">scenario</span> editor-can-scroll-up-past-empty-lines [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span> <span class="Comment"># text with empty line in second screen</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[axy</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[axy</span> <span class="Constant">bxy</span> <span class="Constant">cxy</span> @@ -3202,7 +3235,7 @@ exy fxy gxy ] - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">4/right</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .axy .</span> @@ -3213,7 +3246,7 @@ gxy press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -3225,7 +3258,7 @@ gxy press page-down ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -3238,7 +3271,7 @@ gxy press page-up ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 ca1057c4..c05d0127 100644 --- a/html/edit/004-programming-environment.mu.html +++ b/html/edit/004-programming-environment.mu.html @@ -41,22 +41,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def!</span> main [ <span class="Constant">local-scope</span> open-console - initial-recipe:address:shared:array:character<span class="Special"> <- </span>restore <span class="Constant">[recipes.mu]</span> - initial-sandbox:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + initial-recipe:address:array:character<span class="Special"> <- </span>restore <span class="Constant">[recipes.mu]</span> + initial-sandbox:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> hide-screen <span class="Constant">0/screen</span> - env:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox render-all <span class="Constant">0/screen</span>, env 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 [ - recipes:address:shared:editor-data - current-sandbox:address:shared:editor-data + recipes:address:editor-data + current-sandbox:address:editor-data sandbox-in-focus?:boolean <span class="Comment"># false => cursor in recipes; true => cursor in current-sandbox</span> ] -<span class="muRecipe">def</span> new-programming-environment screen:address:shared:screen, initial-recipe-contents:address:shared:array:character, initial-sandbox-contents:address:shared:array:character<span class="muRecipe"> -> </span>result:address:shared:programming-environment-data, screen:address:shared:screen [ +<span class="muRecipe">def</span> new-programming-environment screen:address:screen, initial-recipe-contents:address:array:character, initial-sandbox-contents:address:array:character<span class="muRecipe"> -> </span>result:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> width:number<span class="Special"> <- </span>screen-width screen @@ -73,21 +73,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color divider:number, _<span class="Special"> <- </span>divide-with-remainder width, <span class="Constant">2</span> draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span> <span class="Comment"># recipe editor on the left</span> - recipes:address:address:shared:editor-data<span class="Special"> <- </span>get-address *result, <span class="Constant">recipes:offset</span> - *recipes<span class="Special"> <- </span>new-editor initial-recipe-contents, screen, <span class="Constant">0/left</span>, divider/right + recipes:address:editor-data<span class="Special"> <- </span>new-editor initial-recipe-contents, screen, <span class="Constant">0/left</span>, divider/right <span class="Comment"># sandbox editor on the right</span> - new-left:number<span class="Special"> <- </span>add divider, <span class="Constant">1</span> - current-sandbox:address:address:shared:editor-data<span class="Special"> <- </span>get-address *result, <span class="Constant">current-sandbox:offset</span> - *current-sandbox<span class="Special"> <- </span>new-editor initial-sandbox-contents, screen, new-left, width/right + sandbox-left:number<span class="Special"> <- </span>add divider, <span class="Constant">1</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>new-editor initial-sandbox-contents, screen, sandbox-left, width/right + *result<span class="Special"> <- </span>put *result, <span class="Constant">recipes:offset</span>, recipes + *result<span class="Special"> <- </span>put *result, <span class="Constant">current-sandbox:offset</span>, current-sandbox + *result<span class="Special"> <- </span>put *result, <span class="Constant">sandbox-in-focus?:offset</span>, <span class="Constant">0/false</span> <span class="Constant"> <programming-environment-initialization></span> ] -<span class="muRecipe">def</span> event-loop screen:address:shared:screen, console:address:shared:console, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>screen:address:shared:screen, console:address:shared:console, env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> event-loop screen:address:screen, console:address:console, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, console:address:console, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - recipes:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> - sandbox-in-focus?:address:boolean<span class="Special"> <- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span> + recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + sandbox-in-focus?:boolean<span class="Special"> <- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span> <span class="Comment"># if we fall behind we'll stop updating the screen, but then we have to</span> <span class="Comment"># render the entire screen when we catch up.</span> <span class="Comment"># todo: test this</span> @@ -102,37 +103,38 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> <handle-event></span> <span class="Comment"># check for global events that will trigger regardless of which editor has focus</span> <span class="Delimiter">{</span> - k:address:number<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span> - <span class="muControl">break-unless</span> k + k:number, is-keycode?:boolean<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span> + <span class="muControl">break-unless</span> is-keycode? <span class="Constant"> <global-keypress></span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> - c:address:character<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">text:variant</span> - <span class="muControl">break-unless</span> c + c:character, is-unicode?:boolean<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">text:variant</span> + <span class="muControl">break-unless</span> is-unicode? <span class="Constant"> <global-type></span> <span class="Delimiter">}</span> <span class="Comment"># 'touch' event - send to both sides, see what picks it up</span> <span class="Delimiter">{</span> - t:address:touch-event<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">touch:variant</span> - <span class="muControl">break-unless</span> t + t:touch-event, is-touch?:boolean<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">touch:variant</span> + <span class="muControl">break-unless</span> is-touch? <span class="Comment"># ignore all but 'left-click' events for now</span> <span class="Comment"># todo: test this</span> - touch-type:number<span class="Special"> <- </span>get *t, <span class="Constant">type:offset</span> + touch-type:number<span class="Special"> <- </span>get t, <span class="Constant">type:offset</span> is-left-click?:boolean<span class="Special"> <- </span>equal touch-type, <span class="Constant">65513/mouse-left</span> <span class="muControl">loop-unless</span> is-left-click?, <span class="Constant">+next-event:label</span> <span class="Comment"># later exceptions for non-editor touches will go here</span> <span class="Constant"> <global-touch></span> <span class="Comment"># send to both editors</span> - _<span class="Special"> <- </span>move-cursor-in-editor screen, recipes, *t - *sandbox-in-focus?<span class="Special"> <- </span>move-cursor-in-editor screen, current-sandbox, *t - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + _<span class="Special"> <- </span>move-cursor-in-editor screen, recipes, t + sandbox-in-focus?:boolean<span class="Special"> <- </span>move-cursor-in-editor screen, current-sandbox, t + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox-in-focus?:offset</span>, sandbox-in-focus? + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> <span class="Comment"># 'resize' event - redraw editor</span> <span class="Comment"># todo: test this after supporting resize in assume-console</span> <span class="Delimiter">{</span> - r:address:resize-event<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">resize:variant</span> - <span class="muControl">break-unless</span> r + r:resize-event, is-resize?:boolean<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">resize:variant</span> + <span class="muControl">break-unless</span> is-resize? <span class="Comment"># if more events, we're still resizing; wait until we stop</span> more-events?:boolean<span class="Special"> <- </span>has-more-events? console <span class="Delimiter">{</span> @@ -150,8 +152,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># if it's not global and not a touch event, send to appropriate editor</span> <span class="Delimiter">{</span> hide-screen screen + sandbox-in-focus?:boolean<span class="Special"> <- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span> <span class="Delimiter">{</span> - <span class="muControl">break-if</span> *sandbox-in-focus? + <span class="muControl">break-if</span> sandbox-in-focus? screen, recipes, render?:boolean<span class="Special"> <- </span>handle-keyboard-event screen, recipes, e:event <span class="Comment"># refresh screen only if no more events</span> <span class="Comment"># if there are more events to process, wait for them to clear up, then make sure you render-all afterward.</span> @@ -179,7 +182,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> *sandbox-in-focus? + <span class="muControl">break-unless</span> sandbox-in-focus? screen, current-sandbox, render?:boolean<span class="Special"> <- </span>handle-keyboard-event screen, current-sandbox, e:event <span class="Comment"># refresh screen only if no more events</span> <span class="Comment"># if there are more events to process, wait for them to clear up, then make sure you render-all afterward.</span> @@ -207,48 +210,44 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Constant"> +finish-event</span> - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env show-screen screen <span class="Delimiter">}</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> resize screen:address:shared:screen, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>env:address:shared:programming-environment-data, screen:address:shared:screen [ +<span class="muRecipe">def</span> resize screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> clear-screen screen <span class="Comment"># update screen dimensions</span> width:number<span class="Special"> <- </span>screen-width screen divider:number, _<span class="Special"> <- </span>divide-with-remainder width, <span class="Constant">2</span> <span class="Comment"># update recipe editor</span> - recipes:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> - right:address:number<span class="Special"> <- </span>get-address *recipes, <span class="Constant">right:offset</span> - *right<span class="Special"> <- </span>subtract divider, <span class="Constant">1</span> + recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + right:number<span class="Special"> <- </span>subtract divider, <span class="Constant">1</span> + *recipes<span class="Special"> <- </span>put *recipes, <span class="Constant">right:offset</span>, right <span class="Comment"># reset cursor (later we'll try to preserve its position)</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *recipes, <span class="Constant">cursor-row:offset</span> - *cursor-row<span class="Special"> <- </span>copy <span class="Constant">1</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *recipes, <span class="Constant">cursor-column:offset</span> - *cursor-column<span class="Special"> <- </span>copy <span class="Constant">0</span> + *recipes<span class="Special"> <- </span>put *recipes, <span class="Constant">cursor-row:offset</span>, <span class="Constant">1</span> + *recipes<span class="Special"> <- </span>put *recipes, <span class="Constant">cursor-column:offset</span>, <span class="Constant">0</span> <span class="Comment"># update sandbox editor</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> - left:address:number<span class="Special"> <- </span>get-address *current-sandbox, <span class="Constant">left:offset</span> - right:address:number<span class="Special"> <- </span>get-address *current-sandbox, <span class="Constant">right:offset</span> - *left<span class="Special"> <- </span>add divider, <span class="Constant">1</span> - *right<span class="Special"> <- </span>subtract width, <span class="Constant">1</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + left:number<span class="Special"> <- </span>add divider, <span class="Constant">1</span> + *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">left:offset</span>, left + right:number<span class="Special"> <- </span>subtract width, <span class="Constant">1</span> + *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">right:offset</span>, right <span class="Comment"># reset cursor (later we'll try to preserve its position)</span> - cursor-row:address:number<span class="Special"> <- </span>get-address *current-sandbox, <span class="Constant">cursor-row:offset</span> - *cursor-row<span class="Special"> <- </span>copy <span class="Constant">1</span> - cursor-column:address:number<span class="Special"> <- </span>get-address *current-sandbox, <span class="Constant">cursor-column:offset</span> - *cursor-column<span class="Special"> <- </span>copy *left + *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">cursor-row:offset</span>, <span class="Constant">1</span> + *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">cursor-column:offset</span>, left ] <span class="muScenario">scenario</span> point-at-multiple-editors [ trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize both halves of screen</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># focus on both sides</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> @@ -256,11 +255,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># check cursor column in each</span> run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data - <span class="Constant">4</span>:address:shared:editor-data<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:programming-environment-data, <span class="Constant">recipes:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">4</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> - <span class="Constant">6</span>:address:shared:editor-data<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:programming-environment-data, <span class="Constant">current-sandbox:offset</span> - <span class="Constant">7</span>:number<span class="Special"> <- </span>get *<span class="Constant">6</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </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"> <- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span> + <span class="Constant">7</span>:number<span class="Special"> <- </span>get *<span class="Constant">6</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] memory-should-contain [ <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -272,10 +271,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># type one letter in each of them</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> @@ -284,11 +283,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data - <span class="Constant">4</span>:address:shared:editor-data<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:programming-environment-data, <span class="Constant">recipes:offset</span> - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">4</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> - <span class="Constant">6</span>:address:shared:editor-data<span class="Special"> <- </span>get *<span class="Constant">3</span>:address:shared:programming-environment-data, <span class="Constant">current-sandbox:offset</span> - <span class="Constant">7</span>:number<span class="Special"> <- </span>get *<span class="Constant">6</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + 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"> <- </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"> <- </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"> <- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span> + <span class="Constant">7</span>:number<span class="Special"> <- </span>get *<span class="Constant">6</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] screen-should-contain [ <span class="Constant"> . run (F4) . # this line has a different background, but we don't test that yet</span> @@ -303,7 +302,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># show the cursor at the right window</span> run [ <span class="Constant">8</span>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">8</span>:character/cursor + print screen:address:screen, <span class="Constant">8</span>:character/cursor ] screen-should-contain [ <span class="Constant"> . run (F4) .</span> @@ -317,10 +316,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># divider isn't messed up</span> screen-should-contain [ @@ -335,16 +334,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-in-focus-keeps-cursor [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># initialize programming environment and highlight cursor</span> assume-console <span class="Constant">[]</span> run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># is cursor at the right place?</span> screen-should-contain [ @@ -358,9 +357,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[z]</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># cursor should still be right</span> screen-should-contain [ @@ -375,11 +374,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊abc .</span> @@ -393,9 +392,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press backspace ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># cursor moves to end of old line</span> screen-should-contain [ @@ -406,7 +405,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> render-all screen:address:shared:screen, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>screen:address:shared:screen, env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> render-all screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[render all]</span> @@ -430,19 +429,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen<span class="Special"> <- </span>render-sandbox-side screen, env <span class="Constant"> <render-components-end></span> <span class="Comment">#</span> - recipes:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> sandbox-in-focus?:boolean<span class="Special"> <- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span> screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="Comment">#</span> show-screen screen ] -<span class="muRecipe">def</span> render-recipes screen:address:shared:screen, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>screen:address:shared:screen, env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> render-recipes screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render recipes]</span> - recipes:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> <span class="Comment"># render recipes</span> left:number<span class="Special"> <- </span>get *recipes, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *recipes, <span class="Constant">right:offset</span> @@ -457,10 +456,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">def</span> render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>screen:address:shared:screen, env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> left:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">right:offset</span> row:number, column:number, screen, current-sandbox<span class="Special"> <- </span>render screen, current-sandbox @@ -472,7 +471,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color clear-screen-from screen, row, left, left, right ] -<span class="muRecipe">def</span> update-cursor screen:address:shared:screen, recipes:address:shared:editor-data, current-sandbox:address:shared:editor-data, sandbox-in-focus?:boolean, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> update-cursor screen:address:screen, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Constant"> <update-cursor-special-cases></span> @@ -491,7 +490,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># print a text 's' to 'editor' in 'color' starting at 'row'</span> <span class="Comment"># clear rest of last line, move cursor to next line</span> -<span class="muRecipe">def</span> render screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:shared:screen [ +<span class="muRecipe">def</span> render screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> s @@ -552,7 +551,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># like 'render' for texts, but with colorization for comments like in the editor</span> -<span class="muRecipe">def</span> render-code screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:shared:screen [ +<span class="muRecipe">def</span> render-code screen:address:screen, s:address:array:character, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> s @@ -618,9 +617,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><global-type></span> [ <span class="Delimiter">{</span> - redraw-screen?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">12/ctrl-l</span> + redraw-screen?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">12/ctrl-l</span> <span class="muControl">break-unless</span> redraw-screen? - screen<span class="Special"> <- </span>render-all screen, env:address:shared:programming-environment-data + screen<span class="Special"> <- </span>render-all screen, env:address:programming-environment-data sync-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> @@ -631,17 +630,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><global-type></span> [ <span class="Delimiter">{</span> - switch-side?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">14/ctrl-n</span> + switch-side?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">14/ctrl-n</span> <span class="muControl">break-unless</span> switch-side? - *sandbox-in-focus?<span class="Special"> <- </span>not *sandbox-in-focus? - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + sandbox-in-focus?:boolean<span class="Special"> <- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span> + sandbox-in-focus?<span class="Special"> <- </span>not sandbox-in-focus? + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox-in-focus?:offset</span>, sandbox-in-focus? + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] <span class="SalientComment">## helpers</span> -<span class="muRecipe">def</span> draw-vertical screen:address:shared:screen, col:number, y:number, bottom:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> draw-vertical screen:address:screen, col:number, y:number, bottom:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> style:character, style-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index 77cd3727..660791b8 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -42,10 +42,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def!</span> main [ <span class="Constant">local-scope</span> open-console - initial-recipe:address:shared:array:character<span class="Special"> <- </span>restore <span class="Constant">[recipes.mu]</span> - initial-sandbox:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + initial-recipe:address:array:character<span class="Special"> <- </span>restore <span class="Constant">[recipes.mu]</span> + initial-sandbox:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> hide-screen <span class="Constant">0/screen</span> - env:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox env<span class="Special"> <- </span>restore-sandboxes env render-all <span class="Constant">0/screen</span>, env event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env @@ -53,41 +53,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muData">container</span> programming-environment-data [ - sandbox:address:shared:sandbox-data <span class="Comment"># list of sandboxes, from top to bottom</span> + sandbox:address:sandbox-data <span class="Comment"># list of sandboxes, from top to bottom</span> render-from:number number-of-sandboxes:number ] <span class="muRecipe">after</span> <span class="Constant"><programming-environment-initialization></span> [ - render-from:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">render-from:offset</span> - *render-from<span class="Special"> <- </span>copy <span class="Constant">-1</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">render-from:offset</span>, <span class="Constant">-1</span> ] <span class="muData">container</span> sandbox-data [ - data:address:shared:array:character - response:address:shared:array:character + data:address:array:character + response:address:array:character <span class="Comment"># coordinates to track clicks</span> <span class="Comment"># constraint: will be 0 for sandboxes at positions before env.render-from</span> starting-row-on-screen:number code-ending-row-on-screen:number <span class="Comment"># past end of code</span> - screen:address:shared:screen <span class="Comment"># prints in the sandbox go here</span> - next-sandbox:address:shared:sandbox-data + screen:address:screen <span class="Comment"># prints in the sandbox go here</span> + next-sandbox:address:sandbox-data ] <span class="muScenario">scenario</span> run-and-show-results [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Comment"># sandbox editor contains an instruction without storing outputs</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[divide-with-remainder 11, 3]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[divide-with-remainder 11, 3]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors</span> assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -137,7 +136,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -160,7 +159,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><global-keypress></span> [ <span class="Comment"># F4? load all code and run all sandboxes.</span> <span class="Delimiter">{</span> - do-run?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65532/F4</span> + do-run?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65532/F4</span> <span class="muControl">break-unless</span> do-run? screen<span class="Special"> <- </span>update-status screen, <span class="Constant">[running... ]</span>, <span class="Constant">245/grey</span> error?:boolean, env, screen<span class="Special"> <- </span>run-sandboxes env, screen @@ -170,45 +169,43 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> error? screen<span class="Special"> <- </span>update-status screen, <span class="Constant">[ ]</span>, <span class="Constant">245/grey</span> <span class="Delimiter">}</span> - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> run-sandboxes env:address:shared:programming-environment-data, screen:address:shared:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [ +<span class="muRecipe">def</span> run-sandboxes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> errors-found?:boolean, env, screen<span class="Special"> <- </span>update-recipes env, screen <span class="muControl">return-if</span> errors-found? <span class="Comment"># check contents of right editor (sandbox)</span> <span class="Constant"> <run-sandboxes-begin></span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> <span class="Delimiter">{</span> - sandbox-contents:address:shared:array:character<span class="Special"> <- </span>editor-contents current-sandbox + sandbox-contents:address:array:character<span class="Special"> <- </span>editor-contents current-sandbox <span class="muControl">break-unless</span> sandbox-contents <span class="Comment"># if contents exist, first save them</span> <span class="Comment"># run them and turn them into a new sandbox-data</span> - new-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>new <span class="Constant">sandbox-data:type</span> - data:address:address:shared:array:character<span class="Special"> <- </span>get-address *new-sandbox, <span class="Constant">data:offset</span> - *data<span class="Special"> <- </span>copy sandbox-contents + new-sandbox:address:sandbox-data<span class="Special"> <- </span>new <span class="Constant">sandbox-data:type</span> + *new-sandbox<span class="Special"> <- </span>put *new-sandbox, <span class="Constant">data:offset</span>, sandbox-contents <span class="Comment"># push to head of sandbox list</span> - dest:address:address:shared:sandbox-data<span class="Special"> <- </span>get-address *env, <span class="Constant">sandbox:offset</span> - next:address:address:shared:sandbox-data<span class="Special"> <- </span>get-address *new-sandbox, <span class="Constant">next-sandbox:offset</span> - *next<span class="Special"> <- </span>copy *dest - *dest<span class="Special"> <- </span>copy new-sandbox + dest:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + *new-sandbox<span class="Special"> <- </span>put *new-sandbox, <span class="Constant">next-sandbox:offset</span>, dest + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox:offset</span>, new-sandbox <span class="Comment"># update sandbox count</span> - sandbox-count:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">number-of-sandboxes:offset</span> - *sandbox-count<span class="Special"> <- </span>add *sandbox-count, <span class="Constant">1</span> + sandbox-count:number<span class="Special"> <- </span>get *env, <span class="Constant">number-of-sandboxes:offset</span> + sandbox-count<span class="Special"> <- </span>add sandbox-count, <span class="Constant">1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">number-of-sandboxes:offset</span>, sandbox-count <span class="Comment"># clear sandbox editor</span> - init:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *current-sandbox, <span class="Constant">data:offset</span> - *init<span class="Special"> <- </span>push <span class="Constant">167/§</span>, <span class="Constant">0/tail</span> - top-of-screen:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *current-sandbox, <span class="Constant">top-of-screen:offset</span> - *top-of-screen<span class="Special"> <- </span>copy *init + init:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">167/§</span>, <span class="Constant">0/tail</span> + *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">data:offset</span>, init + *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">top-of-screen:offset</span>, init <span class="Delimiter">}</span> <span class="Comment"># save all sandboxes before running, just in case we die when running</span> save-sandboxes env <span class="Comment"># run all sandboxes</span> - curr:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + curr:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> curr @@ -222,45 +219,45 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># copy code from recipe editor, persist, load into mu</span> <span class="Comment"># replaced in a later layer (whereupon errors-found? will actually be set)</span> -<span class="muRecipe">def</span> update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [ +<span class="muRecipe">def</span> update-recipes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - recipes:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> - in:address:shared:array:character<span class="Special"> <- </span>editor-contents recipes + recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + in:address:array:character<span class="Special"> <- </span>editor-contents recipes save <span class="Constant">[recipes.mu]</span>, in <span class="Comment"># newlayer: persistence</span> reload in errors-found?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">def!</span> update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number<span class="muRecipe"> -> </span>sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [ +<span class="muRecipe">def!</span> update-sandbox sandbox:address:sandbox-data, env:address:programming-environment-data, idx:number<span class="muRecipe"> -> </span>sandbox:address:sandbox-data, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - data:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> - response:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response:offset</span> - fake-screen:address:address:shared:screen<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">screen:offset</span> - *response, _, *fake-screen<span class="Special"> <- </span>run-interactive data + data:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> + response:address:array:character, _, fake-screen:address:screen<span class="Special"> <- </span>run-interactive data + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response:offset</span>, response + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">screen:offset</span>, fake-screen ] -<span class="muRecipe">def</span> update-status screen:address:shared:screen, msg:address:shared:array:character, color:number<span class="muRecipe"> -> </span>screen:address:shared:screen [ +<span class="muRecipe">def</span> update-status screen:address:screen, msg:address:array:character, color:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> screen<span class="Special"> <- </span>move-cursor screen, <span class="Constant">0</span>, <span class="Constant">2</span> screen<span class="Special"> <- </span>print screen, msg, color, <span class="Constant">238/grey/background</span> ] -<span class="muRecipe">def</span> save-sandboxes env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> save-sandboxes env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </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>* >/dev/null <span class="Constant">2</span>>/dev/null] <span class="Comment"># some shells can't handle '>&'</span> - curr:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + curr:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> curr - data:address:shared:array:character<span class="Special"> <- </span>get *curr, <span class="Constant">data:offset</span> - filename:address:shared:array:character<span class="Special"> <- </span>to-text idx + data:address:array:character<span class="Special"> <- </span>get *curr, <span class="Constant">data:offset</span> + filename:address:array:character<span class="Special"> <- </span>to-text idx save filename, data <span class="Constant"> <end-save-sandbox></span> idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> @@ -269,11 +266,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muRecipe">def!</span> render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>screen:address:shared:screen, env:address:shared:programming-environment-data [ +<span class="muRecipe">def!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render sandbox side]</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> row:number, column:number<span class="Special"> <- </span>copy <span class="Constant">1</span>, <span class="Constant">0</span> left:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">right:offset</span> @@ -288,12 +285,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Comment"># render sandboxes</span> draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span> - sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> row, screen<span class="Special"> <- </span>render-sandboxes screen, sandbox, left, right, row, render-from clear-rest-of-screen screen, row, left, right ] -<span class="muRecipe">def</span> render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number<span class="muRecipe"> -> </span>row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [ +<span class="muRecipe">def</span> render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number<span class="muRecipe"> -> </span>row:number, screen:address:screen, sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> sandbox @@ -311,20 +308,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color delete-icon:character<span class="Special"> <- </span>copy <span class="Constant">120/x</span> print screen, delete-icon, <span class="Constant">245/grey</span> <span class="Comment"># save menu row so we can detect clicks to it later</span> - starting-row:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">starting-row-on-screen:offset</span> - *starting-row<span class="Special"> <- </span>copy row + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">starting-row-on-screen:offset</span>, row <span class="Comment"># render sandbox contents</span> row<span class="Special"> <- </span>add row, <span class="Constant">1</span> screen<span class="Special"> <- </span>move-cursor screen, row, left - sandbox-data:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> + sandbox-data:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> row, screen<span class="Special"> <- </span>render-code screen, sandbox-data, left, right, row - code-ending-row:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span> - *code-ending-row<span class="Special"> <- </span>copy row + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>, row <span class="Comment"># render sandbox warnings, screen or response, in that order</span> - sandbox-response:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">response:offset</span> + sandbox-response:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">response:offset</span> <span class="Constant"> <render-sandbox-results></span> <span class="Delimiter">{</span> - sandbox-screen:address:shared:screen<span class="Special"> <- </span>get *sandbox, <span class="Constant">screen:offset</span> + sandbox-screen:address:screen<span class="Special"> <- </span>get *sandbox, <span class="Constant">screen:offset</span> empty-screen?:boolean<span class="Special"> <- </span>fake-screen-is-empty? sandbox-screen <span class="muControl">break-if</span> empty-screen? row, screen<span class="Special"> <- </span>render-screen screen, sandbox-screen, left, right, row @@ -343,33 +338,31 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># if hidden, reset row attributes</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> hidden? - tmp:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">starting-row-on-screen:offset</span> - *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> - tmp:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span> - *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">starting-row-on-screen:offset</span>, <span class="Constant">0</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>, <span class="Constant">0</span> <span class="Constant"> <end-render-sandbox-reset-hidden></span> <span class="Delimiter">}</span> <span class="Comment"># draw next sandbox</span> - next-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> + next-sandbox:address:sandbox-data<span class="Special"> <- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> next-idx:number<span class="Special"> <- </span>add idx, <span class="Constant">1</span> row, screen<span class="Special"> <- </span>render-sandboxes screen, next-sandbox, left, right, row, render-from, next-idx ] <span class="Comment"># assumes programming environment has no sandboxes; restores them from previous session</span> -<span class="muRecipe">def</span> restore-sandboxes env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> restore-sandboxes env:address:programming-environment-data<span class="muRecipe"> -> </span>env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># read all scenarios, pushing them to end of a list of scenarios</span> idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - curr:address:address:shared:sandbox-data<span class="Special"> <- </span>get-address *env, <span class="Constant">sandbox:offset</span> + curr:address:sandbox-data<span class="Special"> <- </span>copy <span class="Constant">0</span> + prev:address:sandbox-data<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> - filename:address:shared:array:character<span class="Special"> <- </span>to-text idx - contents:address:shared:array:character<span class="Special"> <- </span>restore filename + filename:address:array:character<span class="Special"> <- </span>to-text idx + contents:address:array:character<span class="Special"> <- </span>restore filename <span class="muControl">break-unless</span> contents <span class="Comment"># stop at first error; assuming file didn't exist</span> <span class="Comment"># create new sandbox for file</span> - *curr<span class="Special"> <- </span>new <span class="Constant">sandbox-data:type</span> - data:address:address:shared:array:character<span class="Special"> <- </span>get-address **curr, <span class="Constant">data:offset</span> - *data<span class="Special"> <- </span>copy contents + curr<span class="Special"> <- </span>new <span class="Constant">sandbox-data:type</span> + *curr<span class="Special"> <- </span>put *curr, <span class="Constant">data:offset</span>, contents <span class="Comment"># restore expected output for sandbox if it exists</span> <span class="Delimiter">{</span> filename<span class="Special"> <- </span>append filename, <span class="Constant">[.out]</span> @@ -379,17 +372,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Constant"> +continue</span> idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> - curr<span class="Special"> <- </span>get-address **curr, <span class="Constant">next-sandbox:offset</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> prev + *prev<span class="Special"> <- </span>put *prev, <span class="Constant">next-sandbox:offset</span>, curr + <span class="Delimiter">}</span> + prev<span class="Special"> <- </span>copy curr <span class="muControl">loop</span> <span class="Delimiter">}</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox:offset</span>, curr <span class="Comment"># update sandbox count</span> - number-of-sandboxes:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">number-of-sandboxes:offset</span> - *number-of-sandboxes<span class="Special"> <- </span>copy idx + *env<span class="Special"> <- </span>put *env, <span class="Constant">number-of-sandboxes:offset</span>, idx ] <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">def</span> render-screen screen:address:shared:screen, sandbox-screen:address:shared:screen, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:shared:screen [ +<span class="muRecipe">def</span> render-screen screen:address:screen, sandbox-screen:address:screen, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> sandbox-screen @@ -400,7 +397,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color column:number<span class="Special"> <- </span>copy left s-width:number<span class="Special"> <- </span>screen-width sandbox-screen s-height:number<span class="Special"> <- </span>screen-height sandbox-screen - buf:address:shared:array:screen-cell<span class="Special"> <- </span>get *sandbox-screen, <span class="Constant">data:offset</span> + buf:address:array:screen-cell<span class="Special"> <- </span>get *sandbox-screen, <span class="Constant">data:offset</span> stop-printing:number<span class="Special"> <- </span>add left, s-width, <span class="Constant">3</span> max-column:number<span class="Special"> <- </span>min stop-printing, right i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -458,20 +455,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant">local-scope</span> <span class="Constant">z:number <- 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors</span> assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -491,7 +488,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -511,16 +508,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an instruction</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[print-integer screen, 4]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[print-integer screen, 4]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editor</span> assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -540,11 +537,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> editor-contents editor:address:shared:editor-data<span class="muRecipe"> -> </span>result:address:shared:array:character [ +<span class="muRecipe">def</span> editor-contents editor:address:editor-data<span class="muRecipe"> -> </span>result:address:array:character [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - buf:address:shared:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> - curr:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> + curr:address:duplex-list:character<span class="Special"> <- </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"> <- </span>next curr @@ -561,16 +558,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:address:shared:array:character<span class="Special"> <- </span>editor-contents <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">4</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:shared:array:character + 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"> <- </span>editor-contents <span class="Constant">2</span>:address:editor-data + <span class="Constant">4</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">3</span>:address:array:character ] memory-should-contain [ <span class="Constant">4</span>:array:character<span class="Special"> <- </span><span class="Constant">[abdefc]</span> @@ -583,10 +580,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize sandbox side</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[add 2, 2]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[add 2, 2]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data assume-console [ <span class="Comment"># create a sandbox</span> press F4 @@ -596,9 +593,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">]</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] screen-should-contain [ <span class="Constant"> . . # minor: F4 clears menu tooltip in very narrow screens</span> @@ -613,9 +610,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># sandbox editor hidden; first sandbox displayed</span> <span class="Comment"># cursor moves to first sandbox</span> @@ -633,9 +630,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press up-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># sandbox editor displays again</span> screen-should-contain [ @@ -651,23 +648,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># down on sandbox side updates render-from when sandbox editor has cursor at bottom</span> <span class="muRecipe">after</span> <span class="Constant"><global-keypress></span> [ <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> *sandbox-in-focus? - down?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65516/down-arrow</span> + <span class="muControl">break-unless</span> sandbox-in-focus? + down?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65516/down-arrow</span> <span class="muControl">break-unless</span> down? sandbox-bottom:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">bottom:offset</span> sandbox-cursor:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">cursor-row:offset</span> sandbox-cursor-on-last-line?:boolean<span class="Special"> <- </span>equal sandbox-bottom, sandbox-cursor <span class="muControl">break-unless</span> sandbox-cursor-on-last-line? - sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="muControl">break-unless</span> sandbox <span class="Comment"># slide down if possible</span> <span class="Delimiter">{</span> - render-from:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">render-from:offset</span> + render-from:number<span class="Special"> <- </span>get *env, <span class="Constant">render-from:offset</span> number-of-sandboxes:number<span class="Special"> <- </span>get *env, <span class="Constant">number-of-sandboxes:offset</span> max:number<span class="Special"> <- </span>subtract number-of-sandboxes, <span class="Constant">1</span> - at-end?:boolean<span class="Special"> <- </span>greater-or-equal *render-from, max + at-end?:boolean<span class="Special"> <- </span>greater-or-equal render-from, max <span class="muControl">jump-if</span> at-end?, <span class="Constant">+finish-event:label</span> <span class="Comment"># render nothing</span> - *render-from<span class="Special"> <- </span>add *render-from, <span class="Constant">1</span> + render-from<span class="Special"> <- </span>add render-from, <span class="Constant">1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">render-from:offset</span>, render-from <span class="Delimiter">}</span> hide-screen screen screen<span class="Special"> <- </span>render-sandbox-side screen, env @@ -692,13 +690,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># 'up' on sandbox side is like 'down': updates render-from when necessary</span> <span class="muRecipe">after</span> <span class="Constant"><global-keypress></span> [ <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> *sandbox-in-focus? - up?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65517/up-arrow</span> + <span class="muControl">break-unless</span> sandbox-in-focus? + up?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65517/up-arrow</span> <span class="muControl">break-unless</span> up? - render-from:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">render-from:offset</span> - at-beginning?:boolean<span class="Special"> <- </span>equal *render-from, <span class="Constant">-1</span> + render-from:number<span class="Special"> <- </span>get *env, <span class="Constant">render-from:offset</span> + at-beginning?:boolean<span class="Special"> <- </span>equal render-from, <span class="Constant">-1</span> <span class="muControl">break-if</span> at-beginning? - *render-from<span class="Special"> <- </span>subtract *render-from, <span class="Constant">1</span> + render-from<span class="Special"> <- </span>subtract render-from, <span class="Constant">1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">render-from:offset</span>, render-from hide-screen screen screen<span class="Special"> <- </span>render-sandbox-side screen, env show-screen screen @@ -708,12 +707,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># sandbox belonging to 'env' whose next-sandbox is 'in'</span> <span class="Comment"># return 0 if there's no such sandbox, either because 'in' doesn't exist in 'env', or because it's the first sandbox</span> -<span class="muRecipe">def</span> previous-sandbox env:address:shared:programming-environment-data, in:address:shared:sandbox-data<span class="muRecipe"> -> </span>out:address:shared:sandbox-data [ +<span class="muRecipe">def</span> previous-sandbox env:address:programming-environment-data, in:address:sandbox-data<span class="muRecipe"> -> </span>out:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - curr:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + curr:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="muControl">return-unless</span> curr, <span class="Constant">0/nil</span> - next:address:shared:sandbox-data<span class="Special"> <- </span>get *curr, <span class="Constant">next-sandbox:offset</span> + next:address:sandbox-data<span class="Special"> <- </span>get *curr, <span class="Constant">next-sandbox:offset</span> <span class="Delimiter">{</span> <span class="muControl">return-unless</span> next, <span class="Constant">0/nil</span> found?:boolean<span class="Special"> <- </span>equal next, in @@ -729,24 +728,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize sandbox side and create a sandbox</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">]</span> <span class="Comment"># create a sandbox</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[add 2, 2]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[add 2, 2]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># hit 'down' in recipe editor</span> assume-console [ press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># cursor moves down on recipe side</span> screen-should-contain [ @@ -765,10 +764,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n @@ -777,9 +776,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[add 1, 1]</span> press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ┊␣ .</span> @@ -797,9 +796,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># sandbox editor hidden; first sandbox displayed</span> <span class="Comment"># cursor moves to first sandbox</span> @@ -820,7 +819,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># just second sandbox displayed</span> screen-should-contain [ @@ -838,7 +837,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># no change</span> screen-should-contain [ @@ -856,7 +855,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press up-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># back to displaying both sandboxes without editor</span> screen-should-contain [ @@ -876,9 +875,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press up-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] <span class="Comment"># back to displaying both sandboxes as well as editor</span> screen-should-contain [ @@ -898,7 +897,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press up-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># no change</span> screen-should-contain [ @@ -919,17 +918,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create a sandbox</span> assume-console [ press ctrl-n type <span class="Constant">[add 1, 1]</span> press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊ .</span> @@ -945,7 +944,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># sandbox editor hidden; first sandbox displayed</span> <span class="Comment"># cursor moves to first sandbox</span> @@ -963,7 +962,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press up-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># back to displaying both sandboxes as well as editor</span> screen-should-contain [ @@ -981,7 +980,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># sandbox editor hidden; first sandbox displayed</span> <span class="Comment"># cursor moves to first sandbox</span> diff --git a/html/edit/006-sandbox-edit.mu.html b/html/edit/006-sandbox-edit.mu.html index faf615af..85684b0e 100644 --- a/html/edit/006-sandbox-edit.mu.html +++ b/html/edit/006-sandbox-edit.mu.html @@ -38,17 +38,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> reply 4</span> <span class="Constant">]</span>] <span class="Comment"># run it</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> @@ -59,12 +59,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] - <span class="Comment"># click somewhere on the sandbox</span> + <span class="Comment"># click somewhere in the first row of the sandbox</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">30</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -82,7 +82,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[0]</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -100,81 +100,94 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> - click-column:number<span class="Special"> <- </span>get *t, <span class="Constant">column:offset</span> + click-column:number<span class="Special"> <- </span>get t, <span class="Constant">column:offset</span> on-sandbox-side?:boolean<span class="Special"> <- </span>greater-or-equal click-column, sandbox-left-margin <span class="muControl">break-unless</span> on-sandbox-side? - first-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + first-sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="muControl">break-unless</span> first-sandbox first-sandbox-begins:number<span class="Special"> <- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span> - click-row:number<span class="Special"> <- </span>get *t, <span class="Constant">row:offset</span> + click-row:number<span class="Special"> <- </span>get t, <span class="Constant">row:offset</span> below-sandbox-editor?:boolean<span class="Special"> <- </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"> <- </span>empty-editor? current-sandbox <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:shared:sandbox-data<span class="Special"> <- </span>extract-sandbox env, click-row + sandbox:address:sandbox-data<span class="Special"> <- </span>extract-sandbox env, click-row <span class="muControl">break-unless</span> sandbox - text:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> + text:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> current-sandbox<span class="Special"> <- </span>insert-text current-sandbox, text - render-from:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">render-from:offset</span> - *render-from<span class="Special"> <- </span>copy <span class="Constant">-1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">render-from:offset</span>, <span class="Constant">-1</span> hide-screen screen screen<span class="Special"> <- </span>render-sandbox-side screen, env - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> empty-editor? editor:address:shared:editor-data<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">def</span> empty-editor? editor:address:editor-data<span class="muRecipe"> -> </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - head:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> - first:address:shared:duplex-list:character<span class="Special"> <- </span>next head + head:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + first:address:duplex-list:character<span class="Special"> <- </span>next head result<span class="Special"> <- </span>not first ] -<span class="muRecipe">def</span> extract-sandbox env:address:shared:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>result:address:shared:sandbox-data, env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> extract-sandbox env:address:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>result:address:sandbox-data, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - sandbox:address:address:shared:sandbox-data<span class="Special"> <- </span>get-address *env, <span class="Constant">sandbox:offset</span> - start:number<span class="Special"> <- </span>get **sandbox, <span class="Constant">starting-row-on-screen:offset</span> + curr-sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + start:number<span class="Special"> <- </span>get *curr-sandbox, <span class="Constant">starting-row-on-screen:offset</span> in-editor?:boolean<span class="Special"> <- </span>lesser-than click-row, start <span class="muControl">return-if</span> in-editor?, <span class="Constant">0</span> + first-sandbox?:boolean<span class="Special"> <- </span>equal click-row, start <span class="Delimiter">{</span> - next-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get **sandbox, <span class="Constant">next-sandbox:offset</span> - <span class="muControl">break-unless</span> next-sandbox - <span class="Comment"># if click-row < sandbox.next-sandbox.starting-row-on-screen, break</span> - next-start:number<span class="Special"> <- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span> - found?:boolean<span class="Special"> <- </span>lesser-than click-row, next-start - <span class="muControl">break-if</span> found? - sandbox<span class="Special"> <- </span>get-address **sandbox, <span class="Constant">next-sandbox:offset</span> - <span class="muControl">loop</span> + <span class="Comment"># first sandbox? pop</span> + <span class="muControl">break-unless</span> first-sandbox? + next-sandbox:address:sandbox-data<span class="Special"> <- </span>get *curr-sandbox, <span class="Constant">next-sandbox:offset</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox:offset</span>, next-sandbox <span class="Delimiter">}</span> - <span class="Comment"># snip sandbox out of its list</span> - result<span class="Special"> <- </span>copy *sandbox - *sandbox<span class="Special"> <- </span>copy next-sandbox + <span class="Delimiter">{</span> + <span class="Comment"># not first sandbox?</span> + <span class="muControl">break-if</span> first-sandbox? + prev-sandbox:address:sandbox-data<span class="Special"> <- </span>copy curr-sandbox + curr-sandbox<span class="Special"> <- </span>get *curr-sandbox, <span class="Constant">next-sandbox:offset</span> + <span class="Delimiter">{</span> + next-sandbox:address:sandbox-data<span class="Special"> <- </span>get *curr-sandbox, <span class="Constant">next-sandbox:offset</span> + <span class="muControl">break-unless</span> next-sandbox + <span class="Comment"># if click-row < sandbox.next-sandbox.starting-row-on-screen, break</span> + next-start:number<span class="Special"> <- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span> + found?:boolean<span class="Special"> <- </span>lesser-than click-row, next-start + <span class="muControl">break-if</span> found? + prev-sandbox<span class="Special"> <- </span>copy curr-sandbox + curr-sandbox<span class="Special"> <- </span>copy next-sandbox + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># snip sandbox out of its list</span> + *prev-sandbox<span class="Special"> <- </span>put *prev-sandbox, <span class="Constant">next-sandbox:offset</span>, next-sandbox + <span class="Delimiter">}</span> + result<span class="Special"> <- </span>copy curr-sandbox <span class="Comment"># update sandbox count</span> - sandbox-count:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">number-of-sandboxes:offset</span> - *sandbox-count<span class="Special"> <- </span>subtract *sandbox-count, <span class="Constant">1</span> + sandbox-count:number<span class="Special"> <- </span>get *env, <span class="Constant">number-of-sandboxes:offset</span> + sandbox-count<span class="Special"> <- </span>subtract sandbox-count, <span class="Constant">1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">number-of-sandboxes:offset</span>, sandbox-count <span class="Comment"># position cursor in sandbox editor</span> - sandbox-in-focus?:address:boolean<span class="Special"> <- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span> - *sandbox-in-focus?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox-in-focus?:offset</span>, <span class="Constant">1/true</span> ] <span class="muScenario">scenario</span> sandbox-with-print-can-be-edited [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an instruction</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[print-integer screen, 4]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[print-integer screen, 4]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the sandbox</span> assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -195,7 +208,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">3</span>, <span class="Constant">70</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -210,10 +223,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -224,7 +237,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow press down-arrow ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> @@ -239,7 +252,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">2</span>, <span class="Constant">20</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># second sandbox shows in editor; scroll resets to display first sandbox</span> screen-should-contain [ @@ -258,10 +271,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n @@ -270,7 +283,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[add 1, 1]</span> press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊ .</span> @@ -287,7 +300,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># no change in contents</span> screen-should-contain [ @@ -307,7 +320,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># screen should show just final sandbox</span> screen-should-contain [ diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html index cc950bca..b29c649d 100644 --- a/html/edit/007-sandbox-delete.mu.html +++ b/html/edit/007-sandbox-delete.mu.html @@ -37,9 +37,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> deleting-sandboxes [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run a few commands</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">80</span> @@ -48,7 +48,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[add 2, 2]</span> press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -69,7 +69,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">7</span>, <span class="Constant">99</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -87,7 +87,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">3</span>, <span class="Constant">99</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -101,27 +101,39 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><global-touch></span> [ <span class="Comment"># on a sandbox delete icon? process delete</span> <span class="Delimiter">{</span> - was-delete?:boolean<span class="Special"> <- </span>delete-sandbox *t, env + was-delete?:boolean<span class="Special"> <- </span>delete-sandbox t, env <span class="muControl">break-unless</span> was-delete? hide-screen screen screen<span class="Special"> <- </span>render-sandbox-side screen, env - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> delete-sandbox t:touch-event, env:address:shared:programming-environment-data<span class="muRecipe"> -> </span>was-delete?:boolean, env:address:shared:programming-environment-data [ +<span class="muRecipe">def</span> delete-sandbox t:touch-event, env:address:programming-environment-data<span class="muRecipe"> -> </span>was-delete?:boolean, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> click-column:number<span class="Special"> <- </span>get t, <span class="Constant">column:offset</span> - current-sandbox:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> + current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> right:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">right:offset</span> at-right?:boolean<span class="Special"> <- </span>equal click-column, right <span class="muControl">return-unless</span> at-right?, <span class="Constant">0/false</span> click-row:number<span class="Special"> <- </span>get t, <span class="Constant">row:offset</span> - prev:address:address:shared:sandbox-data<span class="Special"> <- </span>get-address *env, <span class="Constant">sandbox:offset</span> - curr:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + <span class="Delimiter">{</span> + first:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + <span class="muControl">reply-unless</span> first, <span class="Constant">0/false</span> + target-row:number<span class="Special"> <- </span>get *first, <span class="Constant">starting-row-on-screen:offset</span> + delete-first?:boolean<span class="Special"> <- </span>equal target-row, click-row + <span class="muControl">break-unless</span> delete-first? + new-first:address:sandbox-data<span class="Special"> <- </span>get *first, <span class="Constant">next-sandbox:offset</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">sandbox:offset</span>, new-first + env<span class="Special"> <- </span>fixup-delete env, new-first + <span class="muControl">return</span> <span class="Constant">1/true</span> <span class="Comment"># force rerender</span> + <span class="Delimiter">}</span> + prev:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + assert prev, <span class="Constant">[failed to find any sandboxes!]</span> + curr:address:sandbox-data<span class="Special"> <- </span>get *prev, <span class="Constant">next-sandbox:offset</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> curr <span class="Comment"># more sandboxes to check</span> @@ -130,35 +142,44 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color delete-curr?:boolean<span class="Special"> <- </span>equal target-row, click-row <span class="muControl">break-unless</span> delete-curr? <span class="Comment"># delete this sandbox</span> - *prev<span class="Special"> <- </span>get *curr, <span class="Constant">next-sandbox:offset</span> - <span class="Comment"># update sandbox count</span> - sandbox-count:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">number-of-sandboxes:offset</span> - *sandbox-count<span class="Special"> <- </span>subtract *sandbox-count, <span class="Constant">1</span> - <span class="Comment"># if it's the last sandbox and if it was the only sandbox rendered, reset scroll</span> - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> *prev - render-from:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">render-from:offset</span> - reset-scroll?:boolean<span class="Special"> <- </span>equal *render-from, *sandbox-count - <span class="muControl">break-unless</span> reset-scroll? - *render-from<span class="Special"> <- </span>copy <span class="Constant">-1</span> - <span class="Delimiter">}</span> + next:address:sandbox-data<span class="Special"> <- </span>get *curr, <span class="Constant">next-sandbox:offset</span> + *prev<span class="Special"> <- </span>put *prev, <span class="Constant">next-sandbox:offset</span>, next + env<span class="Special"> <- </span>fixup-delete env, next <span class="muControl">return</span> <span class="Constant">1/true</span> <span class="Comment"># force rerender</span> <span class="Delimiter">}</span> - prev<span class="Special"> <- </span>get-address *curr, <span class="Constant">next-sandbox:offset</span> + prev<span class="Special"> <- </span>copy curr curr<span class="Special"> <- </span>get *curr, <span class="Constant">next-sandbox:offset</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Constant">0/false</span> ] +<span class="muRecipe">def</span> fixup-delete env:address:programming-environment-data, next:address:sandbox-data<span class="muRecipe"> -> </span>env:address:programming-environment-data [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="Comment"># update sandbox count</span> + sandbox-count:number<span class="Special"> <- </span>get *env, <span class="Constant">number-of-sandboxes:offset</span> + sandbox-count<span class="Special"> <- </span>subtract sandbox-count, <span class="Constant">1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">number-of-sandboxes:offset</span>, sandbox-count + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> next + <span class="Comment"># deleted sandbox was last</span> + render-from:number<span class="Special"> <- </span>get *env, <span class="Constant">render-from:offset</span> + reset-scroll?:boolean<span class="Special"> <- </span>equal render-from, sandbox-count + <span class="muControl">break-unless</span> reset-scroll? + <span class="Comment"># deleted sandbox was only sandbox rendered, so reset scroll</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">render-from:offset</span>, <span class="Constant">-1</span> + <span class="Delimiter">}</span> +] + <span class="muScenario">scenario</span> deleting-sandbox-after-scroll [ 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -168,7 +189,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 press down-arrow ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> @@ -183,7 +204,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">6</span>, <span class="Constant">29</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># second sandbox shows in editor; scroll resets to display first sandbox</span> screen-should-contain [ @@ -201,10 +222,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -214,7 +235,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 press down-arrow ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> @@ -229,7 +250,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">2</span>, <span class="Constant">29</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># second sandbox shows in editor; scroll resets to display first sandbox</span> screen-should-contain [ @@ -247,10 +268,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -261,7 +282,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow press down-arrow ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> @@ -276,7 +297,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">2</span>, <span class="Constant">29</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># implicitly scroll up to first sandbox</span> screen-should-contain [ @@ -295,10 +316,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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">10/height</span> <span class="Comment"># initialize environment</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + render-all screen, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n @@ -307,7 +328,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[add 1, 1]</span> press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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"> . .</span> <span class="Constant"> . ┊ .</span> @@ -327,7 +348,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press down-arrow ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># shouldn't go past last sandbox</span> screen-should-contain [ diff --git a/html/edit/008-sandbox-test.mu.html b/html/edit/008-sandbox-test.mu.html index 2f012d7a..69a4fd5c 100644 --- a/html/edit/008-sandbox-test.mu.html +++ b/html/edit/008-sandbox-test.mu.html @@ -39,17 +39,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> reply 4</span> <span class="Constant">]</span>] <span class="Comment"># run it</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> @@ -65,7 +65,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">5</span>, <span class="Constant">21</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>, [ @@ -81,7 +81,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># cursor should remain unmoved</span> run [ <span class="Constant">4</span>:character/cursor<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor + print screen:address:screen, <span class="Constant">4</span>:character/cursor ] screen-should-contain [ <span class="Constant"> . run (F4) .</span> @@ -102,7 +102,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>, [ @@ -120,13 +120,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># this requires tracking a couple more things</span> <span class="muData">container</span> sandbox-data [ response-starting-row-on-screen:number - expected-response:address:shared:array:character + expected-response:address:array:character ] <span class="Comment"># include expected response when saving or restoring a sandbox</span> <span class="muRecipe">before</span> <span class="Constant"><end-save-sandbox></span> [ <span class="Delimiter">{</span> - expected-response:address:shared:array:character<span class="Special"> <- </span>get *curr, <span class="Constant">expected-response:offset</span> + expected-response:address:array:character<span class="Special"> <- </span>get *curr, <span class="Constant">expected-response:offset</span> <span class="muControl">break-unless</span> expected-response filename<span class="Special"> <- </span>append filename, <span class="Constant">[.out]</span> save filename, expected-response @@ -134,8 +134,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">before</span> <span class="Constant"><end-restore-sandbox></span> [ - expected-response:address:address:shared:array:character<span class="Special"> <- </span>get-address **curr, <span class="Constant">expected-response:offset</span> - *expected-response<span class="Special"> <- </span>copy contents + *curr<span class="Special"> <- </span>put *curr, <span class="Constant">expected-response:offset</span>, contents ] <span class="Comment"># clicks on sandbox responses save it as 'expected'</span> @@ -143,41 +142,41 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> - click-column:number<span class="Special"> <- </span>get *t, <span class="Constant">column:offset</span> + click-column:number<span class="Special"> <- </span>get t, <span class="Constant">column:offset</span> on-sandbox-side?:boolean<span class="Special"> <- </span>greater-or-equal click-column, sandbox-left-margin <span class="muControl">break-unless</span> on-sandbox-side? - first-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + first-sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="muControl">break-unless</span> first-sandbox first-sandbox-begins:number<span class="Special"> <- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span> - click-row:number<span class="Special"> <- </span>get *t, <span class="Constant">row:offset</span> + click-row:number<span class="Special"> <- </span>get t, <span class="Constant">row:offset</span> below-sandbox-editor?:boolean<span class="Special"> <- </span>greater-or-equal click-row, first-sandbox-begins <span class="muControl">break-unless</span> below-sandbox-editor? <span class="Comment"># identify the sandbox whose output is being clicked on</span> - sandbox:address:shared:sandbox-data<span class="Special"> <- </span>find-click-in-sandbox-output env, click-row + sandbox:address:sandbox-data<span class="Special"> <- </span>find-click-in-sandbox-output env, click-row <span class="muControl">break-unless</span> sandbox <span class="Comment"># toggle its expected-response, and save session</span> sandbox<span class="Special"> <- </span>toggle-expected-response sandbox save-sandboxes env hide-screen screen screen<span class="Special"> <- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span> - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="Comment"># no change in cursor</span> show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> find-click-in-sandbox-output env:address:shared:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>sandbox:address:shared:sandbox-data [ +<span class="muRecipe">def</span> find-click-in-sandbox-output env:address:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># assert click-row >= sandbox.starting-row-on-screen</span> - sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> start:number<span class="Special"> <- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span> clicked-on-sandboxes?:boolean<span class="Special"> <- </span>greater-or-equal click-row, start assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span> <span class="Comment"># while click-row < sandbox.next-sandbox.starting-row-on-screen</span> <span class="Delimiter">{</span> - next-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> + next-sandbox:address:sandbox-data<span class="Special"> <- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> <span class="muControl">break-unless</span> next-sandbox next-start:number<span class="Special"> <- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span> found?:boolean<span class="Special"> <- </span>lesser-than click-row, next-start @@ -193,28 +192,29 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">return</span> sandbox ] -<span class="muRecipe">def</span> toggle-expected-response sandbox:address:shared:sandbox-data<span class="muRecipe"> -> </span>sandbox:address:shared:sandbox-data [ +<span class="muRecipe">def</span> toggle-expected-response sandbox:address:sandbox-data<span class="muRecipe"> -> </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - expected-response:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">expected-response:offset</span> + expected-response:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">expected-response:offset</span> <span class="Delimiter">{</span> <span class="Comment"># if expected-response is set, reset</span> - <span class="muControl">break-unless</span> *expected-response - *expected-response<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="muControl">return</span> sandbox/same-as-ingredient:<span class="Constant">0</span> + <span class="muControl">break-unless</span> expected-response + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">expected-response:offset</span>, <span class="Constant">0</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Comment"># if not, set expected response to the current response</span> + <span class="muControl">break-if</span> expected-response + response:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">response:offset</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">expected-response:offset</span>, response <span class="Delimiter">}</span> - <span class="Comment"># if not, current response is the expected response</span> - response:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">response:offset</span> - *expected-response<span class="Special"> <- </span>copy response ] <span class="Comment"># when rendering a sandbox, color it in red/green if expected response exists</span> <span class="muRecipe">after</span> <span class="Constant"><render-sandbox-response></span> [ <span class="Delimiter">{</span> <span class="muControl">break-unless</span> sandbox-response - response-starting-row:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span> - *response-starting-row<span class="Special"> <- </span>copy row - expected-response:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">expected-response:offset</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>, row + expected-response:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">expected-response:offset</span> <span class="muControl">break-unless</span> expected-response <span class="Comment"># fall-through to print in grey</span> response-is-expected?:boolean<span class="Special"> <- </span>equal expected-response, sandbox-response <span class="Delimiter">{</span> @@ -230,8 +230,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">before</span> <span class="Constant"><end-render-sandbox-reset-hidden></span> [ - tmp:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span> - *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>, <span class="Constant">0</span> ] </pre> </body> diff --git a/html/edit/009-sandbox-trace.mu.html b/html/edit/009-sandbox-trace.mu.html index 6464866c..c6d30308 100644 --- a/html/edit/009-sandbox-trace.mu.html +++ b/html/edit/009-sandbox-trace.mu.html @@ -39,17 +39,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> stash [abc]</span> ]] <span class="Comment"># run it</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> @@ -64,9 +64,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">4</span>, <span class="Constant">21</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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>:character/cursor-icon<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor-icon + print screen:address:screen, <span class="Constant">4</span>:character/cursor-icon ] <span class="Comment"># trace now printed and cursor shouldn't have budged</span> screen-should-contain [ @@ -94,8 +94,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">4</span>, <span class="Constant">25</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data - print screen:address:shared:screen, <span class="Constant">4</span>:character/cursor-icon + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + print screen:address:screen, <span class="Constant">4</span>:character/cursor-icon ] <span class="Comment"># trace hidden again</span> screen-should-contain [ @@ -113,18 +113,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> stash [abc]</span> <span class="muControl">reply</span> <span class="Constant">4</span> ]] <span class="Comment"># run it</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> @@ -140,7 +140,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click <span class="Constant">4</span>, <span class="Constant">21</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 above result</span> screen-should-contain [ @@ -157,19 +157,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muData">container</span> sandbox-data [ - trace:address:shared:array:character + trace:address:array:character display-trace?:boolean ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">def!</span> update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number<span class="muRecipe"> -> </span>sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [ +<span class="muRecipe">def!</span> update-sandbox sandbox:address:sandbox-data, env:address:programming-environment-data, idx:number<span class="muRecipe"> -> </span>sandbox:address:sandbox-data, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - data:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> - response:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response:offset</span> - trace:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">trace:offset</span> - fake-screen:address:address:shared:screen<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">screen:offset</span> - *response, _, *fake-screen, *trace<span class="Special"> <- </span>run-interactive data + data:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> + response:address:array:character, _, fake-screen:address:screen, trace:address:array:character<span class="Special"> <- </span>run-interactive data + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response:offset</span>, response + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">screen:offset</span>, fake-screen + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">trace:offset</span>, trace ] <span class="Comment"># clicks on sandbox code toggle its display-trace? flag</span> @@ -177,31 +177,32 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> - click-column:number<span class="Special"> <- </span>get *t, <span class="Constant">column:offset</span> + click-column:number<span class="Special"> <- </span>get t, <span class="Constant">column:offset</span> on-sandbox-side?:boolean<span class="Special"> <- </span>greater-or-equal click-column, sandbox-left-margin <span class="muControl">break-unless</span> on-sandbox-side? - first-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> + first-sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="muControl">break-unless</span> first-sandbox first-sandbox-begins:number<span class="Special"> <- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span> - click-row:number<span class="Special"> <- </span>get *t, <span class="Constant">row:offset</span> + click-row:number<span class="Special"> <- </span>get t, <span class="Constant">row:offset</span> below-sandbox-editor?:boolean<span class="Special"> <- </span>greater-or-equal click-row, first-sandbox-begins <span class="muControl">break-unless</span> below-sandbox-editor? <span class="Comment"># identify the sandbox whose code is being clicked on</span> - sandbox:address:shared:sandbox-data<span class="Special"> <- </span>find-click-in-sandbox-code env, click-row + sandbox:address:sandbox-data<span class="Special"> <- </span>find-click-in-sandbox-code env, click-row <span class="muControl">break-unless</span> sandbox <span class="Comment"># toggle its display-trace? property</span> - x:address:boolean<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">display-trace?:offset</span> - *x<span class="Special"> <- </span>not *x + x:boolean<span class="Special"> <- </span>get *sandbox, <span class="Constant">display-trace?:offset</span> + x<span class="Special"> <- </span>not x + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">display-trace?:offset</span>, x hide-screen screen screen<span class="Special"> <- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span> - screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env + screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="Comment"># no change in cursor</span> show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] -<span class="muRecipe">def</span> find-click-in-sandbox-code env:address:shared:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>sandbox:address:shared:sandbox-data [ +<span class="muRecipe">def</span> find-click-in-sandbox-code env:address:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># assert click-row >= sandbox.starting-row-on-screen</span> @@ -211,7 +212,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span> <span class="Comment"># while click-row < sandbox.next-sandbox.starting-row-on-screen</span> <span class="Delimiter">{</span> - next-sandbox:address:shared:sandbox-data<span class="Special"> <- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> + next-sandbox:address:sandbox-data<span class="Special"> <- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span> <span class="muControl">break-unless</span> next-sandbox next-start:number<span class="Special"> <- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span> found?:boolean<span class="Special"> <- </span>lesser-than click-row, next-start @@ -237,7 +238,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> display-trace?:boolean<span class="Special"> <- </span>get *sandbox, <span class="Constant">display-trace?:offset</span> <span class="muControl">break-unless</span> display-trace? - sandbox-trace:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">trace:offset</span> + sandbox-trace:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">trace:offset</span> <span class="muControl">break-unless</span> sandbox-trace <span class="Comment"># nothing to print; move on</span> row, screen<span class="Special"> <- </span>render screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row <span class="Delimiter">}</span> diff --git a/html/edit/010-errors.mu.html b/html/edit/010-errors.mu.html index eb7f529b..d1627ae7 100644 --- a/html/edit/010-errors.mu.html +++ b/html/edit/010-errors.mu.html @@ -36,21 +36,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="SalientComment">## handling malformed programs</span> <span class="muData">container</span> programming-environment-data [ - recipe-errors:address:shared:array:character + recipe-errors:address:array:character ] <span class="Comment"># copy code from recipe editor, persist, load into mu, save any errors</span> -<span class="muRecipe">def!</span> update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [ +<span class="muRecipe">def!</span> update-recipes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - recipes:address:shared:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> - in:address:shared:array:character<span class="Special"> <- </span>editor-contents recipes + recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + in:address:array:character<span class="Special"> <- </span>editor-contents recipes save <span class="Constant">[recipes.mu]</span>, in - recipe-errors:address:address:shared:array:character<span class="Special"> <- </span>get-address *env, <span class="Constant">recipe-errors:offset</span> - *recipe-errors<span class="Special"> <- </span>reload in + recipe-errors:address:array:character<span class="Special"> <- </span>reload in + *env<span class="Special"> <- </span>put *env, <span class="Constant">recipe-errors:offset</span>, recipe-errors <span class="Comment"># if recipe editor has errors, stop</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> *recipe-errors + <span class="muControl">break-unless</span> recipe-errors update-status screen, <span class="Constant">[errors found ]</span>, <span class="Constant">1/red</span> errors-found?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">return</span> @@ -60,7 +60,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">before</span> <span class="Constant"><render-components-end></span> [ trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render status]</span> - recipe-errors:address:shared:array:character<span class="Special"> <- </span>get *env, <span class="Constant">recipe-errors:offset</span> + recipe-errors:address:array:character<span class="Special"> <- </span>get *env, <span class="Constant">recipe-errors:offset</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> recipe-errors update-status screen, <span class="Constant">[errors found ]</span>, <span class="Constant">1/red</span> @@ -69,7 +69,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">before</span> <span class="Constant"><render-recipe-components-end></span> [ <span class="Delimiter">{</span> - recipe-errors:address:shared:array:character<span class="Special"> <- </span>get *env, <span class="Constant">recipe-errors:offset</span> + recipe-errors:address:array:character<span class="Special"> <- </span>get *env, <span class="Constant">recipe-errors:offset</span> <span class="muControl">break-unless</span> recipe-errors row, screen<span class="Special"> <- </span>render screen, recipe-errors, left, right, <span class="Constant">1/red</span>, row <span class="Delimiter">}</span> @@ -80,18 +80,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">after</span> <span class="Constant"><programming-environment-initialization></span> [ - error-index:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">error-index:offset</span> - *error-index<span class="Special"> <- </span>copy <span class="Constant">-1</span> + *result<span class="Special"> <- </span>put *result, <span class="Constant">error-index:offset</span>, <span class="Constant">-1</span> ] <span class="muRecipe">after</span> <span class="Constant"><run-sandboxes-begin></span> [ - error-index:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">error-index:offset</span> - *error-index<span class="Special"> <- </span>copy <span class="Constant">-1</span> + *env<span class="Special"> <- </span>put *env, <span class="Constant">error-index:offset</span>, <span class="Constant">-1</span> ] <span class="muRecipe">before</span> <span class="Constant"><run-sandboxes-end></span> [ <span class="Delimiter">{</span> - sandboxes-completed-successfully?:boolean<span class="Special"> <- </span>equal *error-index, <span class="Constant">-1</span> + error-index:number<span class="Special"> <- </span>get *env, <span class="Constant">error-index:offset</span> + sandboxes-completed-successfully?:boolean<span class="Special"> <- </span>equal error-index, <span class="Constant">-1</span> <span class="muControl">break-if</span> sandboxes-completed-successfully? errors-found?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="Delimiter">}</span> @@ -103,47 +102,47 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color error-index:number<span class="Special"> <- </span>get *env, <span class="Constant">error-index:offset</span> sandboxes-completed-successfully?:boolean<span class="Special"> <- </span>equal error-index, <span class="Constant">-1</span> <span class="muControl">break-if</span> sandboxes-completed-successfully? - error-index-text:address:shared:array:character<span class="Special"> <- </span>to-text error-index - status:address:shared:array:character<span class="Special"> <- </span>interpolate <span class="Constant">[errors found (_) ]</span>, error-index-text + error-index-text:address:array:character<span class="Special"> <- </span>to-text error-index + status:address:array:character<span class="Special"> <- </span>interpolate <span class="Constant">[errors found (_) ]</span>, error-index-text update-status screen, status, <span class="Constant">1/red</span> <span class="Delimiter">}</span> ] <span class="muData">container</span> sandbox-data [ - errors:address:shared:array:character + errors:address:array:character ] -<span class="muRecipe">def!</span> update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number<span class="muRecipe"> -> </span>sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [ +<span class="muRecipe">def!</span> update-sandbox sandbox:address:sandbox-data, env:address:programming-environment-data, idx:number<span class="muRecipe"> -> </span>sandbox:address:sandbox-data, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - data:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> - response:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response:offset</span> - errors:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">errors:offset</span> - trace:address:address:shared:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">trace:offset</span> - fake-screen:address:address:shared:screen<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">screen:offset</span> - *response, *errors, *fake-screen, *trace, completed?:boolean<span class="Special"> <- </span>run-interactive data + data:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> + response:address:array:character, errors:address:array:character, fake-screen:address:screen, trace:address:array:character, completed?:boolean<span class="Special"> <- </span>run-interactive data + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response:offset</span>, response + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">errors:offset</span>, errors + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">screen:offset</span>, fake-screen + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">trace:offset</span>, trace <span class="Delimiter">{</span> - <span class="muControl">break-if</span> *errors + <span class="muControl">break-if</span> errors <span class="muControl">break-if</span> completed?:boolean - *errors<span class="Special"> <- </span>new <span class="Constant">[took too long!</span> + errors<span class="Special"> <- </span>new <span class="Constant">[took too long!</span> <span class="Constant">]</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">errors:offset</span>, errors <span class="Delimiter">}</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> *errors - error-index:address:number<span class="Special"> <- </span>get-address *env, <span class="Constant">error-index:offset</span> - error-not-set?:boolean<span class="Special"> <- </span>equal *error-index, <span class="Constant">-1</span> + <span class="muControl">break-unless</span> errors + error-index:number<span class="Special"> <- </span>get *env, <span class="Constant">error-index:offset</span> + error-not-set?:boolean<span class="Special"> <- </span>equal error-index, <span class="Constant">-1</span> <span class="muControl">break-unless</span> error-not-set? - *error-index<span class="Special"> <- </span>copy idx + *env<span class="Special"> <- </span>put *env, <span class="Constant">error-index:offset</span>, idx <span class="Delimiter">}</span> ] <span class="Comment"># make sure we render any trace</span> <span class="muRecipe">after</span> <span class="Constant"><render-sandbox-trace-done></span> [ <span class="Delimiter">{</span> - sandbox-errors:address:shared:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">errors:offset</span> + sandbox-errors:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">errors:offset</span> <span class="muControl">break-unless</span> sandbox-errors - response-starting-row:address:number<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span> - *response-starting-row<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># no response</span> + *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>, <span class="Constant">0</span> <span class="Comment"># no response</span> row, screen<span class="Special"> <- </span>render screen, sandbox-errors, left, right, <span class="Constant">1/red</span>, row <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> @@ -153,17 +152,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-shows-errors-in-get [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -193,9 +192,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-updates-status-with-first-erroneous-sandbox [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">80</span> <span class="Comment"># create invalid sandbox 1</span> @@ -206,7 +205,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># status line shows that error is in first sandbox</span> screen-should-contain [ @@ -217,9 +216,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-updates-status-with-first-erroneous-sandbox-2 [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">80</span> <span class="Comment"># create invalid sandbox 2</span> @@ -233,7 +232,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># status line shows that error is in second sandbox</span> screen-should-contain [ @@ -244,14 +243,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-hides-errors-from-past-sandboxes [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[get foo, x:offset]</span> <span class="Comment"># invalid</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[get foo, x:offset]</span> <span class="Comment"># invalid</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 <span class="Comment"># generate error</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">80</span> @@ -260,7 +259,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 <span class="Comment"># update sandbox</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># error should disappear</span> screen-should-contain [ @@ -279,18 +278,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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"># define a shape-shifting recipe with an error</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe foo x:_elem -> z:_elem [</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe foo x:_elem -> z:_elem [</span> <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Constant">y:address:number <- copy 0</span> <span class="Constant">z <- add x, y</span> <span class="Constant">]</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo 2]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo 2]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 (0) run (F4) .</span> <span class="Constant"> .recipe foo x:_elem -> z:_elem [ ┊ .</span> @@ -307,7 +306,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># error should remain unchanged</span> screen-should-contain [ @@ -327,24 +326,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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"># overload a well-known shape-shifting recipe</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe length l:address:shared:list:_elem -> n:number [</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe length l:address:list:_elem -> n:number [</span> <span class="Constant">]</span>] <span class="Comment"># call code that uses other variants of it, but not it itself</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[x:address:shared:list:number <- copy 0</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[x:address:list:number <- copy 0</span> <span class="Constant">to-text x]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run it once</span> assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># no errors anywhere on screen (can't check anything else, since to-text will return an address)</span> screen-should-contain-in-color <span class="Constant">1/red</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="Constant"> . .</span> <span class="Constant"> . .</span> <span class="Constant"> . .</span> @@ -361,7 +360,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data ] <span class="Comment"># still no errors</span> screen-should-contain-in-color <span class="Constant">1/red</span>, [ @@ -369,7 +368,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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="Constant"> . .</span> <span class="Constant"> . .</span> @@ -386,17 +385,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-shows-missing-type-errors [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> x <- copy 0</span> <span class="Constant">]</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -412,18 +411,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo «</span> <span class="Constant"> x <- copy 0</span> <span class="Constant">]</span> - replace <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">171/«</span>, <span class="Constant">91</span> <span class="Comment"># '['</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + 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"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -440,30 +439,30 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-shows-get-on-non-container-errors [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> local-scope</span> -<span class="Constant"> x:address:shared:point <- new point:type</span> -<span class="Constant"> get x:address:shared:point, 1:offset</span> +<span class="Constant"> x:address:point <- new point:type</span> +<span class="Constant"> get x:address:point, 1:offset</span> <span class="Constant">]</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> <span class="Constant"> . ┊foo .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . local-scope ┊ .</span> - <span class="Constant"> . x:address:shared:point <- new point:type ┊ .</span> - <span class="Constant"> . get x:address:shared:point, 1:offset ┊ .</span> + <span class="Constant"> . x:address:point <- 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:shared:point ┊ .</span> + <span class="Constant"> .ner, but got x:address:point ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> ] @@ -472,20 +471,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> run-shows-non-literal-get-argument-errors [ 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> local-scope</span> <span class="Constant"> x:number <- copy 0</span> -<span class="Constant"> y:address:shared:point <- new point:type</span> -<span class="Constant"> get *y:address:shared:point, x:number</span> +<span class="Constant"> y:address:point <- new point:type</span> +<span class="Constant"> get *y:address:point, x:number</span> <span class="Constant">]</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -493,11 +492,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . local-scope ┊ .</span> <span class="Constant"> . x:number <- copy 0 ┊ .</span> - <span class="Constant"> . y:address:shared:point <- new point:type ┊ .</span> - <span class="Constant"> . get *y:address:shared:point, x:number ┊ .</span> + <span class="Constant"> . y:address:point <- new point:type ┊ .</span> + <span class="Constant"> . get *y:address:point, x:number ┊ .</span> <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> @@ -509,17 +506,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> local-scope</span> <span class="Constant"> x:number <- copy y:number</span> <span class="Constant">]</span>] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> <span class="Constant"> . ┊foo .</span> @@ -536,7 +533,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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> @@ -555,16 +552,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an illegal instruction</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors</span> assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -618,17 +615,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an illegal instruction</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the code in the editors multiple times</span> assume-console [ press F4 press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 [ @@ -649,20 +646,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe foo [</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe foo [</span> <span class="Constant"> {</span> <span class="Constant"> loop</span> <span class="Constant"> }</span> <span class="Constant">]</span>] <span class="Comment"># right editor contains an instruction</span> - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run the sandbox</span> assume-console [ press F4 ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared: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 (0) run (F4) .</span> @@ -680,7 +677,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 error</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe foo [</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe foo [</span> <span class="Constant">local-scope</span> <span class="Constant">a:number <- next-ingredient</span> <span class="Constant">b:number <- next-ingredient</span> @@ -688,13 +685,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color _, c:number<span class="Special"> <- </span>divide-with-remainder a, b <span class="muControl">reply</span> b ]] - <span class="Constant">2</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[foo 4, 0]</span> - <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo 4, 0]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character <span class="Comment"># run</span> assume-console [ press F4 ] - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + 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"> . errors found (0) run (F4) .</span> @@ -712,7 +709,7 @@ _, c:number<span class="Special"> <- </span>divide-with-remainder a, b left-click <span class="Constant">4</span>, <span class="Constant">55</span> ] run [ - event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data + 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 [ diff --git a/html/edit/011-editor-undo.mu.html b/html/edit/011-editor-undo.mu.html index 99b13730..18d6843a 100644 --- a/html/edit/011-editor-undo.mu.html +++ b/html/edit/011-editor-undo.mu.html @@ -46,13 +46,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> insert-operation [ before-row:number before-column:number - before-top-of-screen:address:shared:duplex-list:character + before-top-of-screen:address:duplex-list:character after-row:number after-column:number - after-top-of-screen:address:shared:duplex-list:character + after-top-of-screen:address:duplex-list:character <span class="Comment"># inserted text is from 'insert-from' until 'insert-until'; list doesn't have to terminate</span> - insert-from:address:shared:duplex-list:character - insert-until:address:shared:duplex-list:character + insert-from:address:duplex-list:character + insert-until:address:duplex-list:character tag:number <span class="Comment"># event causing this operation; might be used to coalesce runs of similar events</span> <span class="Comment"># 0: no coalesce (enter+indent)</span> <span class="Comment"># 1: regular alphanumeric characters</span> @@ -61,10 +61,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> move-operation [ before-row:number before-column:number - before-top-of-screen:address:shared:duplex-list:character + before-top-of-screen:address:duplex-list:character after-row:number after-column:number - after-top-of-screen:address:shared:duplex-list:character + after-top-of-screen:address:duplex-list:character tag:number <span class="Comment"># event causing this operation; might be used to coalesce runs of similar events</span> <span class="Comment"># 0: no coalesce (touch events, etc)</span> <span class="Comment"># 1: left arrow</span> @@ -76,13 +76,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muData">container</span> delete-operation [ before-row:number before-column:number - before-top-of-screen:address:shared:duplex-list:character + before-top-of-screen:address:duplex-list:character after-row:number after-column:number - after-top-of-screen:address:shared:duplex-list:character - deleted-text:address:shared:duplex-list:character - delete-from:address:shared:duplex-list:character - delete-until:address:shared:duplex-list:character + after-top-of-screen:address:duplex-list:character + deleted-text:address:duplex-list:character + delete-from:address:duplex-list:character + delete-until:address:duplex-list:character tag:number <span class="Comment"># event causing this operation; might be used to coalesce runs of similar events</span> <span class="Comment"># 0: no coalesce (ctrl-k, ctrl-u)</span> <span class="Comment"># 1: backspace</span> @@ -91,21 +91,23 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># every editor accumulates a list of operations to undo/redo</span> <span class="muData">container</span> editor-data [ - undo:address:shared:list:address:shared:operation - redo:address:shared:list:address:shared:operation + undo:address:list:address:operation + redo:address:list:address:operation ] <span class="Comment"># ctrl-z - undo operation</span> <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - undo?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">26/ctrl-z</span> + undo?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">26/ctrl-z</span> <span class="muControl">break-unless</span> undo? - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> - <span class="muControl">break-unless</span> *undo - op:address:shared:operation<span class="Special"> <- </span>first *undo - *undo<span class="Special"> <- </span>rest *undo - redo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">redo:offset</span> - *redo<span class="Special"> <- </span>push op, *redo + undo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">undo:offset</span> + <span class="muControl">break-unless</span> undo + op:address:operation<span class="Special"> <- </span>first undo + undo<span class="Special"> <- </span>rest undo + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">undo:offset</span>, undo + redo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">redo:offset</span> + redo<span class="Special"> <- </span>push op, redo + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">redo:offset</span>, redo <span class="Constant"> <handle-undo></span> <span class="muControl">return</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> <span class="Delimiter">}</span> @@ -114,14 +116,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># ctrl-y - redo operation</span> <span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ <span class="Delimiter">{</span> - redo?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">25/ctrl-y</span> + redo?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">25/ctrl-y</span> <span class="muControl">break-unless</span> redo? - redo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">redo:offset</span> - <span class="muControl">break-unless</span> *redo - op:address:shared:operation<span class="Special"> <- </span>first *redo - *redo<span class="Special"> <- </span>rest *redo - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> - *undo<span class="Special"> <- </span>push op, *undo + redo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">redo:offset</span> + <span class="muControl">break-unless</span> redo + op:address:operation<span class="Special"> <- </span>first redo + redo<span class="Special"> <- </span>rest redo + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">redo:offset</span>, redo + undo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">undo:offset</span> + undo<span class="Special"> <- </span>push op, undo + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">undo:offset</span>, undo <span class="Constant"> <handle-redo></span> <span class="muControl">return</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> <span class="Delimiter">}</span> @@ -132,19 +136,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-typing [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 +162,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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,53 +174,57 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># save operation to undo</span> <span class="muRecipe">after</span> <span class="Constant"><insert-character-begin></span> [ - top-before:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - cursor-before:address:shared:duplex-list:character<span class="Special"> <- </span>copy *before-cursor + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><insert-character-end></span> [ - top-after:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + undo:address:list:address:operation<span class="Special"> <- </span>get *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 - op:address:shared:operation<span class="Special"> <- </span>first *undo - typing:address:insert-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">typing:variant</span> - <span class="muControl">break-unless</span> typing - previous-coalesce-tag:number<span class="Special"> <- </span>get *typing, <span class="Constant">tag:offset</span> + <span class="muControl">break-unless</span> undo + op:address:operation<span class="Special"> <- </span>first undo + typing:insert-operation, is-insert?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">typing:variant</span> + <span class="muControl">break-unless</span> is-insert? + previous-coalesce-tag:number<span class="Special"> <- </span>get typing, <span class="Constant">tag:offset</span> <span class="muControl">break-unless</span> previous-coalesce-tag - insert-until:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *typing, <span class="Constant">insert-until:offset</span> - *insert-until<span class="Special"> <- </span>next *before-cursor - after-row:address:number<span class="Special"> <- </span>get-address *typing, <span class="Constant">after-row:offset</span> - *after-row<span class="Special"> <- </span>copy *cursor-row - after-column:address:number<span class="Special"> <- </span>get-address *typing, <span class="Constant">after-column:offset</span> - *after-column<span class="Special"> <- </span>copy *cursor-column - after-top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *typing, <span class="Constant">after-top-of-screen:offset</span> - *after-top<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + insert-until:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + typing<span class="Special"> <- </span>put typing, <span class="Constant">insert-until:offset</span>, insert-until + typing<span class="Special"> <- </span>put typing, <span class="Constant">after-row:offset</span>, cursor-row + typing<span class="Special"> <- </span>put typing, <span class="Constant">after-column:offset</span>, cursor-column + typing<span class="Special"> <- </span>put typing, <span class="Constant">after-top-of-screen:offset</span>, top-after + *op<span class="Special"> <- </span>merge <span class="Constant">0/insert-operation</span>, typing <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:shared:duplex-list:character<span class="Special"> <- </span>next cursor-before - insert-to:address:shared:duplex-list:character<span class="Special"> <- </span>next insert-from - op:address:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - *op<span class="Special"> <- </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> + insert-from:address:duplex-list:character<span class="Special"> <- </span>next cursor-before + insert-to:address:duplex-list:character<span class="Special"> <- </span>next insert-from + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + *op<span class="Special"> <- </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"> <- </span>add-operation editor, op <span class="Constant"> +done-adding-insert-operation</span> ] <span class="Comment"># enter operations never coalesce with typing before or after</span> <span class="muRecipe">after</span> <span class="Constant"><insert-enter-begin></span> [ - cursor-row-before:number<span class="Special"> <- </span>copy *cursor-row - cursor-column-before:number<span class="Special"> <- </span>copy *cursor-column - top-before:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - cursor-before:address:shared:duplex-list:character<span class="Special"> <- </span>copy *before-cursor + cursor-row-before:number<span class="Special"> <- </span>copy cursor-row + cursor-column-before:number<span class="Special"> <- </span>copy cursor-column + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><insert-enter-end></span> [ - top-after:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> <span class="Comment"># never coalesce</span> - insert-from:address:shared:duplex-list:character<span class="Special"> <- </span>next cursor-before - insert-to:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor - op:address:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - *op<span class="Special"> <- </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> + insert-from:address:duplex-list:character<span class="Special"> <- </span>next cursor-before + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + insert-to:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + *op<span class="Special"> <- </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"> <- </span>add-operation editor, op ] @@ -224,48 +232,53 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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">def</span> add-operation editor:address:shared:editor-data, op:address:shared:operation<span class="muRecipe"> -> </span>editor:address:shared:editor-data [ +<span class="muRecipe">def</span> add-operation editor:address:editor-data, op:address:operation<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> - *undo<span class="Special"> <- </span>push op *undo - redo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">redo:offset</span> - *redo<span class="Special"> <- </span>copy <span class="Constant">0</span> + undo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">undo:offset</span> + undo<span class="Special"> <- </span>push op undo + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">undo:offset</span>, undo + redo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">redo:offset</span> + redo<span class="Special"> <- </span>copy <span class="Constant">0</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">redo:offset</span>, redo <span class="muControl">return</span> editor/same-as-ingredient:<span class="Constant">0</span> ] <span class="muRecipe">after</span> <span class="Constant"><handle-undo></span> [ <span class="Delimiter">{</span> - typing:address:insert-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">typing:variant</span> - <span class="muControl">break-unless</span> typing - start:address:shared:duplex-list:character<span class="Special"> <- </span>get *typing, <span class="Constant">insert-from:offset</span> - end:address:shared:duplex-list:character<span class="Special"> <- </span>get *typing, <span class="Constant">insert-until:offset</span> + typing:insert-operation, is-insert?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">typing:variant</span> + <span class="muControl">break-unless</span> is-insert? + start:address:duplex-list:character<span class="Special"> <- </span>get typing, <span class="Constant">insert-from:offset</span> + end:address:duplex-list:character<span class="Special"> <- </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"> <- </span>prev start - remove-between *before-cursor, end - *cursor-row<span class="Special"> <- </span>get *typing, <span class="Constant">before-row:offset</span> - *cursor-column<span class="Special"> <- </span>get *typing, <span class="Constant">before-column:offset</span> - top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *top<span class="Special"> <- </span>get *typing, <span class="Constant">before-top-of-screen:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>prev start + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor + remove-between before-cursor, end + cursor-row<span class="Special"> <- </span>get typing, <span class="Constant">before-row:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>get typing, <span class="Constant">before-column:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + top:address:duplex-list:character<span class="Special"> <- </span>get typing, <span class="Constant">before-top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> editor-can-undo-typing-multiple [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -279,14 +292,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-typing-multiple-2 [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -298,7 +311,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -312,7 +325,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[3]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -325,15 +338,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-typing-enter [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -342,8 +355,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> . .</span> ] <span class="Comment"># line is indented</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -353,10 +366,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">5</span> @@ -373,7 +386,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -388,14 +401,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-redo-typing [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -407,7 +420,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -421,7 +434,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[3]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -433,30 +446,33 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-redo></span> [ <span class="Delimiter">{</span> - typing:address:insert-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">typing:variant</span> - <span class="muControl">break-unless</span> typing - insert-from:address:shared:duplex-list:character<span class="Special"> <- </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(*before-cursor)</span> - insert-range *before-cursor, insert-from + typing:insert-operation, is-insert?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">typing:variant</span> + <span class="muControl">break-unless</span> is-insert? + before-cursor<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + insert-from:address:duplex-list:character<span class="Special"> <- </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(before-cursor)</span> + insert-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"> <- </span>get *typing, <span class="Constant">after-row:offset</span> - *cursor-column<span class="Special"> <- </span>get *typing, <span class="Constant">after-column:offset</span> - top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *top<span class="Special"> <- </span>get *typing, <span class="Constant">after-top-of-screen:offset</span> + cursor-row<span class="Special"> <- </span>get typing, <span class="Constant">after-row:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>get typing, <span class="Constant">after-column:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + top:address:duplex-list:character<span class="Special"> <- </span>get typing, <span class="Constant">after-top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> editor-redo-typing-empty [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -468,7 +484,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -482,7 +498,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[3]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -495,21 +511,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-work-clears-redo-stack [ <span class="Comment"># create an editor with some text, do some work, undo</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -522,7 +538,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -537,9 +553,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-redo-typing-and-enter-and-tab [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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 [ press tab @@ -550,7 +566,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press tab type <span class="Constant">[efg]</span> ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -558,8 +574,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">7</span> @@ -569,11 +585,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -590,11 +606,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">8</span> @@ -610,11 +626,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> @@ -630,11 +646,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">8</span> @@ -650,11 +666,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -671,11 +687,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">7</span> @@ -694,24 +710,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-touch [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># click undone</span> memory-should-contain [ @@ -723,7 +739,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -735,49 +751,49 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">after</span> <span class="Constant"><move-cursor-begin></span> [ - before-cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> - before-cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> - before-top-of-screen:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row-before:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column-before:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><move-cursor-end></span> [ - after-cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> - after-cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> - after-top-of-screen:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column: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:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> - <span class="muControl">break-unless</span> *undo - op:address:shared:operation<span class="Special"> <- </span>first *undo - move:address:move-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">move:variant</span> - <span class="muControl">break-unless</span> move - previous-coalesce-tag:number<span class="Special"> <- </span>get *move, <span class="Constant">tag:offset</span> + undo:address:list:address:operation<span class="Special"> <- </span>get *editor, <span class="Constant">undo:offset</span> + <span class="muControl">break-unless</span> undo + op:address:operation<span class="Special"> <- </span>first undo + move:move-operation, is-move?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">move:variant</span> + <span class="muControl">break-unless</span> is-move? + previous-coalesce-tag:number<span class="Special"> <- </span>get move, <span class="Constant">tag:offset</span> coalesce?:boolean<span class="Special"> <- </span>equal undo-coalesce-tag, previous-coalesce-tag <span class="muControl">break-unless</span> coalesce? - after-row:address:number<span class="Special"> <- </span>get-address *move, <span class="Constant">after-row:offset</span> - *after-row<span class="Special"> <- </span>copy after-cursor-row - after-column:address:number<span class="Special"> <- </span>get-address *move, <span class="Constant">after-column:offset</span> - *after-column<span class="Special"> <- </span>copy after-cursor-column - after-top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *move, <span class="Constant">after-top-of-screen:offset</span> - *after-top<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + move<span class="Special"> <- </span>put move, <span class="Constant">after-row:offset</span>, cursor-row + move<span class="Special"> <- </span>put move, <span class="Constant">after-column:offset</span>, cursor-column + move<span class="Special"> <- </span>put move, <span class="Constant">after-top-of-screen:offset</span>, top-after + *op<span class="Special"> <- </span>merge <span class="Constant">1/move-operation</span>, move <span class="muControl">break</span> <span class="Constant">+done-adding-move-operation:label</span> <span class="Delimiter">}</span> - op:address:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - *op<span class="Special"> <- </span>merge <span class="Constant">1/move-operation</span>, before-cursor-row, before-cursor-column, before-top-of-screen, after-cursor-row, after-cursor-column, after-top-of-screen, undo-coalesce-tag + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + *op<span class="Special"> <- </span>merge <span class="Constant">1/move-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, undo-coalesce-tag editor<span class="Special"> <- </span>add-operation editor, op <span class="Constant"> +done-adding-move-operation</span> ] <span class="muRecipe">after</span> <span class="Constant"><handle-undo></span> [ <span class="Delimiter">{</span> - move:address:move-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">move:variant</span> - <span class="muControl">break-unless</span> move + move:move-operation, is-move?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">move:variant</span> + <span class="muControl">break-unless</span> is-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:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *cursor-row<span class="Special"> <- </span>get *move, <span class="Constant">before-row:offset</span> - *cursor-column<span class="Special"> <- </span>get *move, <span class="Constant">before-column:offset</span> - *top<span class="Special"> <- </span>get *move, <span class="Constant">before-top-of-screen:offset</span> + cursor-row<span class="Special"> <- </span>get move, <span class="Constant">before-row:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>get move, <span class="Constant">before-column:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + top:address:duplex-list:character<span class="Special"> <- </span>get move, <span class="Constant">before-top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top <span class="Delimiter">}</span> ] @@ -785,18 +801,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># screen has 1 line for menu + 3 lines</span> assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span> <span class="Comment"># editor contains a wrapped line</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">cdefgh]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> <span class="Comment"># 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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> <span class="Comment"># screen scrolls</span> screen-should-contain [ <span class="Constant"> . .</span> @@ -813,9 +829,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moved back</span> memory-should-contain [ @@ -834,7 +850,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -847,25 +863,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-left-arrow [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -877,7 +893,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -891,19 +907,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-up-arrow [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -913,9 +929,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -927,7 +943,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -941,25 +957,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-down-arrow [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -971,7 +987,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -985,27 +1001,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-ctrl-f [ <span class="Comment"># create an editor with multiple pages of text</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen should again show page 1</span> screen-should-contain [ @@ -1020,27 +1036,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-page-down [ <span class="Comment"># create an editor with multiple pages of text</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen should again show page 1</span> screen-should-contain [ @@ -1055,28 +1071,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-ctrl-b [ <span class="Comment"># create an editor with multiple pages of text</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen should again show page 2</span> screen-should-contain [ @@ -1091,28 +1107,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-page-up [ <span class="Comment"># create an editor with multiple pages of text</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[a</span> <span class="Constant">b</span> <span class="Constant">c</span> <span class="Constant">d</span> <span class="Constant">e</span> <span class="Constant">f]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen should again show page 2</span> screen-should-contain [ @@ -1127,25 +1143,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-ctrl-a [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -1157,7 +1173,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1171,25 +1187,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-home [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -1201,7 +1217,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1215,25 +1231,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-ctrl-e [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -1245,7 +1261,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1259,25 +1275,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-end [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves back</span> memory-should-contain [ @@ -1289,7 +1305,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1300,20 +1316,131 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] +<span class="muScenario">scenario</span> editor-can-undo-multiple-arrows-in-the-same-direction [ + <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"> <- </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"> <- </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 right-arrow + press right-arrow + press up-arrow + ] + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> + ] + <span class="Comment"># undo</span> + assume-console [ + press ctrl-z + ] + run [ + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># up-arrow is undone</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> + ] + <span class="Comment"># undo again</span> + assume-console [ + press ctrl-z + ] + run [ + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># both right-arrows are undone</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> + ] +] + +<span class="Comment"># redo cursor movement and scroll</span> + +<span class="muScenario">scenario</span> editor-redo-touch [ + <span class="Comment"># create an editor with some text, click on a character, 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"> <- </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"> <- </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: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:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># cursor moves to left-click</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> + ] + <span class="Comment"># cursor should be in the right place</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"> .abc .</span> + <span class="Constant"> .def .</span> + <span class="Constant"> .g1hi .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + ] +] + +<span class="muRecipe">after</span> <span class="Constant"><handle-redo></span> [ + <span class="Delimiter">{</span> + move:move-operation, is-move?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">move:variant</span> + <span class="muControl">break-unless</span> is-move? + <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"> <- </span>get move, <span class="Constant">after-row:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>get move, <span class="Constant">after-column:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + top:address:duplex-list:character<span class="Special"> <- </span>get move, <span class="Constant">after-top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top + <span class="Delimiter">}</span> +] + <span class="muScenario">scenario</span> editor-separates-undo-insert-from-undo-cursor-move [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> .adbc .</span> @@ -1329,9 +1456,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># last letter typed is deleted</span> screen-should-contain [ @@ -1349,9 +1476,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># no change to screen; cursor moves</span> screen-should-contain [ @@ -1369,9 +1496,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># screen empty</span> screen-should-contain [ @@ -1389,9 +1516,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># first insert</span> screen-should-contain [ @@ -1409,9 +1536,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># cursor moves</span> screen-should-contain [ @@ -1420,6 +1547,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] + <span class="Comment"># cursor moves</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1429,9 +1557,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> ] <span class="Comment"># second insert</span> screen-should-contain [ @@ -1446,138 +1574,29 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muScenario">scenario</span> editor-can-undo-multiple-arrows-in-the-same-direction [ - <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> -<span class="Constant">def</span> -<span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data - <span class="Comment"># move the cursor</span> - assume-console [ - left-click <span class="Constant">2</span>, <span class="Constant">1</span> - press right-arrow - press right-arrow - press up-arrow - ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> - ] - <span class="Comment"># undo</span> - assume-console [ - press ctrl-z - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> - ] - <span class="Comment"># up-arrow is undone</span> - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> - ] - <span class="Comment"># undo again</span> - assume-console [ - press ctrl-z - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> - ] - <span class="Comment"># both right-arrows are undone</span> - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> - ] -] - -<span class="Comment"># redo cursor movement and scroll</span> - -<span class="muScenario">scenario</span> editor-redo-touch [ - <span class="Comment"># create an editor with some text, click on a character, undo</span> - assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> -<span class="Constant">def</span> -<span class="Constant">ghi]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data - assume-console [ - left-click <span class="Constant">3</span>, <span class="Constant">1</span> - press ctrl-z - ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Comment"># redo</span> - assume-console [ - press ctrl-y - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> - ] - <span class="Comment"># cursor moves to left-click</span> - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> - ] - <span class="Comment"># cursor should be in the right place</span> - assume-console [ - type <span class="Constant">[1]</span> - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared:editor-data - ] - screen-should-contain [ - <span class="Constant"> . .</span> - <span class="Constant"> .abc .</span> - <span class="Constant"> .def .</span> - <span class="Constant"> .g1hi .</span> -<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> - ] -] - -<span class="muRecipe">after</span> <span class="Constant"><handle-redo></span> [ - <span class="Delimiter">{</span> - move:address:move-operation<span class="Special"> <- </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> - *cursor-row<span class="Special"> <- </span>get *move, <span class="Constant">after-row:offset</span> - *cursor-column<span class="Special"> <- </span>get *move, <span class="Constant">after-column:offset</span> - top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *top<span class="Special"> <- </span>get *move, <span class="Constant">after-top-of-screen:offset</span> - <span class="Delimiter">}</span> -] - <span class="Comment"># undo backspace</span> <span class="muScenario">scenario</span> editor-can-undo-and-redo-backspace [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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 [ type <span class="Constant">[abc]</span> press backspace press backspace ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1587,10 +1606,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> @@ -1606,10 +1625,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1624,39 +1643,39 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># save operation to undo</span> <span class="muRecipe">after</span> <span class="Constant"><backspace-character-begin></span> [ - top-before:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><backspace-character-end></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:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + undo:address:list:address:operation<span class="Special"> <- </span>get *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 - op:address:shared:operation<span class="Special"> <- </span>first *undo - deletion:address:delete-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> - <span class="muControl">break-unless</span> deletion - previous-coalesce-tag:number<span class="Special"> <- </span>get *deletion, <span class="Constant">tag:offset</span> + op:address:operation<span class="Special"> <- </span>first undo + deletion:delete-operation, is-delete?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> + <span class="muControl">break-unless</span> is-delete? + previous-coalesce-tag:number<span class="Special"> <- </span>get deletion, <span class="Constant">tag:offset</span> coalesce?:boolean<span class="Special"> <- </span>equal previous-coalesce-tag, <span class="Constant">1/coalesce-backspace</span> <span class="muControl">break-unless</span> coalesce? - delete-from:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *deletion, <span class="Constant">delete-from:offset</span> - *delete-from<span class="Special"> <- </span>copy *before-cursor - backspaced-so-far:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span> - insert-range backspaced-cell, *backspaced-so-far - *backspaced-so-far<span class="Special"> <- </span>copy backspaced-cell - after-row:address:number<span class="Special"> <- </span>get-address *deletion, <span class="Constant">after-row:offset</span> - *after-row<span class="Special"> <- </span>copy *cursor-row - after-column:address:number<span class="Special"> <- </span>get-address *deletion, <span class="Constant">after-column:offset</span> - *after-column<span class="Special"> <- </span>copy *cursor-column - after-top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span> - *after-top<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">delete-from:offset</span>, before-cursor + backspaced-so-far:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">deleted-text:offset</span> + insert-range backspaced-cell, backspaced-so-far + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">deleted-text:offset</span>, backspaced-cell + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">after-row:offset</span>, cursor-row + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">after-column:offset</span>, cursor-column + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">after-top-of-screen:offset</span>, top-after + *op<span class="Special"> <- </span>merge <span class="Constant">2/delete-operation</span>, deletion <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:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - deleted-until:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor - *op<span class="Special"> <- </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> + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + deleted-until:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + *op<span class="Special"> <- </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"> <- </span>add-operation editor, op <span class="Constant"> +done-adding-backspace-operation</span> <span class="Delimiter">}</span> @@ -1664,35 +1683,39 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><handle-undo></span> [ <span class="Delimiter">{</span> - deletion:address:delete-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> - <span class="muControl">break-unless</span> deletion - start2:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">data:offset</span> - anchor:address:shared:duplex-list:character<span class="Special"> <- </span>get *deletion, <span class="Constant">delete-from:offset</span> + deletion:delete-operation, is-delete?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> + <span class="muControl">break-unless</span> is-delete? + anchor:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">delete-from:offset</span> <span class="muControl">break-unless</span> anchor - deleted:address:shared:duplex-list:character<span class="Special"> <- </span>get *deletion, <span class="Constant">deleted-text:offset</span> - old-cursor:address:shared:duplex-list:character<span class="Special"> <- </span>last deleted + deleted:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">deleted-text:offset</span> + old-cursor:address:duplex-list:character<span class="Special"> <- </span>last deleted insert-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"> <- </span>copy old-cursor - *cursor-row<span class="Special"> <- </span>get *deletion, <span class="Constant">before-row:offset</span> - *cursor-column<span class="Special"> <- </span>get *deletion, <span class="Constant">before-column:offset</span> - top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *top<span class="Special"> <- </span>get *deletion, <span class="Constant">before-top-of-screen:offset</span> + before-cursor<span class="Special"> <- </span>copy old-cursor + cursor-row<span class="Special"> <- </span>get deletion, <span class="Constant">before-row:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>get deletion, <span class="Constant">before-column:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + top:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">before-top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top <span class="Delimiter">}</span> ] <span class="muRecipe">after</span> <span class="Constant"><handle-redo></span> [ <span class="Delimiter">{</span> - deletion:address:delete-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> - <span class="muControl">break-unless</span> deletion - start:address:shared:duplex-list:character<span class="Special"> <- </span>get *deletion, <span class="Constant">delete-from:offset</span> - end:address:shared:duplex-list:character<span class="Special"> <- </span>get *deletion, <span class="Constant">delete-until:offset</span> + deletion:delete-operation, is-delete?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> + <span class="muControl">break-unless</span> is-delete? + start:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">delete-from:offset</span> + end:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">delete-until:offset</span> + data:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> remove-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"> <- </span>get *deletion, <span class="Constant">after-row:offset</span> - *cursor-column<span class="Special"> <- </span>get *deletion, <span class="Constant">after-column:offset</span> - top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span> - *top<span class="Special"> <- </span>get *deletion, <span class="Constant">after-top-of-screen:offset</span> + cursor-row<span class="Special"> <- </span>get deletion, <span class="Constant">after-row:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row + cursor-column<span class="Special"> <- </span>get deletion, <span class="Constant">after-column:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column + top:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">before-top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">top-of-screen:offset</span>, top <span class="Delimiter">}</span> ] @@ -1701,9 +1724,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-and-redo-delete [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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">[abcdef]</span> @@ -1713,15 +1736,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press delete press delete ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1731,10 +1754,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1750,10 +1773,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -1769,10 +1792,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -1788,11 +1811,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -1808,11 +1831,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1828,11 +1851,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1846,38 +1869,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">after</span> <span class="Constant"><delete-character-begin></span> [ - top-before:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><delete-character-end></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:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + undo:address:list:address:operation<span class="Special"> <- </span>get *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 - op:address:shared:operation<span class="Special"> <- </span>first *undo - deletion:address:delete-operation<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> - <span class="muControl">break-unless</span> deletion - previous-coalesce-tag:number<span class="Special"> <- </span>get *deletion, <span class="Constant">tag:offset</span> + <span class="muControl">break-unless</span> undo + op:address:operation<span class="Special"> <- </span>first undo + deletion:delete-operation, is-delete?:boolean<span class="Special"> <- </span>maybe-convert *op, <span class="Constant">delete:variant</span> + <span class="muControl">break-unless</span> is-delete? + previous-coalesce-tag:number<span class="Special"> <- </span>get deletion, <span class="Constant">tag:offset</span> coalesce?:boolean<span class="Special"> <- </span>equal previous-coalesce-tag, <span class="Constant">2/coalesce-delete</span> <span class="muControl">break-unless</span> coalesce? - delete-until:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *deletion, <span class="Constant">delete-until:offset</span> - *delete-until<span class="Special"> <- </span>next *before-cursor - deleted-so-far:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span> - *deleted-so-far<span class="Special"> <- </span>append *deleted-so-far, deleted-cell - after-row:address:number<span class="Special"> <- </span>get-address *deletion, <span class="Constant">after-row:offset</span> - *after-row<span class="Special"> <- </span>copy *cursor-row - after-column:address:number<span class="Special"> <- </span>get-address *deletion, <span class="Constant">after-column:offset</span> - *after-column<span class="Special"> <- </span>copy *cursor-column - after-top:address:address:shared:duplex-list:character<span class="Special"> <- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span> - *after-top<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + delete-until:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">delete-until:offset</span>, delete-until + deleted-so-far:address:duplex-list:character<span class="Special"> <- </span>get deletion, <span class="Constant">deleted-text:offset</span> + deleted-so-far<span class="Special"> <- </span>append deleted-so-far, deleted-cell + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">deleted-text:offset</span>, deleted-so-far + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">after-row:offset</span>, cursor-row + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">after-column:offset</span>, cursor-column + deletion<span class="Special"> <- </span>put deletion, <span class="Constant">after-top-of-screen:offset</span>, top-after + *op<span class="Special"> <- </span>merge <span class="Constant">2/delete-operation</span>, deletion <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:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - deleted-until:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor - *op<span class="Special"> <- </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> + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + deleted-until:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + *op<span class="Special"> <- </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"> <- </span>add-operation editor, op <span class="Constant"> +done-adding-delete-operation</span> <span class="Delimiter">}</span> @@ -1888,16 +1913,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-and-redo-ctrl-k [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1905,8 +1930,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1916,7 +1941,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1925,8 +1950,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1936,7 +1961,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -1946,8 +1971,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> @@ -1957,7 +1982,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -1969,16 +1994,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">after</span> <span class="Constant"><delete-to-end-of-line-begin></span> [ - top-before:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><delete-to-end-of-line-end></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:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> - op:address:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - deleted-until:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor - *op<span class="Special"> <- </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> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + deleted-until:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + *op<span class="Special"> <- </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"> <- </span>add-operation editor, op <span class="Constant"> +done-adding-delete-operation</span> <span class="Delimiter">}</span> @@ -1989,16 +2015,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> editor-can-undo-and-redo-ctrl-u [ <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2006,8 +2032,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> @@ -2017,7 +2043,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2026,8 +2052,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> @@ -2037,7 +2063,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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 [ @@ -2047,8 +2073,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> <span class="Constant"> . .</span> ] - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:shared:editor-data, <span class="Constant">cursor-column:offset</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> @@ -2058,7 +2084,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type <span class="Constant">[1]</span> ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> @@ -2070,16 +2096,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muRecipe">after</span> <span class="Constant"><delete-to-start-of-line-begin></span> [ - top-before:address:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + top-before:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> ] <span class="muRecipe">before</span> <span class="Constant"><delete-to-start-of-line-end></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:shared:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> - undo:address:address:shared:list:address:shared:operation<span class="Special"> <- </span>get-address *editor, <span class="Constant">undo:offset</span> - op:address:shared:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> - deleted-until:address:shared:duplex-list:character<span class="Special"> <- </span>next *before-cursor - *op<span class="Special"> <- </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> + top-after:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + op:address:operation<span class="Special"> <- </span>new <span class="Constant">operation:type</span> + before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + deleted-until:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + *op<span class="Special"> <- </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"> <- </span>add-operation editor, op <span class="Constant"> +done-adding-delete-operation</span> <span class="Delimiter">}</span> @@ -2088,16 +2116,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <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:shared:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - <span class="Constant">2</span>:address:shared:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:shared:array:character, screen:address:shared:screen, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> - editor-render screen, <span class="Constant">2</span>:address:shared:editor-data + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">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:shared:screen, console:address:shared:console, <span class="Constant">2</span>:address:shared: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> diff --git a/html/global.mu.html b/html/global.mu.html index f155c7b7..3c0b8e86 100644 --- a/html/global.mu.html +++ b/html/global.mu.html @@ -32,7 +32,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> main [ <span class="Comment"># allocate 5 locations for globals</span> - <span class="Constant">global-space</span>:address:shared:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">5</span> + <span class="Constant">global-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">5</span> <span class="Comment"># read to globals by using /space:global</span> <span class="Special">1:number/space:global</span><span class="Special"> <- </span>copy <span class="Constant">3</span> foo diff --git a/index.html b/index.html index 1f72e0d6..36050d5d 100644 --- a/index.html +++ b/index.html @@ -89,27 +89,31 @@ harness for adding per-primitive checks to run before running a program. <br/>Various primitive operations: on <a href='html/022arithmetic.cc.html'>numbers</a>, <a href='html/023boolean.cc.html'>booleans</a>, for <a href='html/024jump.cc.html'>control flow</a>, and <a href='html/025compare.cc.html'>comparing values</a>. +<br/><a href='html/026call.cc.html'>026call.cc</a>: calls to functions look +just like primitive operations. +<br/><a href='html/027call_ingredient.cc.html'>027call_ingredient.cc</a>: how +functions pass arguments or 'ingredients' without introducing any syntax and +breaking the metaphor of functions as lists of instructions. +<br/><a href='html/028call_reply.cc.html'>028call_reply.cc</a>: functions can +return arbitrary numbers of values to their callers. <br/><a href='html/029tools.cc.html'>029tools.cc</a>: various primitive operations to help with testing and debugging. <p/><a href='html/030container.cc.html'>030container.cc</a>: Mu supports compound types called<em>containers</em> akin to records, structs or classes. -<br/><a href='html/031address.cc.html'>031address.cc</a>: adding and removing -layers of indirection to Mu data. -<br/><a href='html/032array.cc.html'>032array.cc</a>: all Mu data structures +<br/><a href='html/031array.cc.html'>031array.cc</a>: all Mu data structures are bounds-checked. -<br/><a href='html/033exclusive_container.cc.html'>033exclusive_container.cc</a>: +<br/><a href='html/032exclusive_container.cc.html'>032exclusive_container.cc</a>: tagged unions or sum types. -<br/><a href='html/034call.cc.html'>034call.cc</a>: calls to functions look -just like primitive operations. -<br/><a href='html/035call_ingredient.cc.html'>035call_ingredient.cc</a>: how -functions pass arguments or 'ingredients' without introducing any syntax and -breaking the metaphor of functions as lists of instructions. -<br/><a href='html/036call_reply.cc.html'>036call_reply.cc</a>: functions can -return arbitrary numbers of values to their callers. -<br/><a href='html/037new.cc.html'>037new.cc</a>: rudimentary memory -allocator that is aware of all global types in any Mu program. -<br/><a href='html/061recipe.cc.html'>061recipe.cc</a>: passing functions +<br/><a href='html/033address.cc.html'>033address.cc</a>: Mu requires you to +manually manage memory. However, it provides transparent refcounting for all +addresses, making it entirely safe from the sorts of undefined behavior and +security vulnerabilities that plague C. Compared to Rust, Mu gives up some +runtime efficiency in exchange for C-like flexibility (you can copy addresses +around all you like, and write from any copy of an address) and simpler +implementation (since I punt on Rust's static analysis). + +<p/><a href='html/061recipe.cc.html'>061recipe.cc</a>: passing functions around as first-class values in higher-order functions. <br/><a href='html/062scheduler.cc.html'>062scheduler.cc</a>: running multiple functions concurrently using <em>routines</em> that might execute in |