diff options
Diffstat (limited to 'html')
54 files changed, 3437 insertions, 2997 deletions
diff --git a/html/002test.cc.html b/html/002test.cc.html index d6d5ece6..e93a5c73 100644 --- a/html/002test.cc.html +++ b/html/002test.cc.html @@ -87,7 +87,7 @@ if <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> <sp time_t t<span class="Delimiter">;</span> time<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> cerr << <span class="Constant">"C tests: "</span> << ctime<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> for <span class="Delimiter">(</span>size_t i=<span class="Constant">0</span><span class="Delimiter">;</span> i < sizeof<span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/sizeof<span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << i << '\n'; //? 2</span> +<span class="CommentedCode">//? cerr << i << '\n';</span> run_test<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// End Tests</span> diff --git a/html/003trace.cc.html b/html/003trace.cc.html index 6209ed7b..3b76a730 100644 --- a/html/003trace.cc.html +++ b/html/003trace.cc.html @@ -15,11 +15,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } .PreProc { color: #c000c0; } -.Identifier { color: #804000; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } --> </style> @@ -116,7 +115,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">:(before "End Tracing")</span> bool Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> -<span class="CommentedCode">//? cerr << "AAA setup\n"; //? 2</span> Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End Types")</span> @@ -169,7 +167,6 @@ struct trace_stream <span class="Delimiter">{</span> past_lines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>trace_line<span class="Delimiter">(</span>curr_depth<span class="Delimiter">,</span> trim<span class="Delimiter">(</span>curr_layer<span class="Delimiter">),</span> curr_contents<span class="Delimiter">));</span> <span class="Comment">// preserve indent in contents</span> if <span class="Delimiter">(</span>curr_layer == dump_layer || curr_layer == <span class="Constant">"dump"</span> || dump_layer == <span class="Constant">"all"</span> || <span class="Delimiter">(</span>!Hide_warnings && curr_layer == <span class="Constant">"warn"</span><span class="Delimiter">))</span> -<span class="CommentedCode">//? if (dump_layer == "all" && (Current_routine->id == 3 || curr_layer == "schedule")) //? 1</span> cerr << curr_layer << <span class="Constant">": "</span> << curr_contents << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> delete curr_stream<span class="Delimiter">;</span> curr_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> @@ -222,9 +219,8 @@ string Trace_file<span class="Delimiter">;</span> struct lease_tracer <span class="Delimiter">{</span> lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span> Trace_stream = new trace_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span> ~lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "write to file? " << Trace_file << "$\n"; //? 2</span> + if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// in case tests close Trace_stream</span> if <span class="Delimiter">(</span>!Trace_file<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "writing\n"; //? 2</span> ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> fout << Trace_stream<span class="Delimiter">-></span>readable_contents<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span> @@ -236,7 +232,6 @@ struct lease_tracer <span class="Delimiter">{</span> <span class="PreProc">#define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End Test Setup")</span> START_TRACING_UNTIL_END_OF_SCOPE -<span class="CommentedCode">//? Trace_stream->dump_layer = "all"; //? 1</span> <span class="PreProc">#define CHECK_TRACE_CONTENTS(</span><span class="Delimiter">...</span><span class="PreProc">) check_trace_contents(__FUNCTION__</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">__FILE__</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">__LINE__</span><span class="Delimiter">,</span><span class="PreProc"> __VA_ARGS__)</span> @@ -250,15 +245,12 @@ bool check_trace_contents<span class="Delimiter">(</span>string FUNCTION<span cl string layer<span class="Delimiter">,</span> contents<span class="Delimiter">;</span> split_layer_contents<span class="Delimiter">(</span>expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">),</span> &layer<span class="Delimiter">,</span> &contents<span class="Delimiter">);</span> for <span class="Delimiter">(</span>vector<trace_line>::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "AAA " << layer << ' ' << p->label << '\n'; //? 1</span> if <span class="Delimiter">(</span>layer != p<span class="Delimiter">-></span>label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "BBB ^" << contents << "$ ^" << p->contents << "$\n"; //? 1</span> if <span class="Delimiter">(</span>contents != trim<span class="Delimiter">(</span>p<span class="Delimiter">-></span>contents<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "CCC\n"; //? 1</span> ++curr_expected_line<span class="Delimiter">;</span> while <span class="Delimiter">(</span>curr_expected_line < SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">)</span> && expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>empty<span class="Delimiter">())</span> ++curr_expected_line<span class="Delimiter">;</span> @@ -269,7 +261,6 @@ bool check_trace_contents<span class="Delimiter">(</span>string FUNCTION<span cl ++Num_failures<span class="Delimiter">;</span> cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << FUNCTION << <span class="Constant">"("</span> << FILE << <span class="Constant">":"</span> << LINE << <span class="Constant">"): missing ["</span> << contents << <span class="Constant">"] in trace:</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> DUMP<span class="Delimiter">(</span>layer<span class="Delimiter">);</span> -<span class="CommentedCode">//? exit(0); //? 1</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -297,8 +288,6 @@ int trace_count<span class="Delimiter">(</span>string layer<span class="Delimite long result = <span class="Constant">0</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>vector<trace_line>::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>layer == p<span class="Delimiter">-></span>label<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "a: " << line << "$\n"; //? 1</span> -<span class="CommentedCode">//? cerr << "b: " << trim(p->contents) << "$\n"; //? 1</span> if <span class="Delimiter">(</span>line == <span class="Constant">""</span> || line == trim<span class="Delimiter">(</span>p<span class="Delimiter">-></span>contents<span class="Delimiter">))</span> ++result<span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/010vm.cc.html b/html/010vm.cc.html index 45e698f0..c4fb8ccf 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -14,12 +14,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.Identifier { color: #804000; } .PreProc { color: #c000c0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .SalientComment { color: #00ffff; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } --> </style> @@ -234,7 +233,6 @@ reagent::reagent<span class="Delimiter">(</span>string s<span class="Delimiter"> if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>type<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">()</span> <span class="Comment">// types can contain integers, like for array sizes</span> && !is_integer<span class="Delimiter">(</span>type<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << type << " is " << Next_type_ordinal << '\n'; //? 1</span> Type_ordinal[type] = Next_type_ordinal++<span class="Delimiter">;</span> <span class="Delimiter">}</span> types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[type]<span class="Delimiter">);</span> @@ -273,7 +271,6 @@ string reagent::to_string<span class="Delimiter">()</span> const <span class="De <span class="Delimiter">}</span> <span class="Delimiter">}</span> out << <span class="Constant">"}"</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? if (properties.at(0).second.empty()) cerr << out.str(); //? 1</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> diff --git a/html/011load.cc.html b/html/011load.cc.html index f6d9ea85..123ce5ce 100644 --- a/html/011load.cc.html +++ b/html/011load.cc.html @@ -13,7 +13,7 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.CommentedCode { color: #6c6c6c; } +.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -54,41 +54,46 @@ vector<recipe_ordinal> load<span class="Delimiter">(</span>istream& in in >> std::noskipws<span class="Delimiter">;</span> vector<recipe_ordinal> result<span class="Delimiter">;</span> while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "===\n"; //? 1</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> string command = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Comment">// Command Handlers</span> if <span class="Delimiter">(</span>command == <span class="Constant">"recipe"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - string recipe_name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "recipe: " << recipe_name << '\n'; //? 2</span> - if <span class="Delimiter">(</span>recipe_name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> - raise << <span class="Constant">"empty recipe name</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> == Recipe_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - Recipe_ordinal[recipe_name] = Next_recipe_ordinal++<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>warn_on_redefine<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> - && Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Recipe_ordinal[recipe_name]<span class="Delimiter">)</span> != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"redefining recipe "</span> << Recipe[Recipe_ordinal[recipe_name]]<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="Delimiter">}</span> - <span class="Comment">// todo: save user-defined recipes to mu's memory</span> - Recipe[Recipe_ordinal[recipe_name]] = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << Recipe_ordinal[recipe_name] << ": " << recipe_name << '\n'; //? 2</span> - Recipe[Recipe_ordinal[recipe_name]]<span class="Delimiter">.</span>name = recipe_name<span class="Delimiter">;</span> - <span class="Comment">// track added recipes because we may need to undo them in tests; see below</span> - recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Recipe_ordinal[recipe_name]<span class="Delimiter">);</span> - result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Recipe_ordinal[recipe_name]<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>command == <span class="Constant">"recipe!"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + Disable_redefine_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">));</span> + Disable_redefine_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">// End Command Handlers</span> else <span class="Delimiter">{</span> raise << <span class="Constant">"unknown top-level command: "</span> << command << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - <span class="Comment">// End Load Sanity Checks</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> -recipe slurp_recipe<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> +long long int slurp_recipe<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string recipe_name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>recipe_name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + raise << <span class="Constant">"empty recipe name</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> == Recipe_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Recipe_ordinal[recipe_name] = Next_recipe_ordinal++<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>warn_on_redefine<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> + && Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Recipe_ordinal[recipe_name]<span class="Delimiter">)</span> != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"redefining recipe "</span> << Recipe[Recipe_ordinal[recipe_name]]<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="Delimiter">}</span> + <span class="Comment">// todo: save user-defined recipes to mu's memory</span> + Recipe[Recipe_ordinal[recipe_name]] = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + Recipe[Recipe_ordinal[recipe_name]]<span class="Delimiter">.</span>name = recipe_name<span class="Delimiter">;</span> + <span class="Comment">// track added recipes because we may need to undo them in tests; see below</span> + recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Recipe_ordinal[recipe_name]<span class="Delimiter">);</span> + <span class="Identifier">return</span> Recipe_ordinal[recipe_name]<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +recipe slurp_body<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe result<span class="Delimiter">;</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> @@ -97,7 +102,6 @@ recipe slurp_recipe<span class="Delimiter">(</span>istream& in<span class="D instruction curr<span class="Delimiter">;</span> while <span class="Delimiter">(</span>next_instruction<span class="Delimiter">(</span>in<span class="Delimiter">,</span> &curr<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// End Rewrite Instruction(curr)</span> -<span class="CommentedCode">//? cerr << "instruction: " << curr.to_string() << '\n'; //? 3</span> result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> @@ -110,13 +114,11 @@ bool next_instruction<span class="Delimiter">(</span>istream& in<span class= raise << <span class="Constant">"0: unbalanced '[' for recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> raise << <span class="Constant">"1: unbalanced '[' for recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> raise << <span class="Constant">"2: unbalanced '[' for recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> @@ -124,20 +126,17 @@ bool next_instruction<span class="Delimiter">(</span>istream& in<span class= <span class="Delimiter">}</span> vector<string> words<span class="Delimiter">;</span> -<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span> && !in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> raise << <span class="Constant">"3: unbalanced '[' for recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> string word = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> words<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>word<span class="Delimiter">);</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Delimiter">}</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? if (SIZE(words) == 1) cout << words.at(0) << ' ' << SIZE(words.at(0)) << '\n'; //? 1</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>words<span class="Delimiter">)</span> == <span class="Constant">1</span> && words<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="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// end of recipe</span> <span class="Delimiter">}</span> @@ -158,7 +157,6 @@ bool next_instruction<span class="Delimiter">(</span>istream& in<span class= for <span class="Delimiter">(;</span> *p != <span class="Constant">"<-"</span><span class="Delimiter">;</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>*p == <span class="Constant">","</span><span class="Delimiter">)</span> <span class="Identifier">continue</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>*p<span class="Delimiter">));</span> -<span class="CommentedCode">//? cerr << "product: " << curr->products.back().to_string() << '\n'; //? 1</span> <span class="Delimiter">}</span> ++p<span class="Delimiter">;</span> <span class="Comment">// skip <-</span> <span class="Delimiter">}</span> @@ -170,7 +168,6 @@ bool next_instruction<span class="Delimiter">(</span>istream& in<span class= curr<span class="Delimiter">-></span>name = *p<span class="Delimiter">;</span> if <span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>*p<span class="Delimiter">)</span> == Recipe_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> Recipe_ordinal[*p] = Next_recipe_ordinal++<span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << "AAA: " << *p << " is now " << Recipe_ordinal[*p] << '\n'; //? 1</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>Recipe_ordinal[*p] == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << <span class="Constant">"Recipe "</span> << *p << <span class="Constant">" has number 0, which is reserved for IDLE.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">()</span> << end<span class="Delimiter">();</span> @@ -181,7 +178,6 @@ bool next_instruction<span class="Delimiter">(</span>istream& in<span class= for <span class="Delimiter">(;</span> p != words<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>*p == <span class="Constant">","</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> curr<span class="Delimiter">-></span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>*p<span class="Delimiter">));</span> -<span class="CommentedCode">//? cerr << "ingredient: " << curr->ingredients.back().to_string() << '\n'; //? 1</span> <span class="Delimiter">}</span> trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"instruction: "</span> << curr<span class="Delimiter">-></span>name << end<span class="Delimiter">();</span> @@ -199,26 +195,22 @@ bool next_instruction<span class="Delimiter">(</span>istream& in<span class= <span class="Delimiter">}</span> string next_word<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "AAA next_word\n"; //? 1</span> ostringstream out<span class="Delimiter">;</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> slurp_word<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">);</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << '^' << out.str() << "$\n"; //? 1</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> void slurp_word<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "AAA slurp_word\n"; //? 1</span> char c<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> in >> c<span class="Delimiter">;</span> out << c<span class="Delimiter">;</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> while <span class="Delimiter">(</span>in >> c<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << c << '\n'; //? 1</span> if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>c<span class="Delimiter">)</span> || c == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>putback<span class="Delimiter">(</span>c<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -228,13 +220,14 @@ void slurp_word<span class="Delimiter">(</span>istream& in<span class="Delim <span class="Delimiter">}</span> void skip_whitespace<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> - while <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> && isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> void skip_whitespace_and_comments<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> while <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()))</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> else <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -242,15 +235,15 @@ void skip_whitespace_and_comments<span class="Delimiter">(</span>istream& in <span class="Delimiter">}</span> void skip_comment<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> - while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> void skip_comma<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">()</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -288,7 +281,6 @@ vector<recipe_ordinal> recently_added_recipes<span class="Delimiter">;</sp long long int Reserved_for_tests = <span class="Constant">1000</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "AAA clearing " << Recipe[recently_added_recipes.at(i)].name << '\n'; //? 2</span> if <span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> >= Reserved_for_tests<span class="Delimiter">)</span> <span class="Comment">// don't renumber existing recipes, like 'interactive'</span> Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe[recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> @@ -401,6 +393,38 @@ recipe main [ <span class="Constant">1</span>:number:address/lookup<span class="Special"> <- </span>copy <span class="Constant">23</span> ] <span class="traceContains">+parse: product: {name: "1", properties: ["1": "number":"address", "lookup": ]}</span> + +<span class="Comment">//: this test we can't represent with a scenario</span> +<span class="Delimiter">:(code)</span> +void test_parse_comment_terminated_by_eof<span class="Delimiter">()</span> <span class="Delimiter">{</span> + Trace_file = <span class="Constant">"parse_comment_terminated_by_eof"</span><span class="Delimiter">;</span> + load<span class="Delimiter">(</span><span class="Constant">"recipe main [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" a:number <- copy 34</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"# abc"</span><span class="Delimiter">);</span> <span class="Comment">// no newline after comment</span> + cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> <span class="Comment">// termination = success</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario warn_on_redefine)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> +] +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">24</span> +] +<span class="traceContains">+warn: redefining recipe main</span> + +<span class="Delimiter">:(scenario redefine_without_warning)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">23</span> +] +recipe! main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">24</span> +] +<span class="traceAbsent">-warn: redefining recipe main</span> +$warn: <span class="Constant">0</span> </pre> </body> </html> diff --git a/html/012transform.cc.html b/html/012transform.cc.html index acd35f6c..24c3b436 100644 --- a/html/012transform.cc.html +++ b/html/012transform.cc.html @@ -13,11 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.Identifier { color: #804000; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } --> </style> @@ -46,7 +45,6 @@ vector<transform_fn> Transform<span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> void transform_all<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "AAA transform_all\n"; //? 2</span> for <span class="Delimiter">(</span>long long int t = <span class="Constant">0</span><span class="Delimiter">;</span> t < SIZE<span class="Delimiter">(</span>Transform<span class="Delimiter">);</span> ++t<span class="Delimiter">)</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>map<recipe_ordinal<span class="Delimiter">,</span> recipe>::iterator p = Recipe<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe& r = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> @@ -57,10 +55,10 @@ void transform_all<span class="Delimiter">()</span> <span class="Delimiter">{</s <span class="Delimiter">}</span> <span class="Delimiter">}</span> parse_int_reagents<span class="Delimiter">();</span> <span class="Comment">// do this after all other transforms have run</span> + <span class="Comment">// End Transform</span> <span class="Delimiter">}</span> void parse_int_reagents<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "parse_int_reagents\n"; //? 1</span> for <span class="Delimiter">(</span>map<recipe_ordinal<span class="Delimiter">,</span> recipe>::iterator p = Recipe<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe& r = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> diff --git a/html/013literal_string.cc.html b/html/013literal_string.cc.html index 735e67e0..56fff30c 100644 --- a/html/013literal_string.cc.html +++ b/html/013literal_string.cc.html @@ -13,12 +13,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.Identifier { color: #804000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } .traceContains { color: #008000; } --> @@ -60,7 +59,6 @@ Type_ordinal[<span class="Constant">"literal-string"</span>] = <span c string result = slurp_quoted<span class="Delimiter">(</span>in<span class="Delimiter">);</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << '^' << result << "$\n"; //? 1</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -82,12 +80,10 @@ bool code_string<span class="Delimiter">(</span>istream& in<span class="Deli char c = in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> if <span class="Delimiter">(</span>!isspace<span class="Delimiter">(</span>c<span class="Delimiter">))</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>putback<span class="Delimiter">(</span>c<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "code_string: " << out.str() << '\n'; //? 1</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> out << c<span class="Delimiter">;</span> if <span class="Delimiter">(</span>c == <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "code_string: " << out.str() << '\n'; //? 1</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -97,18 +93,14 @@ bool code_string<span class="Delimiter">(</span>istream& in<span class="Deli <span class="Comment">// Read a regular string. Regular strings can only contain other regular</span> <span class="Comment">// strings.</span> void slurp_quoted_comment_oblivious<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostringstream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "comment oblivious\n"; //? 1</span> int brace_depth = <span class="Constant">1</span><span class="Delimiter">;</span> while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> char c = in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << '%' << (int)c << ' ' << brace_depth << ": " << out.str() << "%$\n"; //? 1</span> -<span class="CommentedCode">//? cout << (int)c << ": " << brace_depth << '\n'; //? 2</span> if <span class="Delimiter">(</span>c == <span class="cSpecial">'\\'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> out << static_cast<char><span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">());</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> out << c<span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << out.str() << "$\n"; //? 1</span> if <span class="Delimiter">(</span>c == <span class="Constant">'['</span><span class="Delimiter">)</span> ++brace_depth<span class="Delimiter">;</span> if <span class="Delimiter">(</span>c == <span class="Constant">']'</span><span class="Delimiter">)</span> --brace_depth<span class="Delimiter">;</span> if <span class="Delimiter">(</span>brace_depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -121,10 +113,8 @@ void slurp_quoted_comment_oblivious<span class="Delimiter">(</span>istream& <span class="Comment">// Read a code string. Code strings can contain either code or regular strings.</span> void slurp_quoted_comment_aware<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostringstream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "comment aware\n"; //? 1</span> char c<span class="Delimiter">;</span> while <span class="Delimiter">(</span>in >> c<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << '^' << (int)c << ": " << out.str() << "$\n"; //? 1</span> if <span class="Delimiter">(</span>c == <span class="cSpecial">'\\'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> out << static_cast<char><span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">());</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> diff --git a/html/020run.cc.html b/html/020run.cc.html index a6e9548f..92ad8931 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -14,15 +14,16 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .SalientComment { color: #00ffff; } -.Identifier { color: #804000; } +.CommentedCode { color: #6c6c6c; } +.PreProc { color: #c000c0; } .traceAbsent { color: #c00000; } +.Delimiter { color: #a04060; } +.traceContains { color: #008000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } -.Delimiter { color: #a04060; } -.Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } +.Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -96,7 +97,7 @@ void run_current_routine<span class="Delimiter">()</span> while <span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>completed<span class="Delimiter">())</span> <span class="Comment">// later layers will modify condition</span> <span class="Delimiter">{</span> <span class="Comment">// Running One Instruction</span> -<span class="CommentedCode">//? Instructions_running[current_recipe_name()]++; //? 1</span> +<span class="CommentedCode">//? Instructions_running[current_recipe_name()]++;</span> if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> ++current_step_index<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> trace<span class="Delimiter">(</span>Initial_callstack_depth+Callstack_depth<span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> << end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>Memory[<span class="Constant">0</span>] != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -110,8 +111,8 @@ void run_current_routine<span class="Delimiter">()</span> if <span class="Delimiter">(</span>should_copy_ingredients<span class="Delimiter">())</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)));</span> -<span class="CommentedCode">//? Locations_read[current_recipe_name()] += SIZE(ingredients.back()); //? 1</span> -<span class="CommentedCode">//? Locations_read_by_instruction[current_instruction().name] += SIZE(ingredients.back()); //? 1</span> +<span class="CommentedCode">//? Locations_read[current_recipe_name()] += SIZE(ingredients.back());</span> +<span class="CommentedCode">//? Locations_read_by_instruction[current_instruction().name] += SIZE(ingredients.back());</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// Instructions below will write to 'products'.</span> @@ -181,26 +182,46 @@ inline bool routine::completed<span class="Delimiter">()</span> const <span clas <span class="Identifier">return</span> running_step_index >= SIZE<span class="Delimiter">(</span>Recipe[running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="SalientComment">//:: Startup flow</span> + +<span class="Comment">//: Step 1: load all .mu files with numeric prefixes (in order)</span> +<span class="Delimiter">:(before "End Load Recipes")</span> +load_permanently<span class="Delimiter">(</span><span class="Constant">"core.mu"</span><span class="Delimiter">);</span> +transform_all<span class="Delimiter">();</span> + +<span class="Comment">//: Step 2: load any .mu files provided at the commandline</span> <span class="Delimiter">:(before "End Commandline Parsing")</span> -<span class="Comment">// Loading Commandline Files</span> if <span class="Delimiter">(</span>argc > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>int i = <span class="Constant">1</span><span class="Delimiter">;</span> i < argc<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - load_permanently<span class="Delimiter">(</span>argv[i]<span class="Delimiter">);</span> + <span class="Comment">// skip argv[0]</span> + argv++<span class="Delimiter">;</span> + argc--<span class="Delimiter">;</span> + <span class="Comment">// ignore argv past '--'; that's commandline args for 'main'</span> + while <span class="Delimiter">(</span>argc > <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>string<span class="Delimiter">(</span>*argv<span class="Delimiter">)</span> == <span class="Constant">"--"</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + load_permanently<span class="Delimiter">(</span>*argv<span class="Delimiter">);</span> + argv++<span class="Delimiter">;</span> + argc--<span class="Delimiter">;</span> <span class="Delimiter">}</span> + transform_all<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">"main"</span><span class="Delimiter">)</span>]<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Comment">//: Step 3: if we aren't running tests, locate a recipe called 'main' and</span> +<span class="Comment">//: start running it.</span> <span class="Delimiter">:(before "End Main")</span> if <span class="Delimiter">(</span>!Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span> setup<span class="Delimiter">();</span> -<span class="CommentedCode">//? Trace_file = "interactive"; //? 2</span> -<span class="CommentedCode">//? START_TRACING_UNTIL_END_OF_SCOPE; //? 2</span> -<span class="CommentedCode">//? Trace_stream->collect_layer.insert("app"); //? 1</span> - transform_all<span class="Delimiter">();</span> +<span class="CommentedCode">//? Trace_file = "interactive";</span> +<span class="CommentedCode">//? START_TRACING_UNTIL_END_OF_SCOPE;</span> +<span class="CommentedCode">//? Trace_stream->collect_layers.insert("app");</span> + run_main<span class="Delimiter">(</span>argc<span class="Delimiter">,</span> argv<span class="Delimiter">);</span> + teardown<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void run_main<span class="Delimiter">(</span>int argc<span class="Delimiter">,</span> char* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe_ordinal r = Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">"main"</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span> -<span class="CommentedCode">//? atexit(dump_profile); //? 1</span> if <span class="Delimiter">(</span>r<span class="Delimiter">)</span> run<span class="Delimiter">(</span>r<span class="Delimiter">);</span> -<span class="CommentedCode">//? dump_memory(); //? 1</span> - teardown<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> @@ -217,6 +238,8 @@ void dump_profile<span class="Delimiter">()</span> <span class="Delimiter">{</sp cerr << p<span class="Delimiter">-></span>first << <span class="Constant">": "</span> << p<span class="Delimiter">-></span>second << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(before "End One-time Setup")</span> +<span class="CommentedCode">//? atexit(dump_profile);</span> <span class="Delimiter">:(code)</span> void cleanup_main<span class="Delimiter">()</span> <span class="Delimiter">{</span> @@ -231,6 +254,10 @@ atexit<span class="Delimiter">(</span>cleanup_main<span class="Delimiter">);</sp <span class="Delimiter">:(code)</span> void load_permanently<span class="Delimiter">(</span>string filename<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_directory<span class="Delimiter">(</span>filename<span class="Delimiter">))</span> <span class="Delimiter">{</span> + load_all_permanently<span class="Delimiter">(</span>filename<span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> ifstream fin<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">());</span> fin<span class="Delimiter">.</span>peek<span class="Delimiter">();</span> if <span class="Delimiter">(</span>!fin<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -239,31 +266,37 @@ void load_permanently<span class="Delimiter">(</span>string filename<span class= <span class="Delimiter">}</span> fin >> std::noskipws<span class="Delimiter">;</span> load<span class="Delimiter">(</span>fin<span class="Delimiter">);</span> - transform_all<span class="Delimiter">();</span> fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span> <span class="Comment">// freeze everything so it doesn't get cleared by tests</span> recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Comment">// End load_permanently.</span> <span class="Delimiter">}</span> -<span class="SalientComment">//:: On startup, load everything in core.mu</span> -<span class="Delimiter">:(before "End Load Recipes")</span> -load_permanently<span class="Delimiter">(</span><span class="Constant">"core.mu"</span><span class="Delimiter">);</span> +bool is_directory<span class="Delimiter">(</span>string path<span class="Delimiter">)</span> <span class="Delimiter">{</span> + struct stat info<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>stat<span class="Delimiter">(</span>path<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &info<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error</span> + <span class="Identifier">return</span> info<span class="Delimiter">.</span>st_mode & S_IFDIR<span class="Delimiter">;</span> +<span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> -<span class="Comment">// helper for tests</span> -void run<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << form << '\n'; //? 1</span> - vector<recipe_ordinal> tmp = load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - transform_all<span class="Delimiter">();</span> - run<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>front<span class="Delimiter">());</span> +void load_all_permanently<span class="Delimiter">(</span>string dir<span class="Delimiter">)</span> <span class="Delimiter">{</span> + dirent** files<span class="Delimiter">;</span> + int num_files = scandir<span class="Delimiter">(</span>dir<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &files<span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">,</span> alphasort<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < num_files<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string curr_file = files[i]<span class="Delimiter">-></span>d_name<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!isdigit<span class="Delimiter">(</span>curr_file<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> + load_permanently<span class="Delimiter">(</span>dir+<span class="Constant">'/'</span>+curr_file<span class="Delimiter">);</span> + free<span class="Delimiter">(</span>files[i]<span class="Delimiter">);</span> + files[i] = <span class="Constant">NULL</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + free<span class="Delimiter">(</span>files<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include</span><span class="Constant"><dirent.h></span> <span class="SalientComment">//:: Reading from memory, writing to memory.</span> +<span class="Delimiter">:(code)</span> vector<double> read_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "read_memory: " << x.to_string() << '\n'; //? 2</span> vector<double> result<span class="Delimiter">;</span> if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> @@ -284,7 +317,7 @@ void write_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> long long int base = x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> if <span class="Delimiter">(</span>size_mismatch<span class="Delimiter">(</span>x<span class="Delimiter">,</span> data<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << current_recipe_name<span class="Delimiter">()</span> << <span class="Constant">": size mismatch in storing to "</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">" at '"</span> << current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << current_recipe_name<span class="Delimiter">()</span> << <span class="Constant">": size mismatch in storing to "</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">" ("</span> << size_of<span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">)</span> << <span class="Constant">" vs "</span> << SIZE<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << <span class="Constant">") at '"</span> << current_instruction<span class="Delimiter">().</span>to_string<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> for <span class="Delimiter">(</span>long long int offset = <span class="Constant">0</span><span class="Delimiter">;</span> offset < SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> ++offset<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -308,7 +341,7 @@ long long int size_of<span class="Delimiter">(</span>const vector<type_ordina bool size_mismatch<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">,</span> const vector<double>& data<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// End size_mismatch(x) Cases</span> -<span class="CommentedCode">//? if (size_of(x) != SIZE(data)) cerr << size_of(x) << " vs " << SIZE(data) << '\n'; //? 2</span> +<span class="CommentedCode">//? if (size_of(x) != SIZE(data)) cerr << size_of(x) << " vs " << SIZE(data) << '\n';</span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -324,6 +357,15 @@ bool is_mu_array<span class="Delimiter">(</span>reagent r<span class="Delimiter" <span class="Identifier">return</span> !r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_ordinal[<span class="Constant">"array"</span>]<span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> +<span class="Comment">// helper for tests</span> +void run<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<recipe_ordinal> tmp = load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> + transform_all<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + run<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>front<span class="Delimiter">());</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario run_label)</span> recipe main [ +foo diff --git a/html/021arithmetic.cc.html b/html/021arithmetic.cc.html index af5099f4..7575dd28 100644 --- a/html/021arithmetic.cc.html +++ b/html/021arithmetic.cc.html @@ -14,12 +14,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.Identifier { color: #804000; } .traceContains { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } --> </style> @@ -41,7 +40,6 @@ Recipe_ordinal[<span class="Constant">"add"</span>] = ADD<span class=" <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case ADD: <span class="Delimiter">{</span> double result = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? if (!tb_is_active()) cerr << ingredients.at(1).at(0) << '\n'; //? 1</span> for <span class="Delimiter">(</span>long long int 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> if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise << current_recipe_name<span class="Delimiter">()</span> << <span class="Constant">": 'add' requires number ingredients, but got "</span> << current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> diff --git a/html/023jump.cc.html b/html/023jump.cc.html index 63248241..9e239685 100644 --- a/html/023jump.cc.html +++ b/html/023jump.cc.html @@ -14,12 +14,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .traceAbsent { color: #c00000; } -.Identifier { color: #804000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } .traceContains { color: #008000; } --> @@ -36,7 +35,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment">//: Jump primitives</span> <span class="Delimiter">:(scenario jump_can_skip_instructions)</span> -<span class="CommentedCode">#? % Trace_stream->dump_layer = "all"; #? 1</span> recipe main [ jump <span class="Constant">1</span>:offset <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> diff --git a/html/029tools.cc.html b/html/029tools.cc.html index 9db3f206..77e709c2 100644 --- a/html/029tools.cc.html +++ b/html/029tools.cc.html @@ -16,7 +16,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .cSpecial { color: #008000; } .SalientComment { color: #00ffff; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .traceContains { color: #008000; } @@ -93,21 +92,21 @@ recipe main [ <span class="Delimiter">:(scenario stash_literal_number)</span> recipe main [ - stash [foo: ]<span class="Delimiter">,</span> <span class="Constant">4</span> + stash [foo:]<span class="Delimiter">,</span> <span class="Constant">4</span> ] <span class="traceContains">+app: foo: 4</span> <span class="Delimiter">:(scenario stash_number)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> - stash [foo: ]<span class="Delimiter">,</span> <span class="Constant">1</span>:number + stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:number ] <span class="traceContains">+app: foo: 34</span> <span class="Delimiter">:(code)</span> string print_mu<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">,</span> const vector<double>& data<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> - <span class="Identifier">return</span> r<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>name+<span class="Constant">' '</span><span class="Delimiter">;</span> <span class="Comment">// End print Special-cases(reagent r, data)</span> ostringstream out<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -146,7 +145,6 @@ case _START_TRACING: <span class="Delimiter">{</span> Trace_stream<span class="Delimiter">-></span>dump_layer = <span class="Constant">"all"</span><span class="Delimiter">;</span> else Trace_stream<span class="Delimiter">-></span>dump_layer = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << Trace_stream << ": " << Trace_stream->dump_layer << '\n'; //? 1</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/030container.cc.html b/html/030container.cc.html index 827e6f74..7d0d4a26 100644 --- a/html/030container.cc.html +++ b/html/030container.cc.html @@ -15,7 +15,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .SalientComment { color: #00ffff; } .traceAbsent { color: #c00000; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -68,7 +67,7 @@ recipe main [ recipe main [ <span class="Constant">2</span>:point<span class="Special"> <- </span>copy <span class="Constant">1</span>:number ] -<span class="traceContains">+warn: main: size mismatch in storing to 2:point at '2:point <- copy 1:number'</span> +<span class="traceContains">+warn: main: size mismatch in storing to 2:point (2 vs 1) at '2:point <- copy 1:number'</span> <span class="Delimiter">:(before "End Mu Types Initialization")</span> <span class="Comment">// A more complex container, containing another container as one of its</span> @@ -141,7 +140,7 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> <span class="Comment"># first</span> <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">35</span> <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">36</span> - stash [foo: ]<span class="Delimiter">,</span> <span class="Constant">1</span>:point-number/<span class="Special">raw</span> + stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:point-number/<span class="Special">raw</span> ] <span class="traceContains">+app: foo: 34 35 36</span> @@ -338,9 +337,6 @@ void insert_container<span class="Delimiter">(</span>const string& command<s skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"reading "</span> << command << <span class="Constant">' '</span> << name << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? cout << name << '\n'; //? 2</span> -<span class="CommentedCode">//? if (Type_ordinal.find(name) != Type_ordinal.end()) //? 1</span> -<span class="CommentedCode">//? cerr << Type_ordinal[name] << '\n'; //? 1</span> if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>name<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">()</span> || Type_ordinal[name] == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> Type_ordinal[name] = Next_type_ordinal++<span class="Delimiter">;</span> @@ -364,7 +360,6 @@ void insert_container<span class="Delimiter">(</span>const string& command<s if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">()</span> <span class="Comment">// types can contain integers, like for array sizes</span> && !is_integer<span class="Delimiter">(</span>type_name<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << type_name << " is " << Next_type_ordinal << '\n'; //? 1</span> Type_ordinal[type_name] = Next_type_ordinal++<span class="Delimiter">;</span> <span class="Delimiter">}</span> types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_ordinal[type_name]<span class="Delimiter">);</span> @@ -402,7 +397,6 @@ vector<type_ordinal> recently_added_types<span class="Delimiter">;</span> recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">:(before "End Setup")</span> <span class="Comment">//: for tests</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "erasing " << Type[recently_added_types.at(i)].name << '\n'; //? 1</span> Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Type[recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> @@ -418,7 +412,6 @@ while<span class="Delimiter">(</span>p != Type_ordinal<span class="Delimiter">.< ++p<span class="Delimiter">;</span> <span class="Comment">// now delete current item if necessary</span> if <span class="Delimiter">(</span>t >= <span class="Constant">1000</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "AAA " << name << " " << t << '\n'; //? 1</span> Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>name<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -435,7 +428,6 @@ Next_type_ordinal = <span class="Constant">1000</span><span class="Delimiter">;< <span class="Delimiter">:(scenario run_warns_on_unknown_types)</span> <span class="Special">% Hide_warnings = true;</span> -<span class="CommentedCode">#? % Trace_stream->dump_layer = "run";</span> recipe main [ <span class="Comment"># integer is not a type</span> <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -498,14 +490,13 @@ container foo [ <span class="traceContains">+parse: element name: y</span> <span class="traceContains">+parse: type: 1</span> -<span class="Delimiter">:(before "End Load Sanity Checks")</span> +<span class="Delimiter">:(before "End Transform")</span> check_container_field_types<span class="Delimiter">();</span> <span class="Delimiter">:(code)</span> void check_container_field_types<span class="Delimiter">()</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>map<type_ordinal<span class="Delimiter">,</span> type_info>::iterator p = Type<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Type<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> const type_info& info = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "checking " << p->first << '\n'; //? 1</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> diff --git a/html/031address.cc.html b/html/031address.cc.html index 38ea84f7..caad95d7 100644 --- a/html/031address.cc.html +++ b/html/031address.cc.html @@ -15,7 +15,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .SalientComment { color: #00ffff; } .traceAbsent { color: #c00000; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -81,16 +80,13 @@ recipe main [ <span class="Delimiter">:(code)</span> reagent canonize<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << "canonize\n"; //? 1</span> reagent r = x<span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << x.to_string() << " => " << r.to_string() << '\n'; //? 1</span> while <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">))</span> r = lookup_memory<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Identifier">return</span> r<span class="Delimiter">;</span> <span class="Delimiter">}</span> reagent lookup_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "lookup_memory: " << x.to_string() << "\n"; //? 2</span> static const type_ordinal ADDRESS = Type_ordinal[<span class="Constant">"address"</span>]<span class="Delimiter">;</span> reagent result<span class="Delimiter">;</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != ADDRESS<span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/032array.cc.html b/html/032array.cc.html index 08097e7b..c73052a4 100644 --- a/html/032array.cc.html +++ b/html/032array.cc.html @@ -126,7 +126,7 @@ recipe main [ <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> - stash [foo: ]<span class="Delimiter">,</span> <span class="Constant">1</span>:array:number:<span class="Constant">3</span> + stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:array:number:<span class="Constant">3</span> ] <span class="traceContains">+app: foo: 3 14 15 16</span> diff --git a/html/033exclusive_container.cc.html b/html/033exclusive_container.cc.html index b2a35106..beea9b0e 100644 --- a/html/033exclusive_container.cc.html +++ b/html/033exclusive_container.cc.html @@ -182,6 +182,42 @@ recipe main [ <span class="traceContains">+mem: storing 34 in location 3</span> <span class="traceContains">+mem: storing 1 in location 4</span> <span class="traceContains">+mem: storing 34 in location 5</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> +if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation == MERGE + && !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>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + reagent x = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + if <span class="Delimiter">(</span>Type[x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>kind == exclusive_container<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <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> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario merge_exclusive_container_with_mismatched_sizes)</span> +container foo [ + x:number + y:number +] + +exclusive-container bar [ + x:number + y:foo +] + +recipe main [ + <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>:bar<span class="Special"> <- </span>merge <span class="Constant">0</span>/x<span class="Delimiter">,</span> <span class="Constant">1</span>:number + <span class="Constant">6</span>:bar<span class="Special"> <- </span>merge <span class="Constant">1</span>/foo<span class="Delimiter">,</span> <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number +] +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="traceContains">+mem: storing 34 in location 4</span> +<span class="Comment"># bar is always 3 large so location 5 is skipped</span> +<span class="traceContains">+mem: storing 1 in location 6</span> +<span class="traceContains">+mem: storing 34 in location 7</span> +<span class="traceContains">+mem: storing 35 in location 8</span> </pre> </body> </html> diff --git a/html/034call.cc.html b/html/034call.cc.html index dd892686..8c95766f 100644 --- a/html/034call.cc.html +++ b/html/034call.cc.html @@ -15,7 +15,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .PreProc { color: #c000c0; } .SalientComment { color: #00ffff; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -161,7 +160,6 @@ inline const vector<instruction>& routine::steps<span class="Delimiter while <span class="Delimiter">(</span>current_step_index<span class="Delimiter">()</span> >= SIZE<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>steps<span class="Delimiter">()))</span> <span class="Delimiter">{</span> <span class="Comment">// Falling Through End Of Recipe</span> --Callstack_depth<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "reply " << SIZE(Current_routine->calls) << '\n'; //? 2</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>pop_front<span class="Delimiter">();</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// Complete Call Fallthrough</span> diff --git a/html/037recipe.cc.html b/html/037recipe.cc.html index 838b0789..856e671c 100644 --- a/html/037recipe.cc.html +++ b/html/037recipe.cc.html @@ -13,12 +13,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.Identifier { color: #804000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } .traceContains { color: #008000; } --> @@ -56,7 +55,6 @@ recipe f [ reply <span class="Constant">3</span>:number ] <span class="traceContains">+mem: storing 34 in location 2</span> -<span class="CommentedCode">#? ?</span> <span class="Delimiter">:(before "End Mu Types Initialization")</span> <span class="Comment">// 'recipe' is a literal</span> diff --git a/html/038scheduler.cc.html b/html/038scheduler.cc.html index 02c08935..3a258741 100644 --- a/html/038scheduler.cc.html +++ b/html/038scheduler.cc.html @@ -15,7 +15,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .SalientComment { color: #00ffff; } .traceAbsent { color: #c00000; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -83,7 +82,12 @@ Scheduling_interval = <span class="Constant">500</span><span class="Delimiter">; Routines<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">:(replace{} "void run(recipe_ordinal r)")</span> void run<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new routine<span class="Delimiter">(</span>r<span class="Delimiter">));</span> + run<span class="Delimiter">(</span>new routine<span class="Delimiter">(</span>r<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void run<span class="Delimiter">(</span>routine* rr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>rr<span class="Delimiter">);</span> Current_routine_index = <span class="Constant">0</span><span class="Delimiter">,</span> Current_routine = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> while <span class="Delimiter">(</span>!all_routines_done<span class="Delimiter">())</span> <span class="Delimiter">{</span> skip_to_next_routine<span class="Delimiter">();</span> @@ -101,7 +105,6 @@ void run<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter"> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> bool all_routines_done<span class="Delimiter">()</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == RUNNING<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -139,6 +142,24 @@ for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</ delete Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> Routines<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Comment">//: special case for the very first routine</span> +<span class="Delimiter">:(replace{} "void run_main(int argc, char* argv[])")</span> +void run_main<span class="Delimiter">(</span>int argc<span class="Delimiter">,</span> char* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe_ordinal r = Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">"main"</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// pass in commandline args as ingredients to main</span> + <span class="Comment">// todo: test this</span> + routine* rr = new routine<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + Current_routine = rr<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i < argc<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<double> arg<span class="Delimiter">;</span> + arg<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_mu_string<span class="Delimiter">(</span>argv[i]<span class="Delimiter">));</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + run<span class="Delimiter">(</span>rr<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + <span class="SalientComment">//:: To schedule new routines to run, call 'start-running'.</span> <span class="Comment">//: 'start-running' will return a unique id for the routine that was created.</span> @@ -253,7 +274,6 @@ recipe f2 [ <span class="Special">% Routines.push_back(new routine(f1)); // f1 meant to run</span> <span class="Special">% Routines.push_back(new routine(f2));</span> <span class="Special">% Routines.back()->state = COMPLETED; // f2 not meant to run</span> -<span class="CommentedCode">#? % Trace_stream->dump_layer = "all";</span> <span class="Comment"># must have at least one routine without escaping</span> recipe f3 [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> @@ -418,12 +438,15 @@ case _DUMP_ROUTINES: <span class="Delimiter">{</span> <span class="Special">% Scheduling_interval = 2;</span> recipe f1 [ <span class="Constant">1</span>:number/child-id<span class="Special"> <- </span>start-running f2:recipe - limit-time <span class="Constant">1</span>:number/child-id<span class="Delimiter">,</span> <span class="Constant">1</span> + limit-time <span class="Constant">1</span>:number/child-id<span class="Delimiter">,</span> <span class="Constant">10</span> + <span class="Comment"># padding loop just to make sure f2 has time to completed</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">20</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>subtract <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">1</span> + jump-if <span class="Constant">2</span>:number<span class="Delimiter">,</span> -<span class="Constant">2</span>:offset ] recipe f2 [ -<span class="Delimiter">{</span> - loop <span class="Comment"># run forever</span> -<span class="Delimiter">}</span> + jump -<span class="Constant">1</span>:offset <span class="Comment"># run forever</span> + $print [should never get here]<span class="Delimiter">,</span> <span class="Constant">10</span>/newline ] <span class="Comment"># f2 terminates</span> <span class="traceContains">+schedule: discontinuing routine 2</span> diff --git a/html/040brace.cc.html b/html/040brace.cc.html index 223e7923..eb62a889 100644 --- a/html/040brace.cc.html +++ b/html/040brace.cc.html @@ -13,7 +13,6 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -71,8 +70,6 @@ recipe main [ <span class="Delimiter">:(code)</span> void transform_braces<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "AAA transform_braces\n"; //? 1</span> -<span class="CommentedCode">//? exit(0); //? 1</span> const int OPEN = <span class="Constant">0</span><span class="Delimiter">,</span> CLOSE = <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// use signed integer for step index because we'll be doing arithmetic on it</span> list<pair<int<span class="Comment">/*</span><span class="Comment">OPEN/CLOSE</span><span class="Comment">*/</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">step</span><span class="Comment">*/</span>long long int> > braces<span class="Delimiter">;</span> @@ -109,6 +106,13 @@ void transform_braces<span class="Delimiter">(</span>const recipe_ordinal r<span trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" ..."</span> << end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + <span class="Comment">// check for errors</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">"-if"</span><span class="Delimiter">)</span> != string::npos || inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">"-unless"</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << inst<span class="Delimiter">.</span>name << <span class="Constant">" expects 1 or 2 ingredients, but got none</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> <span class="Comment">// update instruction operation</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">"-if"</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> inst<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">"jump-if"</span>]<span class="Delimiter">;</span> @@ -375,7 +379,6 @@ recipe main [ <span class="Comment">//: test how things actually run</span> <span class="Delimiter">:(scenarios run)</span> <span class="Delimiter">:(scenario brace_conversion_and_run)</span> -<span class="CommentedCode">#? % Trace_stream->dump_layer = "run";</span> recipe test-factorial [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">5</span> <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> @@ -397,6 +400,15 @@ recipe main [ <span class="Identifier">break</span> ] <span class="traceContains">+warn: break needs a '{' before</span> + +<span class="Delimiter">:(scenario break_conditional_without_ingredient_warns)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + <span class="Delimiter">{</span> + <span class="Identifier">break</span>-if + <span class="Delimiter">}</span> +] +<span class="traceContains">+warn: break-if expects 1 or 2 ingredients, but got none</span> </pre> </body> </html> diff --git a/html/041jump_label.cc.html b/html/041jump_target.cc.html index 6b0f0bd4..8c0ce0cf 100644 --- a/html/041jump_label.cc.html +++ b/html/041jump_target.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 041jump_label.cc</title> +<title>Mu - 041jump_target.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v1"> <meta name="syntax" content="cpp"> @@ -15,7 +15,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .traceAbsent { color: #c00000; } .traceContains { color: #008000; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -33,7 +32,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } </head> <body> <pre id='vimCodeElement'> -<span class="Comment">//: Support jumps to labels.</span> +<span class="Comment">//: Support jumps to special labels called 'targets'. Targets must be in the</span> +<span class="Comment">//: same recipe as the jump, and must be unique in that recipe. Targets always</span> +<span class="Comment">//: start with a '+'.</span> +<span class="Comment">//:</span> <span class="Comment">//: We'll also treat 'break' and 'loop' as jumps. The choice of name is</span> <span class="Comment">//: just documentation about intent; use 'break' to indicate you're exiting</span> <span class="Comment">//: one or more loop nests, and 'loop' to indicate you're skipping to the next</span> @@ -58,7 +60,16 @@ void transform_labels<span class="Delimiter">(</span>const recipe_ordinal r<span map<string<span class="Delimiter">,</span> long long int> offset<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> const instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>label<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> offset[inst<span class="Delimiter">.</span>label] = i<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>label<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && inst<span class="Delimiter">.</span>label<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">'+'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>offset<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> == offset<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + offset[inst<span class="Delimiter">.</span>label] = i<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + raise << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">": duplicate label '"</span> << inst<span class="Delimiter">.</span>label << <span class="Constant">"'"</span> << end<span class="Delimiter">();</span> + <span class="Comment">// have all jumps skip some random but noticeable and deterministic amount of code</span> + offset[inst<span class="Delimiter">.</span>label] = <span class="Constant">9999</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> @@ -84,18 +95,30 @@ void transform_labels<span class="Delimiter">(</span>const recipe_ordinal r<span void replace_offset<span class="Delimiter">(</span>reagent& x<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">const</span><span class="Comment">*/</span> map<string<span class="Delimiter">,</span> long long int>& offset<span class="Delimiter">,</span> const long long int current_offset<span class="Delimiter">,</span> const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">": jump target must be offset or label but is "</span> << x<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// no jump by default</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> assert<span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">);</span> if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// non-labels will be handled like other number operands</span> - if <span class="Delimiter">(</span>offset<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == offset<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + if <span class="Delimiter">(</span>!is_jump_target<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">": can't jump to label "</span> << x<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// no jump by default</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>offset<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == offset<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> raise << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">": can't find label "</span> << x<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// no jump by default</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>offset[x<span class="Delimiter">.</span>name]-current_offset<span class="Delimiter">);</span> <span class="Delimiter">}</span> +bool is_jump_target<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> label<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">'+'</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario break_to_label)</span> recipe main [ -<span class="CommentedCode">#? $print [aaa]</span> <span class="Delimiter">{</span> <span class="Delimiter">{</span> <span class="Identifier">break</span> +target:label @@ -143,6 +166,30 @@ recipe main [ ] <span class="traceContains">+mem: storing 0 in location 5</span> <span class="traceAbsent">-mem: storing 0 in location 4</span> + +<span class="Delimiter">:(scenario recipe_warns_on_duplicate_jump_target)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + +label + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + +label + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +<span class="traceContains">+warn: main: duplicate label '+label'</span> + +<span class="Delimiter">:(scenario jump_ignores_nontarget_label)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + <span class="Comment"># first a few lines of padding to exercise the offset computation</span> + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + jump $target:label + <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + $target + <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +<span class="traceContains">+warn: main: can't jump to label $target</span> </pre> </body> </html> diff --git a/html/042name.cc.html b/html/042name.cc.html index c0f0a2cf..16cf8117 100644 --- a/html/042name.cc.html +++ b/html/042name.cc.html @@ -16,7 +16,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .cSpecial { color: #008000; } .SalientComment { color: #00ffff; } .traceAbsent { color: #c00000; } -.CommentedCode { color: #6c6c6c; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -101,7 +100,6 @@ void transform_names<span class="Delimiter">(</span>const recipe_ordinal r<span <span class="Delimiter">}</span> bool disqualified<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">mutable</span><span class="Comment">*/</span> reagent& x<span class="Delimiter">,</span> const instruction& inst<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << x.to_string() << '\n'; //? 1</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> raise << <span class="Constant">"missing type in '"</span> << inst<span class="Delimiter">.</span>to_string<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="Constant">true</span><span class="Delimiter">;</span> @@ -132,7 +130,6 @@ type_ordinal skip_addresses<span class="Delimiter">(</span>const vector<type_ int find_element_name<span class="Delimiter">(</span>const type_ordinal t<span class="Delimiter">,</span> const string& name<span class="Delimiter">)</span> <span class="Delimiter">{</span> const type_info& container = Type[t]<span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << "looking for element " << name << " in type " << container.name << " with " << SIZE(container.element_names) << " elements\n"; //? 1</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>container<span class="Delimiter">.</span>element_names<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>container<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == name<span class="Delimiter">)</span> <span class="Identifier">return</span> i<span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/043new.cc.html b/html/043new.cc.html index 4f4321e1..82eaa244 100644 --- a/html/043new.cc.html +++ b/html/043new.cc.html @@ -115,8 +115,8 @@ case NEW: <span class="Delimiter">{</span> size = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? Total_alloc += size; //? 1</span> -<span class="CommentedCode">//? Num_alloc++; //? 1</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> @@ -139,21 +139,25 @@ case NEW: <span class="Delimiter">{</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? :(before "End Globals") //? 1</span> -<span class="CommentedCode">//? long long int Total_alloc = 0; //? 1</span> -<span class="CommentedCode">//? long long int Num_alloc = 0; //? 1</span> -<span class="CommentedCode">//? long long int Total_free = 0; //? 1</span> -<span class="CommentedCode">//? long long int Num_free = 0; //? 1</span> -<span class="CommentedCode">//? :(before "End Setup") //? 1</span> -<span class="CommentedCode">//? Total_alloc = Num_alloc = Total_free = Num_free = 0; //? 1</span> -<span class="CommentedCode">//? :(before "End Teardown") //? 1</span> -<span class="CommentedCode">//? cerr << Total_alloc << "/" << Num_alloc //? 1</span> -<span class="CommentedCode">//? << " vs " << Total_free << "/" << Num_free << '\n'; //? 1</span> -<span class="CommentedCode">//? cerr << SIZE(Memory) << '\n'; //? 1</span> +<span class="CommentedCode">//? :(before "End Globals")</span> +<span class="CommentedCode">//? long long int Total_alloc = 0;</span> +<span class="CommentedCode">//? long long int Num_alloc = 0;</span> +<span class="CommentedCode">//? long long int Total_free = 0;</span> +<span class="CommentedCode">//? long long 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> void ensure_space<span class="Delimiter">(</span>long long int size<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>size <= Initial_memory_per_routine<span class="Delimiter">);</span> + if <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.</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> if <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> @@ -267,9 +271,9 @@ case ABANDON: <span class="Delimiter">{</span> <span class="Delimiter">:(code)</span> void abandon<span class="Delimiter">(</span>long long int address<span class="Delimiter">,</span> long long int size<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? Total_free += size; //? 1</span> -<span class="CommentedCode">//? Num_free++; //? 1</span> -<span class="CommentedCode">//? cerr << "abandon: " << size << '\n'; //? 2</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> for <span class="Delimiter">(</span>long long int curr = address<span class="Delimiter">;</span> curr < address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> Memory[curr] = <span class="Constant">0</span><span class="Delimiter">;</span> @@ -359,9 +363,8 @@ if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>cur long long int new_mu_string<span class="Delimiter">(</span>const string& contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// allocate an array just large enough for it</span> long long int string_length = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> -<span class="CommentedCode">//? cout << "string_length is " << string_length << '\n'; //? 1</span> -<span class="CommentedCode">//? Total_alloc += string_length+1; //? 1</span> -<span class="CommentedCode">//? Num_alloc++; //? 1</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> long long int result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> @@ -385,7 +388,7 @@ long long int new_mu_string<span class="Delimiter">(</span>const string& con <span class="Delimiter">:(scenario stash_string)</span> recipe main [ x:address:array:character<span class="Special"> <- </span>new [abc] - stash [foo: ]<span class="Delimiter">,</span> x:address:array:character + stash [foo:]<span class="Delimiter">,</span> x:address:array:character ] <span class="traceContains">+app: foo: abc</span> diff --git a/html/044space.cc.html b/html/044space.cc.html index 99f80cd9..7c46d504 100644 --- a/html/044space.cc.html +++ b/html/044space.cc.html @@ -16,7 +16,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .traceAbsent { color: #c00000; } .SalientComment { color: #00ffff; } .traceContains { color: #008000; } -.CommentedCode { color: #6c6c6c; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -85,11 +84,10 @@ default_space = <span class="Constant">0</span><span class="Delimiter">;</span> reagent r = absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Delimiter">:(code)</span> reagent absolutize<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "absolutize " << x.to_string() << '\n'; //? 4</span> if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">"default-space"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> << <span class="Constant">": reagent not initialized: "</span> << x<span class="Delimiter">.</span>original_string << end<span class="Delimiter">();</span> + raise << current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> << <span class="Constant">": reagent not initialized: "</span> << x<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> <span class="Delimiter">}</span> reagent r = x<span class="Delimiter">;</span> @@ -239,7 +237,6 @@ long long int space_base<span class="Delimiter">(</span>const reagent& x<spa long long int address<span class="Delimiter">(</span>long long int offset<span class="Delimiter">,</span> long long int base<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>base == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> offset<span class="Delimiter">;</span> <span class="Comment">// raw</span> -<span class="CommentedCode">//? cout << base << '\n'; //? 2</span> if <span class="Delimiter">(</span>offset >= static_cast<long long int><span class="Delimiter">(</span>Memory[base]<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// todo: test</span> raise << <span class="Constant">"location "</span> << offset << <span class="Constant">" is out of bounds "</span> << Memory[base] << <span class="Constant">" at "</span> << base << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> diff --git a/html/046closure_name.cc.html b/html/046closure_name.cc.html index 5b612e50..4587a5aa 100644 --- a/html/046closure_name.cc.html +++ b/html/046closure_name.cc.html @@ -14,7 +14,6 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.CommentedCode { color: #6c6c6c; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -110,8 +109,6 @@ void collect_surrounding_spaces<span class="Delimiter">(</span>const recipe_ordi <span class="Delimiter">:(replace{} "long long int lookup_name(const reagent& r, const recipe_ordinal default_recipe)")</span> long long int lookup_name<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">,</span> const recipe_ordinal default_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "AAA " << default_recipe << " " << Recipe[default_recipe].name << '\n'; //? 2</span> -<span class="CommentedCode">//? cout << "AAA " << x.to_string() << '\n'; //? 1</span> if <span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"space"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Name[default_recipe]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise << <span class="Constant">"name not found: "</span> << x<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> Name[default_recipe][x<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html index db392a7c..e6184407 100644 --- a/html/050scenario.cc.html +++ b/html/050scenario.cc.html @@ -15,14 +15,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } .SalientComment { color: #00ffff; } -.Identifier { color: #804000; } +.traceContains { color: #008000; } +.CommentedCode { color: #6c6c6c; } .traceAbsent { color: #c00000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } -.traceContains { color: #008000; } --> </style> @@ -96,6 +96,7 @@ struct scenario <span class="Delimiter">{</span> <span class="Delimiter">:(before "End Globals")</span> vector<scenario> Scenarios<span class="Delimiter">;</span> +set<string> Scenario_names<span class="Delimiter">;</span> <span class="SalientComment">//:: Parse the 'scenario' form.</span> <span class="Comment">//: Simply store the text of the scenario.</span> @@ -107,10 +108,11 @@ else if <span class="Delimiter">(</span>command == <span class="Constant">" <span class="Delimiter">:(code)</span> scenario parse_scenario<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "parse scenario\n"; //? 1</span> scenario result<span class="Delimiter">;</span> result<span class="Delimiter">.</span>name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "scenario: " << result.name << '\n'; //? 2</span> + if <span class="Delimiter">(</span>Scenario_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != Scenario_names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + raise << <span class="Constant">"duplicate scenario name: "</span> << result<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + Scenario_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">);</span> <span class="Comment">// scenarios are take special 'code' strings so we need to ignore brackets</span> @@ -119,7 +121,6 @@ scenario parse_scenario<span class="Delimiter">(</span>istream& in<span clas <span class="Comment">// delete [] delimiters</span> assert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>to_run<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> result<span class="Delimiter">.</span>to_run<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> -<span class="CommentedCode">//? cerr << (int)result.to_run.at(SIZE(result.to_run)-1) << '\n'; //? 1</span> assert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>to_run<span class="Delimiter">.</span>at<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>result<span class="Delimiter">.</span>to_run<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">)</span> == <span class="Constant">']'</span><span class="Delimiter">);</span> result<span class="Delimiter">.</span>to_run<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>result<span class="Delimiter">.</span>to_run<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> @@ -145,8 +146,7 @@ scenario foo [ time_t mu_time<span class="Delimiter">;</span> time<span class="Delimiter">(</span>&mu_time<span class="Delimiter">);</span> cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">Mu tests: "</span> << ctime<span class="Delimiter">(</span>&mu_time<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Scenarios<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << Passed << '\n'; //? 1</span> -<span class="CommentedCode">//? cerr << i << ": " << Scenarios.at(i).name << '\n'; //? 7</span> +<span class="CommentedCode">//? cerr << i << ": " << Scenarios.at(i).name << '\n';</span> run_mu_scenario<span class="Delimiter">(</span>Scenarios<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> if <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -167,7 +167,7 @@ const scenario* Current_scenario = <span class="Constant">NULL</span><span class void run_mu_scenario<span class="Delimiter">(</span>const scenario& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> Current_scenario = &s<span class="Delimiter">;</span> bool not_already_inside_test = !Trace_stream<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << s.name << '\n'; //? 12</span> +<span class="CommentedCode">//? cerr << s.name << '\n';</span> if <span class="Delimiter">(</span>not_already_inside_test<span class="Delimiter">)</span> <span class="Delimiter">{</span> Trace_file = s<span class="Delimiter">.</span>name<span class="Delimiter">;</span> Trace_stream = new trace_stream<span class="Delimiter">;</span> @@ -206,7 +206,7 @@ recipe scenario-foo [ <span class="traceContains">+warn: redefining recipe scenario-foo</span> <span class="Delimiter">:(after "bool warn_on_redefine(const string& recipe_name)")</span> -if <span class="Delimiter">(</span>recipe_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">"scenario-"</span><span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>recipe_name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">"scenario-"</span><span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="SalientComment">//:: The special instructions we want to support inside scenarios.</span> <span class="Comment">//: In a compiler for the mu VM these will require more work.</span> @@ -214,7 +214,6 @@ if <span class="Delimiter">(</span>recipe_name<span class="Delimiter">.</span>fi <span class="Comment">//: 'run' interprets a string as a set of instructions</span> <span class="Delimiter">:(scenario run)</span> -<span class="CommentedCode">#? % Trace_stream->dump_layer = "all";</span> recipe main [ run [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">13</span> @@ -228,14 +227,11 @@ RUN<span class="Delimiter">,</span> Recipe_ordinal[<span class="Constant">"run"</span>] = RUN<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case RUN: <span class="Delimiter">{</span> -<span class="CommentedCode">//? cout << "recipe " << current_instruction().ingredients.at(0).name << '\n'; //? 1</span> ostringstream tmp<span class="Delimiter">;</span> tmp << <span class="Constant">"recipe run"</span> << Next_recipe_ordinal << <span class="Constant">" [ "</span> << current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name << <span class="Constant">" ]"</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? Show_rest_of_stream = true; //? 1</span> vector<recipe_ordinal> tmp_recipe = load<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<span class="Delimiter">());</span> bind_special_scenario_names<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> transform_all<span class="Delimiter">();</span> -<span class="CommentedCode">//? cout << tmp_recipe.at(0) << ' ' << Recipe_ordinal["main"] << '\n'; //? 1</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// not done with caller; don't increment current_step_index()</span> <span class="Delimiter">}</span> @@ -286,7 +282,6 @@ Recipe_ordinal[<span class="Constant">"memory-should-contain"</span>] <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case MEMORY_SHOULD_CONTAIN: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cout << current_instruction().ingredients.at(0).name << '\n'; //? 1</span> check_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -456,10 +451,8 @@ case TRACE_SHOULD_CONTAIN: <span class="Delimiter">{</span> <span class="Comment">// simplified version of check_trace_contents() that emits warnings rather</span> <span class="Comment">// than just printing to stderr</span> bool check_trace<span class="Delimiter">(</span>const string& expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "AAA " << expected << '\n'; //? 1</span> Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> vector<trace_line> expected_lines = parse_trace<span class="Delimiter">(</span>expected<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "BBB " << SIZE(expected_lines) << '\n'; //? 1</span> if <span class="Delimiter">(</span>expected_lines<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> long long int curr_expected_line = <span class="Constant">0</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>vector<trace_line>::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -468,7 +461,6 @@ bool check_trace<span class="Delimiter">(</span>const string& expected<span <span class="Comment">// match</span> ++curr_expected_line<span class="Delimiter">;</span> if <span class="Delimiter">(</span>curr_expected_line == SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "ZZZ\n"; //? 1</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -658,12 +650,11 @@ recipe main [ <span class="Delimiter">:(code)</span> <span class="Comment">// just for the scenarios running scenarios in C++ layers</span> void run_mu_scenario<span class="Delimiter">(</span>const string& form<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << form << '\n'; //? 1</span> + Scenario_names<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> istringstream in<span class="Delimiter">(</span>form<span class="Delimiter">);</span> in >> std::noskipws<span class="Delimiter">;</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string _scenario = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cout << _scenario << '\n'; //? 2</span> assert<span class="Delimiter">(</span>_scenario == <span class="Constant">"scenario"</span><span class="Delimiter">);</span> scenario s = parse_scenario<span class="Delimiter">(</span>in<span class="Delimiter">);</span> run_mu_scenario<span class="Delimiter">(</span>s<span class="Delimiter">);</span> diff --git a/html/051scenario_test.mu.html b/html/051scenario_test.mu.html index d38539dd..f7807a4d 100644 --- a/html/051scenario_test.mu.html +++ b/html/051scenario_test.mu.html @@ -13,10 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -30,69 +29,69 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># tests for 'scenario' in previous layer</span> -<span class="muScenario">scenario</span> first_scenario_in_mu [ +scenario first_scenario_in_mu [ run [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>add <span class="Constant">2</span>, <span class="Constant">2</span> + 1:number<span class="Special"> <- </span>add 2, 2 ] memory-should-contain [ - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">4</span> + 1<span class="Special"> <- </span>4 ] ] -<span class="muScenario">scenario</span> scenario_with_comment_in_mu [ +scenario scenario_with_comment_in_mu [ run [ <span class="Comment"># comment</span> - <span class="Constant">1</span>:number<span class="Special"> <- </span>add <span class="Constant">2</span>, <span class="Constant">2</span> + 1:number<span class="Special"> <- </span>add 2, 2 ] memory-should-contain [ - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">4</span> + 1<span class="Special"> <- </span>4 ] ] -<span class="muScenario">scenario</span> scenario_with_multiple_comments_in_mu [ +scenario scenario_with_multiple_comments_in_mu [ run [ <span class="Comment"># comment1</span> <span class="Comment"># comment2</span> - <span class="Constant">1</span>:number<span class="Special"> <- </span>add <span class="Constant">2</span>, <span class="Constant">2</span> + 1:number<span class="Special"> <- </span>add 2, 2 ] memory-should-contain [ - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">4</span> + 1<span class="Special"> <- </span>4 ] ] -<span class="muScenario">scenario</span> check_string_in_memory [ +scenario check_string_in_memory [ run [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> - <span class="Constant">2</span>:character<span class="Special"> <- </span>copy <span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">3</span>:character<span class="Special"> <- </span>copy <span class="Constant">98</span> <span class="Comment"># 'b'</span> - <span class="Constant">4</span>:character<span class="Special"> <- </span>copy <span class="Constant">99</span> <span class="Comment"># 'c'</span> + 1:number<span class="Special"> <- </span><span class="Identifier">copy</span> 3 + 2:character<span class="Special"> <- </span><span class="Identifier">copy</span> 97 <span class="Comment"># 'a'</span> + 3:character<span class="Special"> <- </span><span class="Identifier">copy</span> 98 <span class="Comment"># 'b'</span> + 4:character<span class="Special"> <- </span><span class="Identifier">copy</span> 99 <span class="Comment"># 'c'</span> ] memory-should-contain [ - <span class="Constant">1</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 1:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> check_trace [ +scenario check_trace [ run [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>add <span class="Constant">2</span>, <span class="Constant">2</span> + 1:number<span class="Special"> <- </span>add 2, 2 ] trace-should-contain [ - mem: storing <span class="Constant">4</span> in location <span class="Constant">1</span> + mem: storing 4 <span class="Identifier">in</span> location 1 ] ] -<span class="muScenario">scenario</span> check_trace_negative [ +scenario check_trace_negative [ run [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>add <span class="Constant">2</span>, <span class="Constant">2</span> + 1:number<span class="Special"> <- </span>add 2, 2 ] trace-should-not-contain [ - mem: storing <span class="Constant">5</span> in location <span class="Constant">1</span> + mem: storing 5 <span class="Identifier">in</span> location 1 ] ] -<span class="muScenario">scenario</span> check_trace_instruction [ +scenario check_trace_instruction [ run [ - trace <span class="Constant">1</span>, <span class="Constant">[foo]</span>, <span class="Constant">[aaa]</span> + trace 1, [foo], [aaa] ] trace-should-contain [ foo: aaa diff --git a/html/052tangle.cc.html b/html/052tangle.cc.html index 93323d00..95fc502f 100644 --- a/html/052tangle.cc.html +++ b/html/052tangle.cc.html @@ -13,12 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.Identifier { color: #804000; } +.traceAbsent { color: #c00000; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } .traceContains { color: #008000; } --> @@ -32,18 +32,22 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } </head> <body> <pre id='vimCodeElement'> -<span class="Comment">//: Allow code for recipes to be pulled in from multiple places.</span> +<span class="Comment">//: Allow code for recipes to be pulled in from multiple places and inserted</span> +<span class="Comment">//: at special labels called 'waypoints'. Unlike jump targets, a recipe can</span> +<span class="Comment">//: have multiple ambiguous waypoints with the same name. Any 'before' and</span> +<span class="Comment">//: 'after' fragments will simply be inserted at all applicable waypoints.</span> +<span class="Comment">//: Waypoints are always surrounded by '<>', e.g. <handle-request>.</span> <span class="Comment">//:</span> <span class="Comment">//: TODO: switch recipe.steps to a more efficient data structure.</span> <span class="Delimiter">:(scenario tangle_before)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - +label1 + <label1> <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> @@ -65,15 +69,19 @@ Fragments_used<span class="Delimiter">.</span>clear<span class="Delimiter">();</ <span class="Delimiter">:(before "End Command Handlers")</span> else if <span class="Delimiter">(</span>command == <span class="Constant">"before"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - recipe tmp = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "adding before fragment " << label << '\n'; //? 1</span> - Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + recipe tmp = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> + Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + else + raise << <span class="Constant">"can't tangle before label "</span> << label << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else if <span class="Delimiter">(</span>command == <span class="Constant">"after"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - recipe tmp = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "adding after fragment " << label << '\n'; //? 1</span> - After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + recipe tmp = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> + After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + else + raise << <span class="Constant">"can't tangle after label "</span> << label << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Comment">//: after all recipes are loaded, insert fragments at appropriate labels.</span> @@ -92,33 +100,70 @@ tangle_done = <span class="Constant">false</span><span class="Delimiter">;</span <span class="Delimiter">:(code)</span> void insert_fragments<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> bool made_progress = <span class="Constant">true</span><span class="Delimiter">;</span> + long long int pass = <span class="Constant">0</span><span class="Delimiter">;</span> while <span class="Delimiter">(</span>made_progress<span class="Delimiter">)</span> <span class="Delimiter">{</span> made_progress = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// create a new vector because insertions invalidate iterators</span> vector<instruction> result<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>is_label || inst<span class="Delimiter">.</span>tangle_done<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>is_label || !is_waypoint<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> || inst<span class="Delimiter">.</span>tangle_done<span class="Delimiter">)</span> <span class="Delimiter">{</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> inst<span class="Delimiter">.</span>tangle_done = <span class="Constant">true</span><span class="Delimiter">;</span> made_progress = <span class="Constant">true</span><span class="Delimiter">;</span> Fragments_used<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">);</span> + ostringstream prefix<span class="Delimiter">;</span> + prefix << <span class="Constant">'+'</span> << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">'_'</span> << pass << <span class="Constant">'_'</span> << i<span class="Delimiter">;</span> if <span class="Delimiter">(</span>Before_fragments<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != Before_fragments<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "loading code before " << inst.label << '\n'; //? 1</span> - result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + append_fragment<span class="Delimiter">(</span>result<span class="Delimiter">,</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">,</span> prefix<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> if <span class="Delimiter">(</span>After_fragments<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != After_fragments<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "loading code after " << inst.label << '\n'; //? 1</span> - result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + append_fragment<span class="Delimiter">(</span>result<span class="Delimiter">,</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">,</span> prefix<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + ++pass<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +void append_fragment<span class="Delimiter">(</span>vector<instruction>& base<span class="Delimiter">,</span> const vector<instruction>& patch<span class="Delimiter">,</span> const string prefix<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// append 'patch' to 'base' while keeping 'base' oblivious to any new jump</span> + <span class="Comment">// targets in 'patch' oblivious to 'base' by prepending 'prefix' to them.</span> + <span class="Comment">// we might tangle the same fragment at multiple points in a single recipe,</span> + <span class="Comment">// and we need to avoid duplicate jump targets.</span> + <span class="Comment">// so we'll keep jump targets local to the specific before/after fragment</span> + <span class="Comment">// that introduces them.</span> + set<string> jump_targets<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>patch<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& inst = patch<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label && is_jump_target<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> + jump_targets<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>patch<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction inst = patch<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>jump_targets<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != jump_targets<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + inst<span class="Delimiter">.</span>label = prefix+inst<span class="Delimiter">.</span>label<span class="Delimiter">;</span> + base<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int 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> + reagent& x = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">"label"</span> && jump_targets<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != jump_targets<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + x<span class="Delimiter">.</span>name = prefix+x<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + base<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +bool is_waypoint<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> *label<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> == <span class="Constant">'<'</span> && *label<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> == <span class="Constant">'>'</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Comment">//: warn about unapplied fragments</span> <span class="Delimiter">:(before "End Globals")</span> bool Transform_check_insert_fragments_Ran = <span class="Constant">false</span><span class="Delimiter">;</span> @@ -141,13 +186,13 @@ void check_insert_fragments<span class="Delimiter">(</span>unused recipe_ordinal <span class="Delimiter">:(scenario tangle_before_and_after)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - +label1 + <label1> <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -after +label1 [ +after <label1> [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> @@ -158,23 +203,41 @@ after +label1 [ <span class="Comment"># nothing else</span> $mem: <span class="Constant">4</span> -<span class="Delimiter">:(scenario tangle_keeps_labels_separate)</span> +<span class="Delimiter">:(scenario tangle_ignores_jump_target)</span> +<span class="Special">% Hide_warnings = true;</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +label1 - +label2 - <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] before +label1 [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -after +label1 [ +<span class="traceContains">+warn: can't tangle before label +label1</span> +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 4</span> +<span class="Comment"># label1</span> +<span class="traceAbsent">-mem: storing 0 in location 2</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">2</span> + +<span class="Delimiter">:(scenario tangle_keeps_labels_separate)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <label1> + <label2> + <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +before <label1> [ + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +after <label1> [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -before +label2 [ +before <label2> [ <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -after +label2 [ +after <label2> [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> @@ -192,19 +255,19 @@ $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_stacks_multiple_fragments)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - +label1 + <label1> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -after +label1 [ +after <label1> [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -before +label1 [ +before <label1> [ <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -after +label1 [ +after <label1> [ <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> @@ -222,14 +285,14 @@ $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_supports_fragments_with_multiple_instructions)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - +label1 + <label1> <span class="Constant">6</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] -after +label1 [ +after <label1> [ <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> ] @@ -246,19 +309,19 @@ $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> - +label1 + <label1> <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> recipe2 ] recipe recipe2 [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">11</span> - +label1 + <label1> <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">11</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> ] -after +label1 [ +after <label1> [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> @@ -278,14 +341,14 @@ $mem: <span class="Constant">8</span> <span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name_2)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> - +label1 - +label1 + <label1> + <label1> <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> ] -after +label1 [ +after <label1> [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> @@ -302,29 +365,93 @@ $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name_3)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> - +label1 - +foo + <label1> + <foo> <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> ] -before +label1 [ +before <label1> [ <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> ] -after +label1 [ +after <label1> [ <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> ] -after +foo [ - +label1 +after <foo> [ + <label1> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 12 in location 2</span> -<span class="Comment"># +foo/label1</span> +<span class="Comment"># foo/label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">6</span> + +<span class="Delimiter">:(scenario tangle_handles_jump_target_inside_fragment)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> + <label1> + <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> +] +before <label1> [ + jump +label2:label + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> + +label2 + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> +] +<span class="traceContains">+mem: storing 10 in location 1</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 12 in location 3</span> +<span class="traceContains">+mem: storing 10 in location 4</span> +<span class="Comment"># ignored by jump</span> +<span class="traceAbsent">-mem: storing 12 in label 2</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">3</span> + +<span class="Delimiter">:(scenario tangle_renames_jump_target)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> + <label1> + +label2 + <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> +] +before <label1> [ + jump +label2:label + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> + +label2 <span class="Comment"># renamed</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> +] +<span class="traceContains">+mem: storing 10 in location 1</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 12 in location 3</span> +<span class="traceContains">+mem: storing 10 in location 4</span> +<span class="Comment"># ignored by jump</span> +<span class="traceAbsent">-mem: storing 12 in label 2</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">3</span> + +<span class="Delimiter">:(scenario tangle_jump_to_base_recipe)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> + <label1> + +label2 + <span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">10</span> +] +before <label1> [ + jump +label2:label + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">12</span> +] +<span class="traceContains">+mem: storing 10 in location 1</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 10 in location 4</span> +<span class="Comment"># ignored by jump</span> +<span class="traceAbsent">-mem: storing 12 in label 2</span> +<span class="traceAbsent">-mem: storing 12 in location 3</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">2</span> </pre> </body> </html> diff --git a/html/053continuation.cc.html b/html/053continuation.cc.html index c0c00353..7e3623fb 100644 --- a/html/053continuation.cc.html +++ b/html/053continuation.cc.html @@ -17,7 +17,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .SalientComment { color: #00ffff; } .traceAbsent { color: #c00000; } .traceContains { color: #008000; } -.CommentedCode { color: #6c6c6c; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -91,7 +90,6 @@ recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:continuation<span class="Special"> <- </span>current-continuation <span class="Delimiter">{</span> -<span class="CommentedCode">#? $print 1:number</span> <span class="Constant">3</span>:boolean<span class="Special"> <- </span>greater-or-equal <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">3</span> <span class="Identifier">break</span>-if <span class="Constant">3</span>:boolean <span class="Constant">1</span>:number<span class="Special"> <- </span>add <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">1</span> @@ -106,7 +104,6 @@ recipe main [ $current-continuation: <span class="Constant">1</span> <span class="Delimiter">:(scenario continuation_inside_caller)</span> -<span class="CommentedCode">#? % Trace_stream->dump_layer = "all"; #? 1</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:continuation<span class="Special"> <- </span>loop-body @@ -167,7 +164,6 @@ recipe g [ <span class="Constant">23</span>:number<span class="Special"> <- </span>add <span class="Constant">22</span>:number<span class="Delimiter">,</span> <span class="Constant">1</span> reply <span class="Constant">23</span>:number ] -<span class="CommentedCode">#? ?</span> <span class="Comment"># first call of 'g' executes the part before reply-delimited-continuation</span> <span class="traceContains">+mem: storing 12 in location 21</span> <span class="traceContains">+run: 2:number <- copy 5</span> diff --git a/html/060string.mu.html b/html/060string.mu.html index 7a2126ff..ff86a100 100644 --- a/html/060string.mu.html +++ b/html/060string.mu.html @@ -13,14 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.muScenario { color: #00af00; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -34,70 +30,70 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># Some useful helpers for dealing with strings.</span> -<span class="muRecipe">recipe</span> string-equal [ - <span class="Constant">local-scope</span> - a:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - a-len:number<span class="Special"> <- </span>length *a - b:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - b-len:number<span class="Special"> <- </span>length *b +recipe string-equal [ + <span class="Underlined">local</span>-scope + a:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + a-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *a + b:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + b-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *b <span class="Comment"># compare lengths</span> - <span class="Delimiter">{</span> - trace <span class="Constant">99</span>, <span class="Constant">[string-equal]</span>, <span class="Constant">[comparing lengths]</span> - length-equal?:boolean<span class="Special"> <- </span>equal a-len, b-len - <span class="muControl">break-if</span> length-equal? - <span class="muControl">reply</span> <span class="Constant">0</span> - <span class="Delimiter">}</span> + { + trace 99, [string-equal], [comparing lengths] + <span class="Identifier">length</span>-equal?:boolean<span class="Special"> <- </span>equal a-len, b-len + break-if <span class="Identifier">length</span>-equal? + reply 0 + } <span class="Comment"># compare each corresponding character</span> - trace <span class="Constant">99</span>, <span class="Constant">[string-equal]</span>, <span class="Constant">[comparing characters]</span> - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + trace 99, [string-equal], [comparing characters] + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { done?:boolean<span class="Special"> <- </span>greater-or-equal i, a-len - <span class="muControl">break-if</span> done? + break-if done? a2:character<span class="Special"> <- </span>index *a, i b2:character<span class="Special"> <- </span>index *b, i - <span class="Delimiter">{</span> - chars-match?:boolean<span class="Special"> <- </span>equal a2, b2 - <span class="muControl">break-if</span> chars-match? - <span class="muControl">reply</span> <span class="Constant">0</span> - <span class="Delimiter">}</span> - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> <span class="Constant">1</span> -] - -<span class="muScenario">scenario</span> string-equal-reflexive [ + { + chars-<span class="Identifier">match</span>?:boolean<span class="Special"> <- </span>equal a2, b2 + break-if chars-<span class="Identifier">match</span>? + reply 0 + } + i<span class="Special"> <- </span>add i, 1 + loop + } + reply 1 +] + +scenario string-equal-reflexive [ run [ - <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>string-equal x, x + default-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30 + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 3:boolean/<span class="Special">raw <- </span>string-equal x, x ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># x == x for all x</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># x == x for all x</span> ] ] -<span class="muScenario">scenario</span> string-equal-identical [ +scenario string-equal-identical [ run [ - <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>string-equal x, y + default-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30 + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + y:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 3:boolean/<span class="Special">raw <- </span>string-equal x, y ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># abc == abc</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># abc == abc</span> ] ] -<span class="muScenario">scenario</span> string-equal-distinct-lengths [ +scenario string-equal-distinct-lengths [ run [ - <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>string-equal x, y + default-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30 + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + y:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abcd] + 3:boolean/<span class="Special">raw <- </span>string-equal x, y ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># abc != abcd</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># abc != abcd</span> ] trace-should-contain [ string-equal: comparing lengths @@ -107,1259 +103,1250 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="muScenario">scenario</span> string-equal-with-empty [ +scenario string-equal-with-empty [ run [ - <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>string-equal x, y + default-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30 + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + y:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abcd] + 3:boolean/<span class="Special">raw <- </span>string-equal x, y ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># "" != abcd</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># "" != abcd</span> ] ] -<span class="muScenario">scenario</span> string-equal-common-lengths-but-distinct [ +scenario string-equal-common-lengths-but-distinct [ run [ - <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>string-equal x, y + default-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30 + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + y:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abd] + 3:boolean/<span class="Special">raw <- </span>string-equal x, y ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># abc != abd</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># abc != abd</span> ] ] <span class="Comment"># A new type to help incrementally construct strings.</span> container buffer [ - length:number - data:address:array:character -] - -<span class="muRecipe">recipe</span> new-buffer [ - <span class="Constant">local-scope</span> -<span class="CommentedCode">#? $print default-space:address:array:location, 10/newline</span> - result:address:buffer<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:array:character<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - capacity:number, found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - assert found?, <span class="Constant">[new-buffer must get a capacity argument]</span> - *s<span class="Special"> <- </span>new <span class="Constant">character:type</span>, capacity -<span class="CommentedCode">#? $print *s, 10/newline</span> - <span class="muControl">reply</span> result -] - -<span class="muRecipe">recipe</span> grow-buffer [ - <span class="Constant">local-scope</span> - in:address:buffer<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Identifier">length</span>:number + data:address:<span class="Identifier">array</span>:character +] + +recipe <span class="Identifier">new</span>-buffer [ + <span class="Underlined">local</span>-scope + result:address:buffer<span class="Special"> <- </span><span class="Identifier">new</span> buffer:<span class="Identifier">type</span> + len:address:number<span class="Special"> <- </span>get-address *result, <span class="Identifier">length</span>:offset + *len:address:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + s:address:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get-address *result, data:offset + capacity:number, found?:boolean<span class="Special"> <- </span>next-ingredient + <span class="Identifier">assert</span> found?, [<span class="Identifier">new</span>-buffer must get a capacity argument] + *s<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, capacity + reply result +] + +recipe grow-buffer [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:buffer<span class="Special"> <- </span>next-ingredient <span class="Comment"># double buffer size</span> - x:address:address:array:character<span class="Special"> <- </span>get-address *in, <span class="Constant">data:offset</span> - oldlen:number<span class="Special"> <- </span>length **x - newlen:number<span class="Special"> <- </span>multiply oldlen, <span class="Constant">2</span> - olddata:address:array:character<span class="Special"> <- </span>copy *x - *x<span class="Special"> <- </span>new <span class="Constant">character:type</span>, newlen + x:address:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, data:offset + oldlen:number<span class="Special"> <- </span><span class="Identifier">length</span> **x + newlen:number<span class="Special"> <- </span>multiply oldlen, 2 + olddata:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *x + *x<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, newlen <span class="Comment"># copy old contents</span> - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { done?:boolean<span class="Special"> <- </span>greater-or-equal i, oldlen - <span class="muControl">break-if</span> done? + break-if 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 - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> in -] - -<span class="muRecipe">recipe</span> buffer-full? [ - <span class="Constant">local-scope</span> - in:address:buffer<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - len:number<span class="Special"> <- </span>get *in, <span class="Constant">length: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 + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> src + i<span class="Special"> <- </span>add i, 1 + loop + } + reply <span class="Identifier">in</span> +] + +recipe buffer-full? [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:buffer<span class="Special"> <- </span>next-ingredient + len:number<span class="Special"> <- </span>get *<span class="Identifier">in</span>, <span class="Identifier">length</span>:offset + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *<span class="Identifier">in</span>, data:offset + capacity:number<span class="Special"> <- </span><span class="Identifier">length</span> *s result:boolean<span class="Special"> <- </span>greater-or-equal len, capacity - <span class="muControl">reply</span> result + reply result ] <span class="Comment"># in <- buffer-append in:address:buffer, c:character</span> -<span class="muRecipe">recipe</span> buffer-append [ - <span class="Constant">local-scope</span> - in:address:buffer<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - c:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - len:address:number<span class="Special"> <- </span>get-address *in, <span class="Constant">length:offset</span> - <span class="Delimiter">{</span> +recipe buffer-<span class="Identifier">append</span> [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:buffer<span class="Special"> <- </span>next-ingredient + c:character<span class="Special"> <- </span>next-ingredient + len:address:number<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, <span class="Identifier">length</span>:offset + { <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> - <span class="muControl">reply-if</span> empty?, in/same-as-ingredient:<span class="Constant">0</span> - *len<span class="Special"> <- </span>subtract *len, <span class="Constant">1</span> - <span class="muControl">reply</span> in/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> + backspace?:boolean<span class="Special"> <- </span>equal c, 8/backspace + break-unless backspace? + empty?:boolean<span class="Special"> <- </span>lesser-or-equal *len, 0 + reply-if empty?, <span class="Identifier">in</span>/same-as-ingredient:0 + *len<span class="Special"> <- </span>subtract *len, 1 + reply <span class="Identifier">in</span>/same-as-ingredient:0 + } + { <span class="Comment"># grow buffer if necessary</span> - full?:boolean<span class="Special"> <- </span>buffer-full? in - <span class="muControl">break-unless</span> full? - in<span class="Special"> <- </span>grow-buffer in - <span class="Delimiter">}</span> - s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> -<span class="CommentedCode">#? $print [array underlying buf: ], s, 10/newline</span> -<span class="CommentedCode">#? $print [index: ], *len, 10/newline</span> + full?:boolean<span class="Special"> <- </span>buffer-full? <span class="Identifier">in</span> + break-unless full? + <span class="Identifier">in</span><span class="Special"> <- </span>grow-buffer <span class="Identifier">in</span> + } + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *<span class="Identifier">in</span>, data:offset dest:address:character<span class="Special"> <- </span>index-address *s, *len -<span class="CommentedCode">#? $print [storing ], c, [ in ], dest, 10/newline</span> - *dest<span class="Special"> <- </span>copy c - *len<span class="Special"> <- </span>add *len, <span class="Constant">1</span> - <span class="muControl">reply</span> in/same-as-ingredient:<span class="Constant">0</span> + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> c + *len<span class="Special"> <- </span>add *len, 1 + reply <span class="Identifier">in</span>/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> buffer-append-works [ +scenario buffer-<span class="Identifier">append</span>-works [ run [ - <span class="Constant">local-scope</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:address:buffer, <span class="Constant">data:offset</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">98</span> <span class="Comment"># 'b'</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">99</span> <span class="Comment"># 'c'</span> - s2:address:array:character<span class="Special"> <- </span>get *x:address:buffer, <span class="Constant">data:offset</span> - <span class="Constant">1</span>:boolean/<span class="Special">raw <- </span>equal s1:address:array:character, s2:address:array:character - <span class="Constant">2</span>:array:character/<span class="Special">raw <- </span>copy *s2:address:array:character -<span class="Constant"> +buffer-filled</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">100</span> <span class="Comment"># 'd'</span> - s3:address:array:character<span class="Special"> <- </span>get *x:address:buffer, <span class="Constant">data:offset</span> - <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal s1:address:array:character, s3:address:array:character - <span class="Constant">11</span>:number/<span class="Special">raw <- </span>get *x:address:buffer, <span class="Constant">length:offset</span> - <span class="Constant">12</span>:array:character/<span class="Special">raw <- </span>copy *s3:address:array:character + <span class="Underlined">local</span>-scope + x:address:buffer<span class="Special"> <- </span><span class="Identifier">new</span>-buffer 3 + s1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *x:address:buffer, data:offset + x:address:buffer<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 97 <span class="Comment"># 'a'</span> + x:address:buffer<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 98 <span class="Comment"># 'b'</span> + x:address:buffer<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 99 <span class="Comment"># 'c'</span> + s2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *x:address:buffer, data:offset + 1:boolean/<span class="Special">raw <- </span>equal s1:address:<span class="Identifier">array</span>:character, s2:address:<span class="Identifier">array</span>:character + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *s2:address:<span class="Identifier">array</span>:character + +buffer-filled + x:address:buffer<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 100 <span class="Comment"># 'd'</span> + s3:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *x:address:buffer, data:offset + 10:boolean/<span class="Special">raw <- </span>equal s1:address:<span class="Identifier">array</span>:character, s3:address:<span class="Identifier">array</span>:character + 11:number/<span class="Special">raw <- </span>get *x:address:buffer, <span class="Identifier">length</span>:offset + 12:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *s3:address:<span class="Identifier">array</span>:character ] memory-should-contain [ <span class="Comment"># before +buffer-filled</span> - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># no change in data pointer</span> - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># size of data</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># data</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">98</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">99</span> + 1<span class="Special"> <- </span>1 <span class="Comment"># no change in data pointer</span> + 2<span class="Special"> <- </span>3 <span class="Comment"># size of data</span> + 3<span class="Special"> <- </span>97 <span class="Comment"># data</span> + 4<span class="Special"> <- </span>98 + 5<span class="Special"> <- </span>99 <span class="Comment"># in the end</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># data pointer has grown</span> - <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># final length</span> - <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># but data's capacity has doubled</span> - <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># data</span> - <span class="Constant">14</span><span class="Special"> <- </span><span class="Constant">98</span> - <span class="Constant">15</span><span class="Special"> <- </span><span class="Constant">99</span> - <span class="Constant">16</span><span class="Special"> <- </span><span class="Constant">100</span> - <span class="Constant">17</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">18</span><span class="Special"> <- </span><span class="Constant">0</span> + 10<span class="Special"> <- </span>0 <span class="Comment"># data pointer has grown</span> + 11<span class="Special"> <- </span>4 <span class="Comment"># final length</span> + 12<span class="Special"> <- </span>6 <span class="Comment"># but data's capacity has doubled</span> + 13<span class="Special"> <- </span>97 <span class="Comment"># data</span> + 14<span class="Special"> <- </span>98 + 15<span class="Special"> <- </span>99 + 16<span class="Special"> <- </span>100 + 17<span class="Special"> <- </span>0 + 18<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> buffer-append-handles-backspace [ +scenario buffer-<span class="Identifier">append</span>-handles-backspace [ run [ - <span class="Constant">local-scope</span> - x:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">3</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">98</span> <span class="Comment"># 'b'</span> - x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, <span class="Constant">8/backspace</span> - s:address:array:character<span class="Special"> <- </span>buffer-to-array x:address:buffer - <span class="Constant">1</span>:array:character/<span class="Special">raw <- </span>copy *s:address:array:character + <span class="Underlined">local</span>-scope + x:address:buffer<span class="Special"> <- </span><span class="Identifier">new</span>-buffer 3 + x<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x, 97 <span class="Comment"># 'a'</span> + x<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x, 98 <span class="Comment"># 'b'</span> + x<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> x, 8/backspace + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>buffer-to-<span class="Identifier">array</span> x + 1:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *s ] memory-should-contain [ - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># length</span> - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># contents</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> + 1<span class="Special"> <- </span>1 <span class="Comment"># length</span> + 2<span class="Special"> <- </span>97 <span class="Comment"># contents</span> + 3<span class="Special"> <- </span>0 ] ] <span class="Comment"># result:address:array:character <- integer-to-decimal-string n:number</span> -<span class="muRecipe">recipe</span> integer-to-decimal-string [ - <span class="Constant">local-scope</span> - n:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe integer-to-decimal-string [ + <span class="Underlined">local</span>-scope + n:number<span class="Special"> <- </span>next-ingredient <span class="Comment"># is it zero?</span> - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> n - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">[0]</span> - <span class="muControl">reply</span> result - <span class="Delimiter">}</span> + { + break-if n + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [0] + reply result + } <span class="Comment"># save sign</span> - negate-result:boolean<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> - negative?:boolean<span class="Special"> <- </span>lesser-than n, <span class="Constant">0</span> - <span class="muControl">break-unless</span> negative? - negate-result<span class="Special"> <- </span>copy <span class="Constant">1</span> - n<span class="Special"> <- </span>multiply n, <span class="Constant">-1</span> - <span class="Delimiter">}</span> + negate-result:boolean<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + negative?:boolean<span class="Special"> <- </span>lesser-than n, 0 + break-unless negative? + negate-result<span class="Special"> <- </span><span class="Identifier">copy</span> 1 + n<span class="Special"> <- </span>multiply n, -1 + } <span class="Comment"># add digits from right to left into intermediate buffer</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> + tmp:address:buffer<span class="Special"> <- </span><span class="Identifier">new</span>-buffer 30 + digit-base:number<span class="Special"> <- </span><span class="Identifier">copy</span> 48 <span class="Comment"># '0'</span> + { + done?:boolean<span class="Special"> <- </span>equal n, 0 + break-if done? + n, digit:number<span class="Special"> <- </span><span class="Identifier">divide</span>-with-remainder n, 10 c:character<span class="Special"> <- </span>add digit-base, digit - tmp:address:buffer<span class="Special"> <- </span>buffer-append tmp, c - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + tmp:address:buffer<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> tmp, c + loop + } <span class="Comment"># add sign</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> negate-result:boolean - tmp<span class="Special"> <- </span>buffer-append tmp, <span class="Constant">45</span> <span class="Comment"># '-'</span> - <span class="Delimiter">}</span> + { + break-unless negate-result:boolean + tmp<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> tmp, 45 <span class="Comment"># '-'</span> + } <span class="Comment"># reverse buffer into string result</span> - len:number<span class="Special"> <- </span>get *tmp, <span class="Constant">length:offset</span> - buf:address:array:character<span class="Special"> <- </span>get *tmp, <span class="Constant">data:offset</span> - result:address:array:character<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> - <span class="Delimiter">{</span> + len:number<span class="Special"> <- </span>get *tmp, <span class="Identifier">length</span>:offset + buf:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *tmp, data:offset + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, len + i:number<span class="Special"> <- </span>subtract len, 1 <span class="Comment"># source index, decreasing</span> + j:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># destination index, increasing</span> + { <span class="Comment"># while i >= 0</span> - done?:boolean<span class="Special"> <- </span>lesser-than i, <span class="Constant">0</span> - <span class="muControl">break-if</span> done? + done?:boolean<span class="Special"> <- </span>lesser-than i, 0 + break-if 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 - 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="muControl">reply</span> result -] - -<span class="muRecipe">recipe</span> buffer-to-array [ - <span class="Constant">local-scope</span> - in:address:buffer<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> src + i<span class="Special"> <- </span>subtract i, 1 + j<span class="Special"> <- </span>add j, 1 + loop + } + reply result +] + +recipe buffer-to-<span class="Identifier">array</span> [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:buffer<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># propagate null buffer</span> - <span class="muControl">break-if</span> in - <span class="muControl">reply</span> <span class="Constant">0</span> - <span class="Delimiter">}</span> - len:number<span class="Special"> <- </span>get *in, <span class="Constant">length:offset</span> -<span class="CommentedCode">#? $print [size ], len, 10/newline</span> - s:address:array:character<span class="Special"> <- </span>get *in, <span class="Constant">data:offset</span> + break-if <span class="Identifier">in</span> + reply 0 + } + len:number<span class="Special"> <- </span>get *<span class="Identifier">in</span>, <span class="Identifier">length</span>:offset + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *<span class="Identifier">in</span>, data:offset <span class="Comment"># we can't just return s because it is usually the wrong length</span> - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, len - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> -<span class="CommentedCode">#? $print i #? 1</span> + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, len + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { done?:boolean<span class="Special"> <- </span>greater-or-equal i, len - <span class="muControl">break-if</span> done? + break-if 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 - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> src + i<span class="Special"> <- </span>add i, 1 + loop + } + reply result ] -<span class="muScenario">scenario</span> integer-to-decimal-digit-zero [ +scenario integer-to-decimal-digit-zero [ run [ - <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>integer-to-decimal-string <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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>integer-to-decimal-string 0 + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[0]</span> + 2:string<span class="Special"> <- </span>[0] ] ] -<span class="muScenario">scenario</span> integer-to-decimal-digit-positive [ +scenario integer-to-decimal-digit-positive [ run [ - <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>integer-to-decimal-string <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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>integer-to-decimal-string 234 + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[234]</span> + 2:string<span class="Special"> <- </span>[234] ] ] -<span class="muScenario">scenario</span> integer-to-decimal-digit-negative [ +scenario integer-to-decimal-digit-negative [ run [ - <span class="Constant">1</span>:address:array:character/<span class="Special">raw <- </span>integer-to-decimal-string <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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>integer-to-decimal-string -1 + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">2</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">45</span> <span class="Comment"># '-'</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">49</span> <span class="Comment"># '1'</span> + 2<span class="Special"> <- </span>2 + 3<span class="Special"> <- </span>45 <span class="Comment"># '-'</span> + 4<span class="Special"> <- </span>49 <span class="Comment"># '1'</span> ] ] <span class="Comment"># result:address:array:character <- string-append a:address:array:character, b:address:array:character</span> -<span class="muRecipe">recipe</span> string-append [ - <span class="Constant">local-scope</span> +recipe string-<span class="Identifier">append</span> [ + <span class="Underlined">local</span>-scope <span class="Comment"># result = new character[a.length + b.length]</span> - a:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - a-len:number<span class="Special"> <- </span>length *a - b:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - b-len:number<span class="Special"> <- </span>length *b + a:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + a-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *a + b:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + b-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *b result-len:number<span class="Special"> <- </span>add a-len, b-len - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, result-len + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, result-len <span class="Comment"># copy a into result</span> - result-idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + result-idx:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while i < a.length</span> a-done?:boolean<span class="Special"> <- </span>greater-or-equal i, a-len - <span class="muControl">break-if</span> a-done? + break-if 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 - 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> - <span class="Delimiter">}</span> + <span class="Identifier">in</span>:character<span class="Special"> <- </span>index *a, i + *out<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + i<span class="Special"> <- </span>add i, 1 + result-idx<span class="Special"> <- </span>add result-idx, 1 + loop + } <span class="Comment"># copy b into result</span> - i<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + i<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while i < b.length</span> b-done?:boolean<span class="Special"> <- </span>greater-or-equal i, b-len - <span class="muControl">break-if</span> b-done? + break-if 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 - 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + <span class="Identifier">in</span>:character<span class="Special"> <- </span>index *b, i + *out<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + i<span class="Special"> <- </span>add i, 1 + result-idx<span class="Special"> <- </span>add result-idx, 1 + loop + } + reply result ] -<span class="muScenario">scenario</span> string-append-1 [ +scenario string-<span class="Identifier">append</span>-1 [ run [ - <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>string-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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [hello,] + 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [ world!] + 3:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>string-<span class="Identifier">append</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> + 4:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">4</span>:string<span class="Special"> <- </span><span class="Constant">[hello, world!]</span> + 4:string<span class="Special"> <- </span>[hello, world!] ] ] -<span class="muScenario">scenario</span> replace-character-in-string [ +scenario replace-character-<span class="Identifier">in</span>-string [ run [ - <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>string-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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc] + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 98/b, 122/z + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[azc]</span> + 2:string<span class="Special"> <- </span>[azc] ] ] -<span class="muRecipe">recipe</span> string-replace [ - <span class="Constant">local-scope</span> - s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - oldc:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - newc:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - from:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - len:number<span class="Special"> <- </span>length *s +recipe string-replace [ + <span class="Underlined">local</span>-scope + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + oldc:character<span class="Special"> <- </span>next-ingredient + newc:character<span class="Special"> <- </span>next-ingredient + from:number<span class="Special"> <- </span>next-ingredient + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *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">reply-if</span> done?, s/same-as-ingredient:<span class="Constant">0</span> + reply-if done?, s/same-as-ingredient:0 dest:address:character<span class="Special"> <- </span>index-address *s, i - *dest<span class="Special"> <- </span>copy newc - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> newc + i<span class="Special"> <- </span>add i, 1 s<span class="Special"> <- </span>string-replace s, oldc, newc, i - <span class="muControl">reply</span> s/same-as-ingredient:<span class="Constant">0</span> + reply s/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> replace-character-at-start [ +scenario replace-character-at-start [ run [ - <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>string-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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc] + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 97/a, 122/z + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[zbc]</span> + 2:string<span class="Special"> <- </span>[zbc] ] ] -<span class="muScenario">scenario</span> replace-character-at-end [ +scenario replace-character-at-end [ run [ - <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>string-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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc] + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 99/c, 122/z + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[abz]</span> + 2:string<span class="Special"> <- </span>[abz] ] ] -<span class="muScenario">scenario</span> replace-character-missing [ +scenario replace-character-missing [ run [ - <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>string-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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc] + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 100/d, 122/z + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 2:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> replace-all-characters [ +scenario replace-all-characters [ run [ - <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>string-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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [banana] + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 97/a, 122/z + 2:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">2</span>:string<span class="Special"> <- </span><span class="Constant">[bznznz]</span> + 2:string<span class="Special"> <- </span>[bznznz] ] ] <span class="Comment"># replace underscores in first with remaining args</span> <span class="Comment"># result:address:array:character <- interpolate template:address:array:character, ...</span> -<span class="muRecipe">recipe</span> interpolate [ - <span class="Constant">local-scope</span> - template:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe <span class="Identifier">interpolate</span> [ + <span class="Underlined">local</span>-scope + template:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient <span class="Comment"># compute result-len, space to allocate for result</span> - tem-len:number<span class="Special"> <- </span>length *template - result-len:number<span class="Special"> <- </span>copy tem-len - <span class="Delimiter">{</span> + tem-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *template + result-len:number<span class="Special"> <- </span><span class="Identifier">copy</span> tem-len + { <span class="Comment"># while arg received</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? + a:address:<span class="Identifier">array</span>:character, <span class="Identifier">arg</span>-received?:boolean<span class="Special"> <- </span>next-ingredient + break-unless <span class="Identifier">arg</span>-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 + a-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *a result-len<span class="Special"> <- </span>add result-len, a-len - result-len<span class="Special"> <- </span>subtract result-len, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> -<span class="CommentedCode">#? $print tem-len, [ ], $result-len, 10/newline</span> + result-len<span class="Special"> <- </span>subtract result-len, 1 + loop + } rewind-ingredients - _<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="Comment"># skip template</span> - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, result-len + _<span class="Special"> <- </span>next-ingredient <span class="Comment"># skip template</span> + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, result-len <span class="Comment"># repeatedly copy sections of template and 'holes' into result</span> - result-idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + result-idx:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while arg received</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? + a:address:<span class="Identifier">array</span>:character, <span class="Identifier">arg</span>-received?:boolean<span class="Special"> <- </span>next-ingredient + break-unless <span class="Identifier">arg</span>-received? <span class="Comment"># copy template into result until '_'</span> - <span class="Delimiter">{</span> + { <span class="Comment"># while i < template.length</span> tem-done?:boolean<span class="Special"> <- </span>greater-or-equal i, tem-len - <span class="muControl">break-if</span> tem-done?, <span class="Constant">+done:label</span> + break-if tem-done?, +done:label <span class="Comment"># while template[i] != '_'</span> - in:character<span class="Special"> <- </span>index *template, i - underscore?:boolean<span class="Special"> <- </span>equal in, <span class="Constant">95/_</span> - <span class="muControl">break-if</span> underscore? + <span class="Identifier">in</span>:character<span class="Special"> <- </span>index *template, i + underscore?:boolean<span class="Special"> <- </span>equal <span class="Identifier">in</span>, 95/_ + break-if 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 - 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> - <span class="Delimiter">}</span> + *out<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + i<span class="Special"> <- </span>add i, 1 + result-idx<span class="Special"> <- </span>add result-idx, 1 + loop + } <span class="Comment"># copy 'a' into result</span> - j:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + j:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while j < a.length</span> - arg-done?:boolean<span class="Special"> <- </span>greater-or-equal j, a-len - <span class="muControl">break-if</span> arg-done? + <span class="Identifier">arg</span>-done?:boolean<span class="Special"> <- </span>greater-or-equal j, a-len + break-if <span class="Identifier">arg</span>-done? <span class="Comment"># result[result-idx] = a[j]</span> - in:character<span class="Special"> <- </span>index *a, j + <span class="Identifier">in</span>: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 - 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> - <span class="Delimiter">}</span> + *out<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + j<span class="Special"> <- </span>add j, 1 + result-idx<span class="Special"> <- </span>add result-idx, 1 + loop + } <span class="Comment"># skip '_' in template</span> - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> <span class="Comment"># interpolate next arg</span> - <span class="Delimiter">}</span> -<span class="Constant"> +done</span> + i<span class="Special"> <- </span>add i, 1 + loop <span class="Comment"># interpolate next arg</span> + } + +done <span class="Comment"># done with holes; copy rest of template directly into result</span> - <span class="Delimiter">{</span> + { <span class="Comment"># while i < template.length</span> tem-done?:boolean<span class="Special"> <- </span>greater-or-equal i, tem-len - <span class="muControl">break-if</span> tem-done? + break-if tem-done? <span class="Comment"># result[result-idx] = template[i]</span> - in:character<span class="Special"> <- </span>index *template, i + <span class="Identifier">in</span>: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 - 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + *out<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + i<span class="Special"> <- </span>add i, 1 + result-idx<span class="Special"> <- </span>add result-idx, 1 + loop + } + reply result ] -<span class="muScenario">scenario</span> interpolate-works [ -<span class="CommentedCode">#? dump run #? 1</span> +scenario <span class="Identifier">interpolate</span>-works [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc _] + 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [def] + 3:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">interpolate</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> + 4:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">4</span>:string<span class="Special"> <- </span><span class="Constant">[abc def]</span> + 4:string<span class="Special"> <- </span>[abc def] ] ] -<span class="muScenario">scenario</span> interpolate-at-start [ +scenario <span class="Identifier">interpolate</span>-at-start [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [_, hello!] + 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc] + 3:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">interpolate</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> + 4:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">4</span>:string<span class="Special"> <- </span><span class="Constant">[abc, hello!]</span> - <span class="Constant">16</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># out of bounds</span> + 4:string<span class="Special"> <- </span>[abc, hello!] + 16<span class="Special"> <- </span>0 <span class="Comment"># out of bounds</span> ] ] -<span class="muScenario">scenario</span> interpolate-at-end [ +scenario <span class="Identifier">interpolate</span>-at-end [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [hello, _] + 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">new</span> [abc] + 3:address:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">interpolate</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> + 4:<span class="Identifier">array</span>:character/<span class="Special">raw <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span> ] memory-should-contain [ - <span class="Constant">4</span>:string<span class="Special"> <- </span><span class="Constant">[hello, abc]</span> + 4:string<span class="Special"> <- </span>[hello, abc] ] ] <span class="Comment"># result:boolean <- space? c:character</span> -<span class="muRecipe">recipe</span> space? [ - <span class="Constant">local-scope</span> - c:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe space? [ + <span class="Underlined">local</span>-scope + c:character<span class="Special"> <- </span>next-ingredient <span class="Comment"># most common case first</span> - result:boolean<span class="Special"> <- </span>equal c, <span class="Constant">32/space</span> - <span class="muControl">jump-if</span> result <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">9/tab</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">13/carriage-return</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> + result:boolean<span class="Special"> <- </span>equal c, 32/space + jump-if result +reply:label + result<span class="Special"> <- </span>equal c, 10/newline + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 9/tab + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 13/carriage-<span class="Identifier">return</span> + jump-if result, +reply:label <span class="Comment"># remaining uncommon cases in sorted order</span> <span class="Comment"># <a href="http://unicode.org">http://unicode.org</a> code-points in unicode-set Z and Pattern_White_Space</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">11/ctrl-k</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">12/ctrl-l</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">133/ctrl-0085</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">160/no-break-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">5760/ogham-space-mark</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8192/en-quad</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8193/em-quad</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8194/en-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8195/em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8196/three-per-em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8197/four-per-em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8198/six-per-em-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8199/figure-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8200/punctuation-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8201/thin-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8202/hair-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8206/left-to-right</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8207/right-to-left</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8232/line-separator</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8233/paragraph-separator</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8239/narrow-no-break-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">8287/medium-mathematical-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> - result<span class="Special"> <- </span>equal c, <span class="Constant">12288/ideographic-space</span> - <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span> -<span class="Constant"> +reply</span> - <span class="muControl">reply</span> result + result<span class="Special"> <- </span>equal c, 11/ctrl-k + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 12/ctrl-l + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 133/ctrl-0085 + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 160/no-break-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 5760/ogham-space-mark + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8192/en-quad + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8193/em-quad + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8194/en-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8195/em-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8196/three-per-em-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8197/four-per-em-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8198/six-per-em-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8199/figure-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8200/punctuation-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8201/thin-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8202/hair-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8206/left-to-right + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8207/right-to-left + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8232/line-separator + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8233/paragraph-separator + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8239/narrow-no-break-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 8287/medium-mathematical-space + jump-if result, +reply:label + result<span class="Special"> <- </span>equal c, 12288/ideographic-space + jump-if result, +reply:label + +reply + reply result ] <span class="Comment"># result:address:array:character <- trim s:address:array:character</span> -<span class="muRecipe">recipe</span> trim [ - <span class="Constant">local-scope</span> - s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - len:number<span class="Special"> <- </span>length *s +recipe trim [ + <span class="Underlined">local</span>-scope + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *s <span class="Comment"># left trim: compute start</span> - start:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> - <span class="Delimiter">{</span> + start:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + { at-end?:boolean<span class="Special"> <- </span>greater-or-equal start, len - <span class="muControl">break-unless</span> at-end? - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, <span class="Constant">0</span> - <span class="muControl">reply</span> result - <span class="Delimiter">}</span> + break-unless at-end? + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, 0 + reply result + } curr:character<span class="Special"> <- </span>index *s, start whitespace?:boolean<span class="Special"> <- </span>space? curr - <span class="muControl">break-unless</span> whitespace? - start<span class="Special"> <- </span>add start, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + break-unless whitespace? + start<span class="Special"> <- </span>add start, 1 + loop + } <span class="Comment"># right trim: compute end</span> - end:number<span class="Special"> <- </span>subtract len, <span class="Constant">1</span> - <span class="Delimiter">{</span> + end:number<span class="Special"> <- </span>subtract len, 1 + { not-at-start?:boolean<span class="Special"> <- </span>greater-than end, start - assert not-at-start?, <span class="Constant">[end ran up against start]</span> + <span class="Identifier">assert</span> not-at-start?, [end ran up against start] curr:character<span class="Special"> <- </span>index *s, end whitespace?:boolean<span class="Special"> <- </span>space? curr - <span class="muControl">break-unless</span> whitespace? - end<span class="Special"> <- </span>subtract end, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + break-unless whitespace? + end<span class="Special"> <- </span>subtract end, 1 + loop + } <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:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, new-len + <span class="Identifier">new</span>-len:number<span class="Special"> <- </span>subtract end, start, -1 + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, <span class="Identifier">new</span>-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> - <span class="Delimiter">{</span> + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> start + j:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while i <= end</span> done?:boolean<span class="Special"> <- </span>greater-than i, end - <span class="muControl">break-if</span> done? + break-if 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 - 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> src + i<span class="Special"> <- </span>add i, 1 + j<span class="Special"> <- </span>add j, 1 + loop + } + reply result ] -<span class="muScenario">scenario</span> trim-unmodified [ +scenario trim-unmodified [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>trim 1:address:<span class="Identifier">array</span>:character + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 3:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> trim-left [ +scenario trim-left [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>trim 1:address:<span class="Identifier">array</span>:character + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 3:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> trim-right [ +scenario trim-right [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc ] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>trim 1:address:<span class="Identifier">array</span>:character + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 3:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> trim-left-right [ +scenario trim-left-right [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ abc ] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>trim 1:address:<span class="Identifier">array</span>:character + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 3:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> trim-newline-tab [ +scenario trim-newline-tab [ run [ - <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: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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ abc +] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>trim 1:address:<span class="Identifier">array</span>:character + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 3:string<span class="Special"> <- </span>[abc] ] ] <span class="Comment"># next-index:number <- find-next text:address:array:character, pattern:character, idx:number</span> -<span class="muRecipe">recipe</span> find-next [ - <span class="Constant">local-scope</span> - text:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - pattern:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - idx:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - len:number<span class="Special"> <- </span>length *text - <span class="Delimiter">{</span> +recipe find-next [ + <span class="Underlined">local</span>-scope + text:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + pattern:character<span class="Special"> <- </span>next-ingredient + idx:number<span class="Special"> <- </span>next-ingredient + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *text + { eof?:boolean<span class="Special"> <- </span>greater-or-equal idx, len - <span class="muControl">break-if</span> eof? + break-if eof? curr:character<span class="Special"> <- </span>index *text, idx found?:boolean<span class="Special"> <- </span>equal curr, pattern - <span class="muControl">break-if</span> found? - idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> idx + break-if found? + idx<span class="Special"> <- </span>add idx, 1 + loop + } + reply idx ] -<span class="muScenario">scenario</span> string-find-next [ +scenario string-find-next [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [a/b] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> + 2<span class="Special"> <- </span>1 ] ] -<span class="muScenario">scenario</span> string-find-next-empty [ +scenario string-find-next-empty [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> + 2<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> string-find-next-initial [ +scenario string-find-next-initial [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [/abc] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># prefix match</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># prefix match</span> ] ] -<span class="muScenario">scenario</span> string-find-next-final [ +scenario string-find-next-final [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc/] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># suffix match</span> + 2<span class="Special"> <- </span>3 <span class="Comment"># suffix match</span> ] ] -<span class="muScenario">scenario</span> string-find-next-missing [ +scenario string-find-next-missing [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># no match</span> + 2<span class="Special"> <- </span>3 <span class="Comment"># no match</span> ] ] -<span class="muScenario">scenario</span> string-find-next-invalid-index [ +scenario string-find-next-invalid-index [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 4/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># no change</span> + 2<span class="Special"> <- </span>4 <span class="Comment"># no change</span> ] ] -<span class="muScenario">scenario</span> string-find-next-first [ +scenario string-find-next-first [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ab/c/] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># first '/' of multiple</span> + 2<span class="Special"> <- </span>2 <span class="Comment"># first '/' of multiple</span> ] ] -<span class="muScenario">scenario</span> string-find-next-second [ +scenario string-find-next-second [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ab/c/] + 2:number<span class="Special"> <- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 3/start-index ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># second '/' of multiple</span> + 2<span class="Special"> <- </span>4 <span class="Comment"># second '/' of multiple</span> ] ] <span class="Comment"># next-index:number <- find-substring text:address:array:character, pattern:address:array:character, idx:number</span> <span class="Comment"># like find-next, but searches for multiple characters</span> <span class="Comment"># fairly dumb algorithm</span> -<span class="muRecipe">recipe</span> find-substring [ - <span class="Constant">local-scope</span> - text:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - pattern:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - idx:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - first:character<span class="Special"> <- </span>index *pattern, <span class="Constant">0</span> +recipe find-<span class="Identifier">substring</span> [ + <span class="Underlined">local</span>-scope + text:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + pattern:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + idx:number<span class="Special"> <- </span>next-ingredient + first:character<span class="Special"> <- </span>index *pattern, 0 <span class="Comment"># repeatedly check for match at current idx</span> - len:number<span class="Special"> <- </span>length *text - <span class="Delimiter">{</span> + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *text + { <span class="Comment"># does some unnecessary work checking for substrings even when there isn't enough of text left</span> done?:boolean<span class="Special"> <- </span>greater-or-equal idx, len - <span class="muControl">break-if</span> done? - found?:boolean<span class="Special"> <- </span>match-at text, pattern, idx - <span class="muControl">break-if</span> found? - idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> + break-if done? + found?:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at text, pattern, idx + break-if found? + idx<span class="Special"> <- </span>add idx, 1 <span class="Comment"># optimization: skip past indices that definitely won't match</span> idx<span class="Special"> <- </span>find-next text, first, idx - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> idx + loop + } + reply idx ] -<span class="muScenario">scenario</span> find-substring-1 [ +scenario find-<span class="Identifier">substring</span>-1 [ run [ - <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-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [bc] + 3:number<span class="Special"> <- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> + 3<span class="Special"> <- </span>1 ] ] -<span class="muScenario">scenario</span> find-substring-2 [ +scenario find-<span class="Identifier">substring</span>-2 [ run [ - <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-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">1</span> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abcd] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [bc] + 3:number<span class="Special"> <- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 1 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> + 3<span class="Special"> <- </span>1 ] ] -<span class="muScenario">scenario</span> find-substring-no-match [ +scenario find-<span class="Identifier">substring</span>-no-<span class="Identifier">match</span> [ run [ - <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-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [bd] + 3:number<span class="Special"> <- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># not found</span> + 3<span class="Special"> <- </span>3 <span class="Comment"># not found</span> ] ] -<span class="muScenario">scenario</span> find-substring-suffix-match [ +scenario find-<span class="Identifier">substring</span>-suffix-<span class="Identifier">match</span> [ run [ - <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-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abcd] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [cd] + 3:number<span class="Special"> <- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> + 3<span class="Special"> <- </span>2 ] ] -<span class="muScenario">scenario</span> find-substring-suffix-match-2 [ +scenario find-<span class="Identifier">substring</span>-suffix-<span class="Identifier">match</span>-2 [ run [ - <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-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abcd] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [cde] + 3:number<span class="Special"> <- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># not found</span> + 3<span class="Special"> <- </span>4 <span class="Comment"># not found</span> ] ] <span class="Comment"># result:boolean <- match-at text:address:array:character, pattern:address:array:character, idx:number</span> <span class="Comment"># checks if substring matches at index 'idx'</span> -<span class="muRecipe">recipe</span> match-at [ - <span class="Constant">local-scope</span> - text:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - pattern:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - idx:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - pattern-len:number<span class="Special"> <- </span>length *pattern +recipe <span class="Identifier">match</span>-at [ + <span class="Underlined">local</span>-scope + text:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + pattern:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + idx:number<span class="Special"> <- </span>next-ingredient + pattern-len:number<span class="Special"> <- </span><span class="Identifier">length</span> *pattern <span class="Comment"># check that there's space left for the pattern</span> - <span class="Delimiter">{</span> - x:number<span class="Special"> <- </span>length *text + { + x:number<span class="Special"> <- </span><span class="Identifier">length</span> *text x<span class="Special"> <- </span>subtract x, pattern-len enough-room?:boolean<span class="Special"> <- </span>lesser-or-equal idx, x - <span class="muControl">break-if</span> enough-room? - <span class="muControl">reply</span> <span class="Constant">0/not-found</span> - <span class="Delimiter">}</span> + break-if enough-room? + reply 0/not-found + } <span class="Comment"># check each character of pattern</span> - pattern-idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + pattern-idx:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { done?:boolean<span class="Special"> <- </span>greater-or-equal pattern-idx, pattern-len - <span class="muControl">break-if</span> done? + break-if done? c:character<span class="Special"> <- </span>index *text, idx - exp:character<span class="Special"> <- </span>index *pattern, pattern-idx - <span class="Delimiter">{</span> - match?:boolean<span class="Special"> <- </span>equal c, exp - <span class="muControl">break-if</span> match? - <span class="muControl">reply</span> <span class="Constant">0/not-found</span> - <span class="Delimiter">}</span> - idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> - pattern-idx<span class="Special"> <- </span>add pattern-idx, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> <span class="Constant">1/found</span> -] - -<span class="muScenario">scenario</span> match-at-checks-substring-at-index [ + <span class="Identifier">exp</span>:character<span class="Special"> <- </span>index *pattern, pattern-idx + { + <span class="Identifier">match</span>?:boolean<span class="Special"> <- </span>equal c, <span class="Identifier">exp</span> + break-if <span class="Identifier">match</span>? + reply 0/not-found + } + idx<span class="Special"> <- </span>add idx, 1 + pattern-idx<span class="Special"> <- </span>add pattern-idx, 1 + loop + } + reply 1/found +] + +scenario <span class="Identifier">match</span>-at-checks-<span class="Identifier">substring</span>-at-index [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ab] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># match found</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># match found</span> ] ] -<span class="muScenario">scenario</span> match-at-reflexive [ +scenario <span class="Identifier">match</span>-at-reflexive [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 1:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># match found</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># match found</span> ] ] -<span class="muScenario">scenario</span> match-at-outside-bounds [ +scenario <span class="Identifier">match</span>-at-outside-bounds [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [a] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 4 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># never matches</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># never matches</span> ] ] -<span class="muScenario">scenario</span> match-at-empty-pattern [ +scenario <span class="Identifier">match</span>-at-empty-pattern [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] 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> + 3<span class="Special"> <- </span>1 <span class="Comment"># always matches empty pattern given a valid index</span> ] ] -<span class="muScenario">scenario</span> match-at-empty-pattern-outside-bound [ +scenario <span class="Identifier">match</span>-at-empty-pattern-outside-bound [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 4 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no match</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># no match</span> ] ] -<span class="muScenario">scenario</span> match-at-empty-text [ +scenario <span class="Identifier">match</span>-at-empty-text [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no match</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># no match</span> ] ] -<span class="muScenario">scenario</span> match-at-empty-against-empty [ +scenario <span class="Identifier">match</span>-at-empty-against-empty [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 1:address:<span class="Identifier">array</span>:character, 0 ] 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> + 3<span class="Special"> <- </span>1 <span class="Comment"># matches because pattern is also empty</span> ] ] -<span class="muScenario">scenario</span> match-at-inside-bounds [ +scenario <span class="Identifier">match</span>-at-inside-bounds [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [bc] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 1 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># matches inner substring</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># matches inner substring</span> ] ] -<span class="muScenario">scenario</span> match-at-inside-bounds-2 [ +scenario <span class="Identifier">match</span>-at-inside-bounds-2 [ run [ - <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> + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [bc] + 3:boolean<span class="Special"> <- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0 ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no match</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># no match</span> ] ] <span class="Comment"># result:address:array:address:array:character <- split s:address:array:character, delim:character</span> -<span class="muRecipe">recipe</span> split [ - <span class="Constant">local-scope</span> - s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - delim:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe <span class="Identifier">split</span> [ + <span class="Underlined">local</span>-scope + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + delim:character<span class="Special"> <- </span>next-ingredient <span class="Comment"># empty string? return empty array</span> - len:number<span class="Special"> <- </span>length *s - <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:address:array:address:array:character<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">0</span> - <span class="muControl">reply</span> result - <span class="Delimiter">}</span> + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *s + { + empty?:boolean<span class="Special"> <- </span>equal len, 0 + break-unless empty? + result:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 0 + reply result + } <span class="Comment"># count #pieces we need room for</span> - count:number<span class="Special"> <- </span>copy <span class="Constant">1</span> <span class="Comment"># n delimiters = n+1 pieces</span> - idx:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + count:number<span class="Special"> <- </span><span class="Identifier">copy</span> 1 <span class="Comment"># n delimiters = n+1 pieces</span> + idx:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { idx<span class="Special"> <- </span>find-next s, delim, idx done?:boolean<span class="Special"> <- </span>greater-or-equal idx, len - <span class="muControl">break-if</span> done? - idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> - count<span class="Special"> <- </span>add count, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + break-if done? + idx<span class="Special"> <- </span>add idx, 1 + count<span class="Special"> <- </span>add count, 1 + loop + } <span class="Comment"># allocate space</span> - result:address:array:address:array:character<span class="Special"> <- </span>new <span class="Constant">location:type</span>, count + result:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</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> - <span class="Delimiter">{</span> + curr-result:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + start:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while next delim exists</span> done?:boolean<span class="Special"> <- </span>greater-or-equal start, len - <span class="muControl">break-if</span> done? + break-if 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:array:character<span class="Special"> <- </span>index-address *result, curr-result - *dest<span class="Special"> <- </span>string-copy s, start, end + dest:address:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index-address *result, curr-result + *dest<span class="Special"> <- </span>string-<span class="Identifier">copy</span> s, start, end <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> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + start<span class="Special"> <- </span>add end, 1 + curr-result<span class="Special"> <- </span>add curr-result, 1 + loop + } + reply result ] -<span class="muScenario">scenario</span> string-split-1 [ +scenario string-<span class="Identifier">split</span>-1 [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [a/b] + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash + 3:number<span class="Special"> <- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character + 4:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0 + 5:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 1 + 10:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character + 20:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *5:address:<span class="Identifier">array</span>: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> - <span class="Constant">10</span>:string<span class="Special"> <- </span><span class="Constant">[a]</span> - <span class="Constant">20</span>:string<span class="Special"> <- </span><span class="Constant">[b]</span> + 3<span class="Special"> <- </span>2 <span class="Comment"># length of result</span> + 10:string<span class="Special"> <- </span>[a] + 20:string<span class="Special"> <- </span>[b] ] ] -<span class="muScenario">scenario</span> string-split-2 [ +scenario string-<span class="Identifier">split</span>-2 [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [a/b/c] + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash + 3:number<span class="Special"> <- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character + 4:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0 + 5:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 1 + 6:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 2 + 10:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character + 20:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *5:address:<span class="Identifier">array</span>:character + 30:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *6:address:<span class="Identifier">array</span>: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> - <span class="Constant">10</span>:string<span class="Special"> <- </span><span class="Constant">[a]</span> - <span class="Constant">20</span>:string<span class="Special"> <- </span><span class="Constant">[b]</span> - <span class="Constant">30</span>:string<span class="Special"> <- </span><span class="Constant">[c]</span> + 3<span class="Special"> <- </span>3 <span class="Comment"># length of result</span> + 10:string<span class="Special"> <- </span>[a] + 20:string<span class="Special"> <- </span>[b] + 30:string<span class="Special"> <- </span>[c] ] ] -<span class="muScenario">scenario</span> string-split-missing [ +scenario string-<span class="Identifier">split</span>-missing [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash + 3:number<span class="Special"> <- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character + 4:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0 + 10:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>: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> - <span class="Constant">10</span>:string<span class="Special"> <- </span><span class="Constant">[abc]</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># length of result</span> + 10:string<span class="Special"> <- </span>[abc] ] ] -<span class="muScenario">scenario</span> string-split-empty [ +scenario string-<span class="Identifier">split</span>-empty [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash + 3:number<span class="Special"> <- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty result</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># empty result</span> ] ] -<span class="muScenario">scenario</span> string-split-empty-piece [ +scenario string-<span class="Identifier">split</span>-empty-piece [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [a/b<span class="Comment">//c]</span> + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash + 3:number<span class="Special"> <- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character + 4:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0 + 5:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 1 + 6:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 2 + 7:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 3 + 10:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character + 20:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *5:address:<span class="Identifier">array</span>:character + 30:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *6:address:<span class="Identifier">array</span>:character + 40:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *7:address:<span class="Identifier">array</span>: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> - <span class="Constant">10</span>:string<span class="Special"> <- </span><span class="Constant">[a]</span> - <span class="Constant">20</span>:string<span class="Special"> <- </span><span class="Constant">[b]</span> - <span class="Constant">30</span>:string<span class="Special"> <- </span><span class="Constant">[]</span> - <span class="Constant">40</span>:string<span class="Special"> <- </span><span class="Constant">[c]</span> + 3<span class="Special"> <- </span>4 <span class="Comment"># length of result</span> + 10:string<span class="Special"> <- </span>[a] + 20:string<span class="Special"> <- </span>[b] + 30:string<span class="Special"> <- </span>[] + 40:string<span class="Special"> <- </span>[c] ] ] <span class="Comment"># x:address:array:character, y:address:array:character <- split-first text:address:array:character, delim:character</span> -<span class="muRecipe">recipe</span> split-first [ - <span class="Constant">local-scope</span> - text:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - delim:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe <span class="Identifier">split</span>-first [ + <span class="Underlined">local</span>-scope + text:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + delim:character<span class="Special"> <- </span>next-ingredient <span class="Comment"># empty string? return empty strings</span> - len:number<span class="Special"> <- </span>length *text - <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: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">reply</span> x, y - <span class="Delimiter">}</span> - idx:number<span class="Special"> <- </span>find-next text, delim, <span class="Constant">0</span> - x:address:array:character<span class="Special"> <- </span>string-copy text, <span class="Constant">0</span>, idx - idx<span class="Special"> <- </span>add idx, <span class="Constant">1</span> - y:address:array:character<span class="Special"> <- </span>string-copy text, idx, len - <span class="muControl">reply</span> x, y -] - -<span class="muScenario">scenario</span> string-split-first [ + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *text + { + empty?:boolean<span class="Special"> <- </span>equal len, 0 + break-unless empty? + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + y:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [] + reply x, y + } + idx:number<span class="Special"> <- </span>find-next text, delim, 0 + x:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>string-<span class="Identifier">copy</span> text, 0, idx + idx<span class="Special"> <- </span>add idx, 1 + y:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>string-<span class="Identifier">copy</span> text, idx, len + reply x, y +] + +scenario string-<span class="Identifier">split</span>-first [ run [ - <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [a/b] + 2:address:<span class="Identifier">array</span>:character, 3:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">split</span>-first 1:address:<span class="Identifier">array</span>:character, 47/slash + 10:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character + 20:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">10</span>:string<span class="Special"> <- </span><span class="Constant">[a]</span> - <span class="Constant">20</span>:string<span class="Special"> <- </span><span class="Constant">[b]</span> + 10:string<span class="Special"> <- </span>[a] + 20:string<span class="Special"> <- </span>[b] ] ] <span class="Comment"># result:address:array:character <- string-copy buf:address:array:character, start:number, end:number</span> <span class="Comment"># todo: make this generic</span> -<span class="muRecipe">recipe</span> string-copy [ - <span class="Constant">local-scope</span> - buf:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - start:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - end:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe string-<span class="Identifier">copy</span> [ + <span class="Underlined">local</span>-scope + buf:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + start:number<span class="Special"> <- </span>next-ingredient + end:number<span class="Special"> <- </span>next-ingredient <span class="Comment"># if end is out of bounds, trim it</span> - len:number<span class="Special"> <- </span>length *buf - end:number<span class="Special"> <- </span>min len, end + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *buf + end:number<span class="Special"> <- </span><span class="Identifier">min</span> len, end <span class="Comment"># allocate space for result</span> len<span class="Special"> <- </span>subtract end, start - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, len + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">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> - <span class="Delimiter">{</span> + src-idx:number<span class="Special"> <- </span><span class="Identifier">copy</span> start + dest-idx:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { done?:boolean<span class="Special"> <- </span>greater-or-equal src-idx, end - <span class="muControl">break-if</span> done? + break-if 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 - 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> src + src-idx<span class="Special"> <- </span>add src-idx, 1 + dest-idx<span class="Special"> <- </span>add dest-idx, 1 + loop + } + reply result ] -<span class="muScenario">scenario</span> string-copy-copies-substring [ +scenario string-<span class="Identifier">copy</span>-copies-<span class="Identifier">substring</span> [ run [ - <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>string-copy <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>string-<span class="Identifier">copy</span> 1:address:<span class="Identifier">array</span>:character, 1, 3 + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[bc]</span> + 3:string<span class="Special"> <- </span>[bc] ] ] -<span class="muScenario">scenario</span> string-copy-out-of-bounds [ +scenario string-<span class="Identifier">copy</span>-out-of-bounds [ run [ - <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>string-copy <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>string-<span class="Identifier">copy</span> 1:address:<span class="Identifier">array</span>:character, 2, 4 + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[c]</span> + 3:string<span class="Special"> <- </span>[c] ] ] -<span class="muScenario">scenario</span> string-copy-out-of-bounds-2 [ +scenario string-<span class="Identifier">copy</span>-out-of-bounds-2 [ run [ - <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>string-copy <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 + 1:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abc] + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>string-<span class="Identifier">copy</span> 1:address:<span class="Identifier">array</span>:character, 3, 3 + 3:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character ] memory-should-contain [ - <span class="Constant">3</span>:string<span class="Special"> <- </span><span class="Constant">[]</span> - ] -] - -<span class="muRecipe">recipe</span> min [ - <span class="Constant">local-scope</span> - x:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - y:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - return-x?:boolean<span class="Special"> <- </span>lesser-than x, y - <span class="muControl">break-if</span> return-x? - <span class="muControl">reply</span> y - <span class="Delimiter">}</span> - <span class="muControl">reply</span> x -] - -<span class="muRecipe">recipe</span> max [ - <span class="Constant">local-scope</span> - x:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - y:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - return-x?:boolean<span class="Special"> <- </span>greater-than x, y - <span class="muControl">break-if</span> return-x? - <span class="muControl">reply</span> y - <span class="Delimiter">}</span> - <span class="muControl">reply</span> x + 3:string<span class="Special"> <- </span>[] + ] +] + +recipe <span class="Identifier">min</span> [ + <span class="Underlined">local</span>-scope + x:number<span class="Special"> <- </span>next-ingredient + y:number<span class="Special"> <- </span>next-ingredient + { + <span class="Identifier">return</span>-x?:boolean<span class="Special"> <- </span>lesser-than x, y + break-if <span class="Identifier">return</span>-x? + reply y + } + reply x +] + +recipe <span class="Identifier">max</span> [ + <span class="Underlined">local</span>-scope + x:number<span class="Special"> <- </span>next-ingredient + y:number<span class="Special"> <- </span>next-ingredient + { + <span class="Identifier">return</span>-x?:boolean<span class="Special"> <- </span>greater-than x, y + break-if <span class="Identifier">return</span>-x? + reply y + } + reply x ] </pre> </body> diff --git a/html/061channel.mu.html b/html/061channel.mu.html index 350dab6e..0823083a 100644 --- a/html/061channel.mu.html +++ b/html/061channel.mu.html @@ -13,14 +13,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } .SalientComment { color: #00ffff; } -.muRecipe { color: #ff8700; } +.Underlined { color: #c000c0; text-decoration: underline; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -33,23 +30,23 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <body> <pre id='vimCodeElement'> <span class="Comment"># Mu synchronizes using channels rather than locks, like Erlang and Go.</span> -<span class="Comment">#</span> +# <span class="Comment"># The two ends of a channel will usually belong to different routines, but</span> <span class="Comment"># each end should only be used by a single one. Don't try to read from or</span> <span class="Comment"># write to it from multiple routines at once.</span> -<span class="Comment">#</span> +# <span class="Comment"># The key property of channels is that writing to a full channel or reading</span> <span class="Comment"># from an empty one will put the current routine in 'waiting' state until the</span> <span class="Comment"># operation can be completed.</span> -<span class="muScenario">scenario</span> channel [ +scenario channel [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - <span class="Constant">2</span>:number, <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>read <span class="Constant">1</span>:address:channel + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3/capacity + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + 2:number, 1:address:channel<span class="Special"> <- </span><span class="Identifier">read</span> 1:address:channel ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">34</span> + 2<span class="Special"> <- </span>34 ] ] @@ -62,344 +59,344 @@ container channel [ <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span> <span class="Comment"># including) index first-empty. The reader always modifies it at first-full,</span> <span class="Comment"># while the writer always modifies it at first-empty.</span> - data:address:array:location + data:address:<span class="Identifier">array</span>:location ] <span class="Comment"># result:address:channel <- new-channel capacity:number</span> -<span class="muRecipe">recipe</span> new-channel [ - <span class="Constant">local-scope</span> +recipe <span class="Identifier">new</span>-channel [ + <span class="Underlined">local</span>-scope <span class="Comment"># result = new channel</span> - result:address:channel<span class="Special"> <- </span>new <span class="Constant">channel:type</span> + result:address:channel<span class="Special"> <- </span><span class="Identifier">new</span> channel:<span class="Identifier">type</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> + full:address:number<span class="Special"> <- </span>get-address *result, first-full:offset + *full<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <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> + free:address:number<span class="Special"> <- </span>get-address *result, first-free:offset + *free<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># result.data = new location[ingredient+1]</span> - capacity:number<span class="Special"> <- </span><span class="Constant">next-ingredient</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:array:location<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *dest<span class="Special"> <- </span>new <span class="Constant">location:type</span>, capacity - <span class="muControl">reply</span> result + capacity:number<span class="Special"> <- </span>next-ingredient + capacity<span class="Special"> <- </span>add capacity, 1 <span class="Comment"># unused slot for 'full?' below</span> + dest:address:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span>get-address *result, data:offset + *dest<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, capacity + reply result ] <span class="Comment"># chan <- write chan:address:channel, val:location</span> -<span class="muRecipe">recipe</span> write [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - val:location<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe <span class="Identifier">write</span> [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient + <span class="Identifier">val</span>:location<span class="Special"> <- </span>next-ingredient + { <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> + break-unless full + full-address:address:number<span class="Special"> <- </span>get-address *chan, first-full:offset wait-for-location *full-address - <span class="Delimiter">}</span> + } <span class="Comment"># store val</span> - circular-buffer:address:array:location<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> + circular-buffer:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span>get *chan, data:offset + free:address:number<span class="Special"> <- </span>get-address *chan, first-free:offset dest:address:location<span class="Special"> <- </span>index-address *circular-buffer, *free - *dest<span class="Special"> <- </span>copy val + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">val</span> <span class="Comment"># mark its slot as filled</span> - *free<span class="Special"> <- </span>add *free, <span class="Constant">1</span> - <span class="Delimiter">{</span> + *free<span class="Special"> <- </span>add *free, 1 + { <span class="Comment"># wrap free around to 0 if necessary</span> - len:number<span class="Special"> <- </span>length *circular-buffer + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *circular-buffer 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span> + break-unless at-end? + *free<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + } + reply chan/same-as-ingredient:0 ] <span class="Comment"># result:location, chan <- read chan:address:channel</span> -<span class="muRecipe">recipe</span> read [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe <span class="Identifier">read</span> [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient + { <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> + break-unless empty? + free-address:address:number<span class="Special"> <- </span>get-address *chan, first-free:offset 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:array:location<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> + full:address:number<span class="Special"> <- </span>get-address *chan, first-full:offset + circular-buffer:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span>get *chan, data:offset result:location<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="Delimiter">{</span> + *full<span class="Special"> <- </span>add *full, 1 + { <span class="Comment"># wrap full around to 0 if necessary</span> - len:number<span class="Special"> <- </span>length *circular-buffer + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *circular-buffer 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result, chan/same-as-ingredient:<span class="Constant">0</span> + break-unless at-end? + *full<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + } + reply result, chan/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> clear-channel [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe clear-channel [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient + { empty?:boolean<span class="Special"> <- </span>channel-empty? chan - <span class="muControl">break-if</span> empty? - _, chan<span class="Special"> <- </span>read chan - <span class="Delimiter">}</span> - <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span> + break-if empty? + _, chan<span class="Special"> <- </span><span class="Identifier">read</span> chan + } + reply chan/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> channel-initialization [ +scenario channel-initialization [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span> + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3/capacity + 2:number<span class="Special"> <- </span>get *1:address:channel, first-full:offset + 3:number<span class="Special"> <- </span>get *1:address:channel, first-free:offset ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-full</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-free</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># first-full</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># first-free</span> ] ] -<span class="muScenario">scenario</span> channel-write-increments-free [ +scenario channel-<span class="Identifier">write</span>-increments-free [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span> + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3/capacity + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + 2:number<span class="Special"> <- </span>get *1:address:channel, first-full:offset + 3:number<span class="Special"> <- </span>get *1:address:channel, first-free:offset ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-full</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-free</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># first-full</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># first-free</span> ] ] -<span class="muScenario">scenario</span> channel-read-increments-full [ +scenario channel-<span class="Identifier">read</span>-increments-full [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - _, <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>read <span class="Constant">1</span>:address:channel - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span> + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3/capacity + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + _, 1:address:channel<span class="Special"> <- </span><span class="Identifier">read</span> 1:address:channel + 2:number<span class="Special"> <- </span>get *1:address:channel, first-full:offset + 3:number<span class="Special"> <- </span>get *1:address:channel, first-free:offset ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-full</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-free</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># first-full</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># first-free</span> ] ] -<span class="muScenario">scenario</span> channel-wrap [ +scenario channel-wrap [ run [ <span class="Comment"># channel with just 1 slot</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 1/capacity <span class="Comment"># write and read a value</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - _, <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>read <span class="Constant">1</span>:address:channel + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + _, 1:address:channel<span class="Special"> <- </span><span class="Identifier">read</span> 1:address:channel <span class="Comment"># first-free will now be 1</span> - <span class="Constant">2</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span> - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span> + 2:number<span class="Special"> <- </span>get *1:address:channel, first-free:offset + 3:number<span class="Special"> <- </span>get *1:address:channel, first-free:offset <span class="Comment"># write second value, verify that first-free wraps</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span> + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + 4:number<span class="Special"> <- </span>get *1:address:channel, first-free:offset <span class="Comment"># read second value, verify that first-full wraps</span> - _, <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>read <span class="Constant">1</span>:address:channel - <span class="Constant">5</span>:number<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span> + _, 1:address:channel<span class="Special"> <- </span><span class="Identifier">read</span> 1:address:channel + 5:number<span class="Special"> <- </span>get *1:address:channel, first-full:offset ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-free after first write</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first-full after first read</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-free after second write, wrapped</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first-full after second read, wrapped</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># first-free after first write</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># first-full after first read</span> + 4<span class="Special"> <- </span>0 <span class="Comment"># first-free after second write, wrapped</span> + 5<span class="Special"> <- </span>0 <span class="Comment"># first-full after second read, wrapped</span> ] ] <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">recipe</span> channel-empty? [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe channel-empty? [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient <span class="Comment"># return chan.first-full == chan.first-free</span> - full:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-full:offset</span> - free:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-free:offset</span> + full:number<span class="Special"> <- </span>get *chan, first-full:offset + free:number<span class="Special"> <- </span>get *chan, first-free:offset result:boolean<span class="Special"> <- </span>equal full, free - <span class="muControl">reply</span> result + reply result ] <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">recipe</span> channel-full? [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe channel-full? [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient <span class="Comment"># tmp = chan.first-free + 1</span> - tmp:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-free:offset</span> - tmp<span class="Special"> <- </span>add tmp, <span class="Constant">1</span> - <span class="Delimiter">{</span> + tmp:number<span class="Special"> <- </span>get *chan, first-free:offset + tmp<span class="Special"> <- </span>add tmp, 1 + { <span class="Comment"># if tmp == chan.capacity, tmp = 0</span> len:number<span class="Special"> <- </span>channel-capacity chan at-end?:boolean<span class="Special"> <- </span>greater-or-equal tmp, len - <span class="muControl">break-unless</span> at-end? - tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">}</span> + break-unless at-end? + tmp<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + } <span class="Comment"># return chan.first-full == tmp</span> - full:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-full:offset</span> + full:number<span class="Special"> <- </span>get *chan, first-full:offset result:boolean<span class="Special"> <- </span>equal full, tmp - <span class="muControl">reply</span> result + reply result ] <span class="Comment"># result:number <- channel-capacity chan:address:channel</span> -<span class="muRecipe">recipe</span> channel-capacity [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - q:address:array:location<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> - result:number<span class="Special"> <- </span>length *q - <span class="muControl">reply</span> result +recipe channel-capacity [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient + q:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span>get *chan, data:offset + result:number<span class="Special"> <- </span><span class="Identifier">length</span> *q + reply result ] -<span class="muScenario">scenario</span> channel-new-empty-not-full [ +scenario channel-<span class="Identifier">new</span>-empty-not-full [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">2</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">1</span>:address:channel - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">1</span>:address:channel + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3/capacity + 2:boolean<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:boolean<span class="Special"> <- </span>channel-full? 1:address:channel ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># empty?</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># full?</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># full?</span> ] ] -<span class="muScenario">scenario</span> channel-write-not-empty [ +scenario channel-<span class="Identifier">write</span>-not-empty [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3/capacity</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - <span class="Constant">2</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">1</span>:address:channel - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">1</span>:address:channel + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3/capacity + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + 2:boolean<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:boolean<span class="Special"> <- </span>channel-full? 1:address:channel ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty?</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># full?</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># full?</span> ] ] -<span class="muScenario">scenario</span> channel-write-full [ +scenario channel-<span class="Identifier">write</span>-full [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - <span class="Constant">2</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">1</span>:address:channel - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">1</span>:address:channel + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 1/capacity + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + 2:boolean<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:boolean<span class="Special"> <- </span>channel-full? 1:address:channel ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># empty?</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># full?</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># full?</span> ] ] -<span class="muScenario">scenario</span> channel-read-not-full [ +scenario channel-<span class="Identifier">read</span>-not-full [ run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">1/capacity</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span> - _, <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>read <span class="Constant">1</span>:address:channel - <span class="Constant">2</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">1</span>:address:channel - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>channel-full? <span class="Constant">1</span>:address:channel + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 1/capacity + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 34 + _, 1:address:channel<span class="Special"> <- </span><span class="Identifier">read</span> 1:address:channel + 2:boolean<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:boolean<span class="Special"> <- </span>channel-full? 1:address:channel ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># empty?</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># full?</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># full?</span> ] ] <span class="Comment"># helper for channels of characters in particular</span> <span class="Comment"># out <- buffer-lines in:address:channel, out:address:channel</span> -<span class="muRecipe">recipe</span> buffer-lines [ - <span class="Constant">local-scope</span> - in:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - out:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe buffer-lines [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:channel<span class="Special"> <- </span>next-ingredient + out:address:channel<span class="Special"> <- </span>next-ingredient <span class="Comment"># repeat forever</span> - <span class="Delimiter">{</span> - line:address:buffer<span class="Special"> <- </span>new-buffer, <span class="Constant">30</span> + { + line:address:buffer<span class="Special"> <- </span><span class="Identifier">new</span>-buffer, 30 <span class="Comment"># read characters from 'in' until newline, copy into line</span> - <span class="Delimiter">{</span> -<span class="Constant"> +next-character</span> - c:character, in<span class="Special"> <- </span>read in + { + +next-character + c:character, <span class="Identifier">in</span><span class="Special"> <- </span><span class="Identifier">read</span> <span class="Identifier">in</span> <span class="Comment"># drop a character on backspace</span> - <span class="Delimiter">{</span> + { <span class="Comment"># special-case: if it's a backspace</span> - backspace?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">8</span> - <span class="muControl">break-unless</span> backspace? + backspace?:boolean<span class="Special"> <- </span>equal c, 8 + break-unless 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> - <span class="muControl">break-if</span> buffer-empty? - *buffer-length<span class="Special"> <- </span>subtract *buffer-length, <span class="Constant">1</span> - <span class="Delimiter">}</span> + { + buffer-<span class="Identifier">length</span>:address:number<span class="Special"> <- </span>get-address *line, <span class="Identifier">length</span>:offset + buffer-empty?:boolean<span class="Special"> <- </span>equal *buffer-<span class="Identifier">length</span>, 0 + break-if buffer-empty? + *buffer-<span class="Identifier">length</span><span class="Special"> <- </span>subtract *buffer-<span class="Identifier">length</span>, 1 + } <span class="Comment"># and don't append this one</span> - <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> - <span class="Delimiter">}</span> + loop +next-character:label + } <span class="Comment"># append anything else</span> - line<span class="Special"> <- </span>buffer-append line, c - line-done?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> - <span class="muControl">break-if</span> line-done? + line<span class="Special"> <- </span>buffer-<span class="Identifier">append</span> line, c + line-done?:boolean<span class="Special"> <- </span>equal c, 10/newline + break-if line-done? <span class="Comment"># stop buffering on eof (currently only generated by fake console)</span> - eof?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">0/eof</span> - <span class="muControl">break-if</span> eof? - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + eof?:boolean<span class="Special"> <- </span>equal c, 0/eof + break-if eof? + loop + } <span class="Comment"># copy line into 'out'</span> - i:number<span class="Special"> <- </span>copy <span class="Constant">0</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 - <span class="muControl">break-if</span> done? + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + line-contents:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *line, data:offset + <span class="Identifier">max</span>:number<span class="Special"> <- </span>get *line, <span class="Identifier">length</span>:offset + { + done?:boolean<span class="Special"> <- </span>greater-or-equal i, <span class="Identifier">max</span> + break-if done? c:character<span class="Special"> <- </span>index *line-contents, i - out<span class="Special"> <- </span>write out, c - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> out/same-as-ingredient:<span class="Constant">1</span> + out<span class="Special"> <- </span><span class="Identifier">write</span> out, c + i<span class="Special"> <- </span>add i, 1 + loop + } + loop + } + reply out/same-as-ingredient:1 ] -<span class="muScenario">scenario</span> buffer-lines-blocks-until-newline [ +scenario buffer-lines-blocks-until-newline [ run [ - <span class="Constant">1</span>:address:channel/stdin<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> - <span class="Constant">2</span>:address:channel/buffered-stdin<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin - assert <span class="Constant">3</span>:boolean, [ -F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> init] + 1:address:channel/stdin<span class="Special"> <- </span><span class="Identifier">new</span>-channel 10/capacity + 2:address:channel/buffered-stdin<span class="Special"> <- </span><span class="Identifier">new</span>-channel 10/capacity + 3:boolean<span class="Special"> <- </span>channel-empty? 2:address:channel/buffered-stdin + <span class="Identifier">assert</span> 3:boolean, [ +F buffer-lines-blocks-until-newline: channel should be empty after init] <span class="Comment"># buffer stdin into buffered-stdin, try to read from buffered-stdin</span> - <span class="Constant">4</span>:number/buffer-routine<span class="Special"> <- </span>start-running <span class="Constant">buffer-lines:recipe</span>, <span class="Constant">1</span>:address:channel/stdin, <span class="Constant">2</span>:address:channel/buffered-stdin - wait-for-routine <span class="Constant">4</span>:number/buffer-routine - <span class="Constant">5</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin - assert <span class="Constant">5</span>:boolean, [ -F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> buffer-lines bring-up] + 4:number/buffer-routine<span class="Special"> <- </span>start-running buffer-lines:recipe, 1:address:channel/stdin, 2:address:channel/buffered-stdin + wait-for-routine 4:number/buffer-routine + 5:boolean<span class="Special"> <- </span>channel-empty? 2:address:channel/buffered-stdin + <span class="Identifier">assert</span> 5:boolean, [ +F buffer-lines-blocks-until-newline: channel should be empty after buffer-lines bring-up] <span class="Comment"># write 'a'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span> - restart <span class="Constant">4</span>:number/buffer-routine - wait-for-routine <span class="Constant">4</span>:number/buffer-routine - <span class="Constant">6</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin - assert <span class="Constant">6</span>:boolean, [ -F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> writing 'a'] + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 97/a + restart 4:number/buffer-routine + wait-for-routine 4:number/buffer-routine + 6:boolean<span class="Special"> <- </span>channel-empty? 2:address:channel/buffered-stdin + <span class="Identifier">assert</span> 6:boolean, [ +F buffer-lines-blocks-until-newline: channel should be empty after writing 'a'] <span class="Comment"># write 'b'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">98/b</span> - restart <span class="Constant">4</span>:number/buffer-routine - wait-for-routine <span class="Constant">4</span>:number/buffer-routine - <span class="Constant">7</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin - assert <span class="Constant">7</span>:boolean, [ -F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> writing 'b'] + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 98/b + restart 4:number/buffer-routine + wait-for-routine 4:number/buffer-routine + 7:boolean<span class="Special"> <- </span>channel-empty? 2:address:channel/buffered-stdin + <span class="Identifier">assert</span> 7:boolean, [ +F buffer-lines-blocks-until-newline: channel should be empty after writing 'b'] <span class="Comment"># write newline</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10/newline</span> - restart <span class="Constant">4</span>:number/buffer-routine - wait-for-routine <span class="Constant">4</span>:number/buffer-routine - <span class="Constant">8</span>:boolean<span class="Special"> <- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin - <span class="Constant">9</span>:boolean/completed?<span class="Special"> <- </span>not <span class="Constant">8</span>:boolean - assert <span class="Constant">9</span>:boolean/completed?, [ -F buffer-lines-blocks-until-newline: channel should contain data <span class="muRecipe">after</span> writing newline] - trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span> + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 10/newline + restart 4:number/buffer-routine + wait-for-routine 4:number/buffer-routine + 8:boolean<span class="Special"> <- </span>channel-empty? 2:address:channel/buffered-stdin + 9:boolean/completed?<span class="Special"> <- </span>not 8:boolean + <span class="Identifier">assert</span> 9:boolean/completed?, [ +F buffer-lines-blocks-until-newline: channel should contain data after writing newline] + trace 1, [test], [reached end] ] trace-should-contain [ test: reached end diff --git a/html/062array.mu.html b/html/062array.mu.html index b65da102..350f8d6a 100644 --- a/html/062array.mu.html +++ b/html/062array.mu.html @@ -13,13 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } -.muRecipe { color: #ff8700; } +.Underlined { color: #c000c0; text-decoration: underline; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -31,45 +28,45 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } </head> <body> <pre id='vimCodeElement'> -<span class="muScenario">scenario</span> array-from-args [ +scenario <span class="Identifier">array</span>-from-<span class="Identifier">args</span> [ run [ - <span class="Constant">1</span>:address:array:location<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:location<span class="Special"> <- </span>copy *<span class="Constant">1</span>:address:array:location + 1:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span>-<span class="Identifier">array</span> 0, 1, 2 + 2:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:location ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># array length</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">2</span> + 2<span class="Special"> <- </span>3 <span class="Comment"># array length</span> + 3<span class="Special"> <- </span>0 + 4<span class="Special"> <- </span>1 + 5<span class="Special"> <- </span>2 ] ] <span class="Comment"># create an array out of a list of scalar args</span> -<span class="muRecipe">recipe</span> new-array [ - <span class="Constant">local-scope</span> - capacity:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> +recipe <span class="Identifier">new</span>-<span class="Identifier">array</span> [ + <span class="Underlined">local</span>-scope + capacity:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while read curr-value</span> - curr-value:location, exists?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">break-unless</span> exists? - capacity<span class="Special"> <- </span>add capacity, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - result:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, capacity + curr-value:location, exists?:boolean<span class="Special"> <- </span>next-ingredient + break-unless exists? + capacity<span class="Special"> <- </span>add capacity, 1 + loop + } + result:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, capacity rewind-ingredients - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># while read curr-value</span> done?:boolean<span class="Special"> <- </span>greater-or-equal i, capacity - <span class="muControl">break-if</span> done? - curr-value:location, 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> + break-if done? + curr-value:location, exists?:boolean<span class="Special"> <- </span>next-ingredient + <span class="Identifier">assert</span> exists?, [<span class="Identifier">error</span> <span class="Identifier">in</span> rewinding ingredients to <span class="Identifier">new</span>-<span class="Identifier">array</span>] tmp:address:location<span class="Special"> <- </span>index-address *result, i - *tmp<span class="Special"> <- </span>copy curr-value - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> result + *tmp<span class="Special"> <- </span><span class="Identifier">copy</span> curr-value + i<span class="Special"> <- </span>add i, 1 + loop + } + reply result ] </pre> </body> diff --git a/html/063list.mu.html b/html/063list.mu.html index 7d106ca0..320049a1 100644 --- a/html/063list.mu.html +++ b/html/063list.mu.html @@ -13,13 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.muScenario { color: #00af00; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -32,7 +29,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <body> <pre id='vimCodeElement'> <span class="Comment"># A list links up multiple objects together to make them easier to manage.</span> -<span class="Comment">#</span> +# <span class="Comment"># Try to make all objects in a single list of the same type, it'll help avoid bugs.</span> <span class="Comment"># If you want to store multiple types in a single list, use an exclusive-container.</span> @@ -42,53 +39,52 @@ container list [ ] <span class="Comment"># result:address:list <- push x:location, in:address:list</span> -<span class="muRecipe">recipe</span> push [ - <span class="Constant">local-scope</span> - x:location<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - in:address:list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - result:address:list<span class="Special"> <- </span>new <span class="Constant">list:type</span> - val:address:location<span class="Special"> <- </span>get-address *result, <span class="Constant">value:offset</span> - *val<span class="Special"> <- </span>copy x - next:address:address:list<span class="Special"> <- </span>get-address *result, <span class="Constant">next:offset</span> - *next<span class="Special"> <- </span>copy in - <span class="muControl">reply</span> result +recipe push [ + <span class="Underlined">local</span>-scope + x:location<span class="Special"> <- </span>next-ingredient + <span class="Identifier">in</span>:address:list<span class="Special"> <- </span>next-ingredient + result:address:list<span class="Special"> <- </span><span class="Identifier">new</span> list:<span class="Identifier">type</span> + <span class="Identifier">val</span>:address:location<span class="Special"> <- </span>get-address *result, value:offset + *<span class="Identifier">val</span><span class="Special"> <- </span><span class="Identifier">copy</span> x + next:address:address:list<span class="Special"> <- </span>get-address *result, next:offset + *next<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + reply result ] <span class="Comment"># result:location <- first in:address:list</span> -<span class="muRecipe">recipe</span> first [ - <span class="Constant">local-scope</span> - in:address:list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - result:location<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> - <span class="muControl">reply</span> result +recipe first [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:list<span class="Special"> <- </span>next-ingredient + result:location<span class="Special"> <- </span>get *<span class="Identifier">in</span>, value:offset + reply result ] <span class="Comment"># result:address:list <- rest in:address:list</span> -<span class="muRecipe">recipe</span> rest [ - <span class="Constant">local-scope</span> - in:address:list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - result:address:list<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> - <span class="muControl">reply</span> result +recipe rest [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:list<span class="Special"> <- </span>next-ingredient + result:address:list<span class="Special"> <- </span>get *<span class="Identifier">in</span>, next:offset + reply result ] -<span class="muScenario">scenario</span> list-handling [ +scenario list-handling [ run [ -<span class="CommentedCode">#? $start-tracing #? 1</span> - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:list - <span class="Constant">2</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:list - <span class="Constant">3</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first <span class="Constant">1</span>:address:list - <span class="Constant">1</span>:address:list<span class="Special"> <- </span>rest <span class="Constant">1</span>:address:list + 1:address:list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + 1:address:list<span class="Special"> <- </span>push 3, 1:address:list + 1:address:list<span class="Special"> <- </span>push 4, 1:address:list + 1:address:list<span class="Special"> <- </span>push 5, 1:address:list + 2:number<span class="Special"> <- </span>first 1:address:list + 1:address:list<span class="Special"> <- </span>rest 1:address:list + 3:number<span class="Special"> <- </span>first 1:address:list + 1:address:list<span class="Special"> <- </span>rest 1:address:list + 4:number<span class="Special"> <- </span>first 1:address:list + 1:address:list<span class="Special"> <- </span>rest 1:address:list ] 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> - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">5</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> + 1<span class="Special"> <- </span>0 <span class="Comment"># empty to empty, dust to dust..</span> + 2<span class="Special"> <- </span>5 + 3<span class="Special"> <- </span>4 + 4<span class="Special"> <- </span>3 ] ] </pre> diff --git a/html/065duplex_list.mu.html b/html/065duplex_list.mu.html index 1ed671cd..a0744bef 100644 --- a/html/065duplex_list.mu.html +++ b/html/065duplex_list.mu.html @@ -13,14 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.muScenario { color: #00af00; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -41,366 +37,558 @@ container duplex-list [ ] <span class="Comment"># result:address:duplex-list <- push-duplex x:location, in:address:duplex-list</span> -<span class="muRecipe">recipe</span> push-duplex [ - <span class="Constant">local-scope</span> - x:location<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - in:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - result:address:duplex-list<span class="Special"> <- </span>new <span class="Constant">duplex-list:type</span> - val:address:location<span class="Special"> <- </span>get-address *result, <span class="Constant">value:offset</span> - *val<span class="Special"> <- </span>copy x - next:address:address:duplex-list<span class="Special"> <- </span>get-address *result, <span class="Constant">next:offset</span> - *next<span class="Special"> <- </span>copy in - <span class="muControl">reply-unless</span> in, result - prev:address:address:duplex-list<span class="Special"> <- </span>get-address *in, <span class="Constant">prev:offset</span> - *prev<span class="Special"> <- </span>copy result - <span class="muControl">reply</span> result +recipe push-duplex [ + <span class="Underlined">local</span>-scope + x:location<span class="Special"> <- </span>next-ingredient + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + result:address:duplex-list<span class="Special"> <- </span><span class="Identifier">new</span> duplex-list:<span class="Identifier">type</span> + <span class="Identifier">val</span>:address:location<span class="Special"> <- </span>get-address *result, value:offset + *<span class="Identifier">val</span><span class="Special"> <- </span><span class="Identifier">copy</span> x + next:address:address:duplex-list<span class="Special"> <- </span>get-address *result, next:offset + *next<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + reply-unless <span class="Identifier">in</span>, result + prev:address:address:duplex-list<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, prev:offset + *prev<span class="Special"> <- </span><span class="Identifier">copy</span> result + reply result ] <span class="Comment"># result:location <- first-duplex in:address:duplex-list</span> -<span class="muRecipe">recipe</span> first-duplex [ - <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> - result:location<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> - <span class="muControl">reply</span> result +recipe first-duplex [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + reply-unless <span class="Identifier">in</span>, 0 + result:location<span class="Special"> <- </span>get *<span class="Identifier">in</span>, value:offset + reply result ] <span class="Comment"># result:address:duplex-list <- next-duplex in:address:duplex-list</span> -<span class="muRecipe">recipe</span> next-duplex [ - <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> - result:address:duplex-list<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> - <span class="muControl">reply</span> result +recipe next-duplex [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + reply-unless <span class="Identifier">in</span>, 0 + result:address:duplex-list<span class="Special"> <- </span>get *<span class="Identifier">in</span>, next:offset + reply result ] <span class="Comment"># result:address:duplex-list <- prev-duplex in:address:duplex-list</span> -<span class="muRecipe">recipe</span> prev-duplex [ - <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> - result:address:duplex-list<span class="Special"> <- </span>get *in, <span class="Constant">prev:offset</span> - <span class="muControl">reply</span> result +recipe prev-duplex [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + reply-unless <span class="Identifier">in</span>, 0 + result:address:duplex-list<span class="Special"> <- </span>get *<span class="Identifier">in</span>, prev:offset + reply result ] -<span class="muScenario">scenario</span> duplex-list-handling [ +scenario duplex-list-handling [ run [ <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:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Constant">3</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">3</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">3</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">3</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">3</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">8</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">8</span>:address:duplex-list - <span class="Constant">10</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">8</span>:address:duplex-list - <span class="Constant">11</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">8</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">12</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">4</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">13</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">4</span>:address:duplex-list - <span class="Constant">14</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">3</span>:address:duplex-list, <span class="Constant">4</span>:address:duplex-list -<span class="CommentedCode">#? $dump-trace #? 1</span> + 1:number<span class="Special"> <- </span><span class="Identifier">copy</span> 34 + 2:number<span class="Special"> <- </span><span class="Identifier">copy</span> 35 + 3:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + 3:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 3:address:duplex-list + 3:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 3:address:duplex-list + 3:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 3:address:duplex-list + 4:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 3:address:duplex-list + 5:number<span class="Special"> <- </span>first-duplex 4:address:duplex-list + 4:address:duplex-list<span class="Special"> <- </span>next-duplex 4:address:duplex-list + 6:number<span class="Special"> <- </span>first-duplex 4:address:duplex-list + 4:address:duplex-list<span class="Special"> <- </span>next-duplex 4:address:duplex-list + 7:number<span class="Special"> <- </span>first-duplex 4:address:duplex-list + 8:address:duplex-list<span class="Special"> <- </span>next-duplex 4:address:duplex-list + 9:number<span class="Special"> <- </span>first-duplex 8:address:duplex-list + 10:address:duplex-list<span class="Special"> <- </span>next-duplex 8:address:duplex-list + 11:address:duplex-list<span class="Special"> <- </span>prev-duplex 8:address:duplex-list + 4:address:duplex-list<span class="Special"> <- </span>prev-duplex 4:address:duplex-list + 12:number<span class="Special"> <- </span>first-duplex 4:address:duplex-list + 4:address:duplex-list<span class="Special"> <- </span>prev-duplex 4:address:duplex-list + 13:number<span class="Special"> <- </span>first-duplex 4:address:duplex-list + 14:boolean<span class="Special"> <- </span>equal 3:address:duplex-list, 4:address:duplex-list ] 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> - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">34</span> - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">35</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># null</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># first of null</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># next of null</span> - <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># prev of null</span> - <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># then start scanning prev</span> - <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">5</span> - <span class="Constant">14</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 0<span class="Special"> <- </span>0 <span class="Comment"># no modifications to null pointers</span> + 1<span class="Special"> <- </span>34 + 2<span class="Special"> <- </span>35 + 5<span class="Special"> <- </span>5 <span class="Comment"># scanning next</span> + 6<span class="Special"> <- </span>4 + 7<span class="Special"> <- </span>3 + 8<span class="Special"> <- </span>0 <span class="Comment"># null</span> + 9<span class="Special"> <- </span>0 <span class="Comment"># first of null</span> + 10<span class="Special"> <- </span>0 <span class="Comment"># next of null</span> + 11<span class="Special"> <- </span>0 <span class="Comment"># prev of null</span> + 12<span class="Special"> <- </span>4 <span class="Comment"># then start scanning prev</span> + 13<span class="Special"> <- </span>5 + 14<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> ] ] <span class="Comment"># l:address:duplex-list <- insert-duplex x:location, in:address:duplex-list</span> <span class="Comment"># Inserts 'x' after 'in'. Returns some pointer into the list.</span> -<span class="muRecipe">recipe</span> insert-duplex [ - <span class="Constant">local-scope</span> - x:location<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - in:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - new-node:address:duplex-list<span class="Special"> <- </span>new <span class="Constant">duplex-list:type</span> - val:address:location<span class="Special"> <- </span>get-address *new-node, <span class="Constant">value:offset</span> - *val<span class="Special"> <- </span>copy x - next-node:address:duplex-list<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> +recipe insert-duplex [ + <span class="Underlined">local</span>-scope + x:location<span class="Special"> <- </span>next-ingredient + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + <span class="Identifier">new</span>-node:address:duplex-list<span class="Special"> <- </span><span class="Identifier">new</span> duplex-list:<span class="Identifier">type</span> + <span class="Identifier">val</span>:address:location<span class="Special"> <- </span>get-address *<span class="Identifier">new</span>-node, value:offset + *<span class="Identifier">val</span><span class="Special"> <- </span><span class="Identifier">copy</span> x + next-node:address:duplex-list<span class="Special"> <- </span>get *<span class="Identifier">in</span>, next:offset <span class="Comment"># in.next = new-node</span> - y:address:address:duplex-list<span class="Special"> <- </span>get-address *in, <span class="Constant">next:offset</span> - *y<span class="Special"> <- </span>copy new-node + y:address:address:duplex-list<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, next:offset + *y<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-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 + y<span class="Special"> <- </span>get-address *<span class="Identifier">new</span>-node, prev:offset + *y<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> <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 + y<span class="Special"> <- </span>get-address *<span class="Identifier">new</span>-node, next:offset + *y<span class="Special"> <- </span><span class="Identifier">copy</span> next-node <span class="Comment"># if next-node is not null</span> - <span class="muControl">reply-unless</span> next-node, new-node + reply-unless next-node, <span class="Identifier">new</span>-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 - <span class="muControl">reply</span> new-node <span class="Comment"># just signalling something changed; don't rely on the result</span> + y<span class="Special"> <- </span>get-address *next-node, prev:offset + *y<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-node + reply <span class="Identifier">new</span>-node <span class="Comment"># just signalling something changed; don't rely on the result</span> ] -<span class="muScenario">scenario</span> inserting-into-duplex-list [ +scenario inserting-into-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">1</span>:address:duplex-list <span class="Comment"># 2 points inside list</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to head of list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list <span class="Comment"># 2 points inside list</span> + 2:address:duplex-list<span class="Special"> <- </span>insert-duplex 6, 2:address:duplex-list <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 1:address:duplex-list + 3:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 4:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 5:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 6:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 7:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 8:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 9:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 10:boolean<span class="Special"> <- </span>equal 1:address:duplex-list, 2:address:duplex-list ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># inserted element</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># then prev</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">5</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 3<span class="Special"> <- </span>5 <span class="Comment"># scanning next</span> + 4<span class="Special"> <- </span>4 + 5<span class="Special"> <- </span>6 <span class="Comment"># inserted element</span> + 6<span class="Special"> <- </span>3 + 7<span class="Special"> <- </span>6 <span class="Comment"># then prev</span> + 8<span class="Special"> <- </span>4 + 9<span class="Special"> <- </span>5 + 10<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> ] ] -<span class="muScenario">scenario</span> inserting-at-end-of-duplex-list [ +scenario inserting-at-end-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">1</span>:address:duplex-list <span class="Comment"># 2 points inside list</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list <span class="Comment"># now at end of list</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to head of list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list <span class="Comment"># 2 points inside list</span> + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list <span class="Comment"># now at end of list</span> + 2:address:duplex-list<span class="Special"> <- </span>insert-duplex 6, 2:address:duplex-list <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 1:address:duplex-list + 3:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 4:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 5:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 6:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 7:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 8:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 9:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 10:boolean<span class="Special"> <- </span>equal 1:address:duplex-list, 2:address:duplex-list ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># inserted element</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># then prev</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">5</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 3<span class="Special"> <- </span>5 <span class="Comment"># scanning next</span> + 4<span class="Special"> <- </span>4 + 5<span class="Special"> <- </span>3 + 6<span class="Special"> <- </span>6 <span class="Comment"># inserted element</span> + 7<span class="Special"> <- </span>3 <span class="Comment"># then prev</span> + 8<span class="Special"> <- </span>4 + 9<span class="Special"> <- </span>5 + 10<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> ] ] -<span class="muScenario">scenario</span> inserting-after-start-of-duplex-list [ +scenario inserting-after-start-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">1</span>:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to head of list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>insert-duplex 6, 1:address:duplex-list <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">9</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 1:address:duplex-list + 3:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 4:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 5:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 6:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 7:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 8:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 9:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 10:boolean<span class="Special"> <- </span>equal 1:address:duplex-list, 2:address:duplex-list ] memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># inserted element</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># then prev</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">6</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">5</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 3<span class="Special"> <- </span>5 <span class="Comment"># scanning next</span> + 4<span class="Special"> <- </span>6 <span class="Comment"># inserted element</span> + 5<span class="Special"> <- </span>4 + 6<span class="Special"> <- </span>3 + 7<span class="Special"> <- </span>4 <span class="Comment"># then prev</span> + 8<span class="Special"> <- </span>6 + 9<span class="Special"> <- </span>5 + 10<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> ] ] <span class="Comment"># l:address:duplex-list <- remove-duplex in:address:duplex-list</span> <span class="Comment"># Removes 'in' from its surrounding list. Returns some valid pointer into the</span> <span class="Comment"># rest of the list.</span> -<span class="Comment">#</span> +# <span class="Comment"># Returns null if and only if list is empty. Beware: in that case any pointers</span> <span class="Comment"># to the head are now invalid.</span> -<span class="muRecipe">recipe</span> remove-duplex [ - <span class="Constant">local-scope</span> - in:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe remove-duplex [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient <span class="Comment"># if 'in' is null, return</span> - <span class="muControl">reply-unless</span> in, in - next-node:address:duplex-list<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> - prev-node:address:duplex-list<span class="Special"> <- </span>get *in, <span class="Constant">prev:offset</span> + reply-unless <span class="Identifier">in</span>, <span class="Identifier">in</span> + next-node:address:duplex-list<span class="Special"> <- </span>get *<span class="Identifier">in</span>, next:offset + prev-node:address:duplex-list<span class="Special"> <- </span>get *<span class="Identifier">in</span>, prev:offset <span class="Comment"># null in's pointers</span> - x:address:address:duplex-list<span class="Special"> <- </span>get-address *in, <span class="Constant">next:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">0</span> - x<span class="Special"> <- </span>get-address *in, <span class="Constant">prev:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + x:address:address:duplex-list<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, next:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + x<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, prev:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { <span class="Comment"># if next-node is not null</span> - <span class="muControl">break-unless</span> next-node + break-unless next-node <span class="Comment"># next-node.prev = prev-node</span> - x<span class="Special"> <- </span>get-address *next-node, <span class="Constant">prev:offset</span> - *x<span class="Special"> <- </span>copy prev-node - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> + x<span class="Special"> <- </span>get-address *next-node, prev:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> prev-node + } + { <span class="Comment"># if prev-node is not null</span> - <span class="muControl">break-unless</span> prev-node + break-unless prev-node <span class="Comment"># prev-node.next = next-node</span> - x<span class="Special"> <- </span>get-address *prev-node, <span class="Constant">next:offset</span> - *x<span class="Special"> <- </span>copy next-node - <span class="muControl">reply</span> prev-node - <span class="Delimiter">}</span> - <span class="muControl">reply</span> next-node + x<span class="Special"> <- </span>get-address *prev-node, next:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> next-node + reply prev-node + } + reply next-node ] -<span class="muScenario">scenario</span> removing-from-duplex-list [ +scenario removing-from-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">1</span>:address:duplex-list <span class="Comment"># 2 points at second element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span> + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to head of list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list <span class="Comment"># 2 points at second element</span> + 2:address:duplex-list<span class="Special"> <- </span>remove-duplex 2:address:duplex-list + 3:boolean<span class="Special"> <- </span>equal 2:address:duplex-list, 0 <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 1:address:duplex-list + 4:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 5:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 6:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 7:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 8:boolean<span class="Special"> <- </span>equal 1:address:duplex-list, 2:address:duplex-list ] 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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next, skipping deleted element</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no more elements</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># prev of final element</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># remove returned non-null</span> + 4<span class="Special"> <- </span>5 <span class="Comment"># scanning next, skipping deleted element</span> + 5<span class="Special"> <- </span>3 + 6<span class="Special"> <- </span>0 <span class="Comment"># no more elements</span> + 7<span class="Special"> <- </span>5 <span class="Comment"># prev of final element</span> + 8<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> ] ] -<span class="muScenario">scenario</span> removing-from-start-of-duplex-list [ +scenario removing-from-start-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to head of list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 1:address:duplex-list <span class="Comment"># removing from head? return value matters.</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>remove-duplex 1:address:duplex-list <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 1:address:duplex-list + 3:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 4:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 5:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 6:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 7:boolean<span class="Special"> <- </span>equal 1:address:duplex-list, 2:address:duplex-list ] 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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no more elements</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># prev of final element</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 3<span class="Special"> <- </span>4 <span class="Comment"># scanning next, skipping deleted element</span> + 4<span class="Special"> <- </span>3 + 5<span class="Special"> <- </span>0 <span class="Comment"># no more elements</span> + 6<span class="Special"> <- </span>4 <span class="Comment"># prev of final element</span> + 7<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> ] ] -<span class="muScenario">scenario</span> removing-from-end-of-duplex-list [ +scenario removing-from-end-of-duplex-list [ run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to head of list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to head of list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 4, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 5, 1:address:duplex-list <span class="Comment"># delete last element</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span> + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>remove-duplex 2:address:duplex-list + 3:boolean<span class="Special"> <- </span>equal 2:address:duplex-list, 0 <span class="Comment"># check structure like before</span> - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list - <span class="Constant">4</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">5</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">6</span>:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">7</span>:number<span class="Special"> <- </span>first-duplex <span class="Constant">2</span>:address:duplex-list - <span class="Constant">8</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 1:address:duplex-list + 4:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 5:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 6:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>prev-duplex 2:address:duplex-list + 7:number<span class="Special"> <- </span>first-duplex 2:address:duplex-list + 8:boolean<span class="Special"> <- </span>equal 1:address:duplex-list, 2:address:duplex-list + ] + memory-should-contain [ + 3<span class="Special"> <- </span>0 <span class="Comment"># remove returned non-null</span> + 4<span class="Special"> <- </span>5 <span class="Comment"># scanning next, skipping deleted element</span> + 5<span class="Special"> <- </span>4 + 6<span class="Special"> <- </span>0 <span class="Comment"># no more elements</span> + 7<span class="Special"> <- </span>5 <span class="Comment"># prev of final element</span> + 8<span class="Special"> <- </span>1 <span class="Comment"># list back at start</span> + ] +] + +scenario removing-from-singleton-list [ + run [ + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to singleton list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 3, 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>remove-duplex 1:address:duplex-list + 3:address:duplex-list<span class="Special"> <- </span>get *1:address:duplex-list, next:offset + 4:address:duplex-list<span class="Special"> <- </span>get *1:address:duplex-list, prev:offset + ] + memory-should-contain [ + 2<span class="Special"> <- </span>0 <span class="Comment"># remove returned null</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># removed node is also detached</span> + 4<span class="Special"> <- </span>0 + ] +] + +<span class="Comment"># l:address:duplex-list <- remove-duplex-between start:address:duplex-list, end:address:duplex-list</span> +<span class="Comment"># Remove values between 'start' and 'end' (both exclusive). Returns some valid</span> +<span class="Comment"># pointer into the rest of the list.</span> +<span class="Comment"># Also clear pointers back out from start/end for hygiene.</span> +recipe remove-duplex-between [ + <span class="Underlined">local</span>-scope + start:address:duplex-list<span class="Special"> <- </span>next-ingredient + end:address:duplex-list<span class="Special"> <- </span>next-ingredient + reply-unless start, start + <span class="Comment"># start->next->prev = 0</span> + <span class="Comment"># start->next = end</span> + next:address:address:duplex-list<span class="Special"> <- </span>get-address *start, next:offset + nothing-to-<span class="Identifier">delete</span>?:boolean<span class="Special"> <- </span>equal *next, end + reply-if nothing-to-<span class="Identifier">delete</span>?, start + prev:address:address:duplex-list<span class="Special"> <- </span>get-address **next, prev:offset + *prev<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + *next<span class="Special"> <- </span><span class="Identifier">copy</span> end + reply-unless end, start + <span class="Comment"># end->prev->next = 0</span> + <span class="Comment"># end->prev = start</span> + prev<span class="Special"> <- </span>get-address *end, prev:offset + next<span class="Special"> <- </span>get-address **prev, next:offset + *next<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + *prev<span class="Special"> <- </span><span class="Identifier">copy</span> start + reply start +] + +scenario remove-range [ + <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to singleton list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 18, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 17, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 16, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 15, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 14, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 13, 1:address:duplex-list + run [ + <span class="Comment"># delete 16 onwards</span> + <span class="Comment"># first pointer: to the third element</span> + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + remove-duplex-between 2:address:duplex-list, 0 + <span class="Comment"># now check the list</span> + 4:number<span class="Special"> <- </span>get *1:address:duplex-list, value:offset + 5:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + 6:number<span class="Special"> <- </span>get *5:address:duplex-list, value:offset + 7:address:duplex-list<span class="Special"> <- </span>next-duplex 5:address:duplex-list + 8:number<span class="Special"> <- </span>get *7:address:duplex-list, value:offset + 9:address:duplex-list<span class="Special"> <- </span>next-duplex 7:address:duplex-list + ] + memory-should-contain [ + 4<span class="Special"> <- </span>13 + 6<span class="Special"> <- </span>14 + 8<span class="Special"> <- </span>15 + 9<span class="Special"> <- </span>0 + ] +] + +scenario remove-range-to-end [ + <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to singleton list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 18, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 17, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 16, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 15, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 14, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 13, 1:address:duplex-list + run [ + <span class="Comment"># delete 15, 16 and 17</span> + <span class="Comment"># first pointer: to the third element</span> + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + <span class="Comment"># second pointer: to the fifth element</span> + 3:address:duplex-list<span class="Special"> <- </span>next-duplex 2:address:duplex-list + 3:address:duplex-list<span class="Special"> <- </span>next-duplex 3:address:duplex-list + 3:address:duplex-list<span class="Special"> <- </span>next-duplex 3:address:duplex-list + 3:address:duplex-list<span class="Special"> <- </span>next-duplex 3:address:duplex-list + remove-duplex-between 2:address:duplex-list, 3:address:duplex-list + <span class="Comment"># now check the list</span> + 4:number<span class="Special"> <- </span>get *1:address:duplex-list, value:offset + 5:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + 6:number<span class="Special"> <- </span>get *5:address:duplex-list, value:offset + 7:address:duplex-list<span class="Special"> <- </span>next-duplex 5:address:duplex-list + 8:number<span class="Special"> <- </span>get *7:address:duplex-list, value:offset + 9:address:duplex-list<span class="Special"> <- </span>next-duplex 7:address:duplex-list ] 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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next, skipping deleted element</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no more elements</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># prev of final element</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># list back at start</span> + 4<span class="Special"> <- </span>13 + 6<span class="Special"> <- </span>14 + 8<span class="Special"> <- </span>18 + 9<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> removing-from-singleton-list [ +scenario remove-range-empty [ + <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span> + 1:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> 0 <span class="Comment"># 1 points to singleton list</span> + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 14, 1:address:duplex-list + 1:address:duplex-list<span class="Special"> <- </span>push-duplex 13, 1:address:duplex-list run [ - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># 1 points to singleton list</span> - <span class="Constant">1</span>:address:duplex-list<span class="Special"> <- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list - <span class="Constant">2</span>:address:duplex-list<span class="Special"> <- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list - <span class="Constant">3</span>:address:duplex-list<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">next:offset</span> - <span class="Constant">4</span>:address:duplex-list<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">prev:offset</span> + <span class="Comment"># delete 16 onwards</span> + <span class="Comment"># first pointer: to the third element</span> + 2:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + remove-duplex-between 1:address:duplex-list, 2:address:duplex-list + <span class="Comment"># now check the list</span> + 4:number<span class="Special"> <- </span>get *1:address:duplex-list, value:offset + 5:address:duplex-list<span class="Special"> <- </span>next-duplex 1:address:duplex-list + 6:number<span class="Special"> <- </span>get *5:address:duplex-list, value:offset + 7:address:duplex-list<span class="Special"> <- </span>next-duplex 5:address:duplex-list ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># remove returned null</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># removed node is also detached</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> + 4<span class="Special"> <- </span>13 + 6<span class="Special"> <- </span>14 + 7<span class="Special"> <- </span>0 ] ] + +<span class="Comment"># l:address:duplex-list <- insert-duplex-range in:address:duplex-list, new:address:duplex-list</span> +<span class="Comment"># Inserts list beginning at 'new' after 'in'. Returns some pointer into the list.</span> +recipe insert-duplex-range [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + start:address:duplex-list<span class="Special"> <- </span>next-ingredient + reply-unless <span class="Identifier">in</span>, <span class="Identifier">in</span> + reply-unless start, <span class="Identifier">in</span> + end:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> start + { + next:address:duplex-list<span class="Special"> <- </span>next-duplex end + break-unless next + end<span class="Special"> <- </span><span class="Identifier">copy</span> next + loop + } + next:address:duplex-list<span class="Special"> <- </span>next-duplex <span class="Identifier">in</span> + dest:address:address:duplex-list<span class="Special"> <- </span>get-address *end, next:offset + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> next + { + break-unless next + dest<span class="Special"> <- </span>get-address *next, prev:offset + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> end + } + dest<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, next:offset + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> start + dest<span class="Special"> <- </span>get-address *start, prev:offset + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + reply <span class="Identifier">in</span> +] + +recipe <span class="Identifier">append</span>-duplex [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + <span class="Identifier">new</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + <span class="Identifier">last</span>:address:duplex-list<span class="Special"> <- </span><span class="Identifier">last</span>-duplex <span class="Identifier">in</span> + dest:address:address:duplex-list<span class="Special"> <- </span>get-address *<span class="Identifier">last</span>, next:offset + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">new</span> + reply-unless <span class="Identifier">new</span>, <span class="Identifier">in</span>/same-as-ingredient:0 + dest<span class="Special"> <- </span>get-address *<span class="Identifier">new</span>, prev:offset + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">last</span> + reply <span class="Identifier">in</span>/same-as-ingredient:0 +] + +recipe <span class="Identifier">last</span>-duplex [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:duplex-list<span class="Special"> <- </span>next-ingredient + result:address:duplex-list<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">in</span> + { + next:address:duplex-list<span class="Special"> <- </span>next-duplex result + break-unless next + result<span class="Special"> <- </span><span class="Identifier">copy</span> next + loop + } + reply result +] + +<span class="Comment"># helper for debugging</span> +recipe dump-duplex-from [ + <span class="Underlined">local</span>-scope + x:address:duplex-list<span class="Special"> <- </span>next-ingredient + $<span class="Identifier">print</span> x, [: ] + { + break-unless x + c:character<span class="Special"> <- </span>get *x, value:offset + $<span class="Identifier">print</span> c, [ ] + x<span class="Special"> <- </span>next-duplex x + { + <span class="Identifier">is</span>-newline?:boolean<span class="Special"> <- </span>equal c, 10/newline + break-unless <span class="Identifier">is</span>-newline? + $<span class="Identifier">print</span> 10/newline + $<span class="Identifier">print</span> x, [: ] + } + loop + } + $<span class="Identifier">print</span> 10/newline, [---], 10/newline +] </pre> </body> </html> diff --git a/html/066stream.mu.html b/html/066stream.mu.html index c6504424..a43f8090 100644 --- a/html/066stream.mu.html +++ b/html/066stream.mu.html @@ -13,11 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -32,46 +31,46 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># new type to help incrementally read strings</span> container stream [ index:number - data:address:array:character + data:address:<span class="Identifier">array</span>:character ] -<span class="muRecipe">recipe</span> new-stream [ - <span class="Constant">local-scope</span> - result:address:stream<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:array:character<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *d<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply</span> result +recipe <span class="Identifier">new</span>-stream [ + <span class="Underlined">local</span>-scope + result:address:stream<span class="Special"> <- </span><span class="Identifier">new</span> stream:<span class="Identifier">type</span> + i:address:number<span class="Special"> <- </span>get-address *result, index:offset + *i<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + d:address:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get-address *result, data:offset + *d<span class="Special"> <- </span>next-ingredient + reply result ] -<span class="muRecipe">recipe</span> rewind-stream [ - <span class="Constant">local-scope</span> - in:address:stream<span class="Special"> <- </span><span class="Constant">next-ingredient</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> - <span class="muControl">reply</span> in/same-as-arg:<span class="Constant">0</span> +recipe rewind-stream [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:stream<span class="Special"> <- </span>next-ingredient + x:address:number<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, index:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + reply <span class="Identifier">in</span>/same-as-<span class="Identifier">arg</span>:0 ] -<span class="muRecipe">recipe</span> read-line [ - <span class="Constant">local-scope</span> - in:address:stream<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - idx:address:number<span class="Special"> <- </span>get-address *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:address:array:character<span class="Special"> <- </span>string-copy 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="muControl">reply</span> result +recipe <span class="Identifier">read</span>-line [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:stream<span class="Special"> <- </span>next-ingredient + idx:address:number<span class="Special"> <- </span>get-address *<span class="Identifier">in</span>, index:offset + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *<span class="Identifier">in</span>, data:offset + next-idx:number<span class="Special"> <- </span>find-next s, 10/newline, *idx + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>string-<span class="Identifier">copy</span> s, *idx, next-idx + *idx<span class="Special"> <- </span>add next-idx, 1 <span class="Comment"># skip newline</span> + reply result ] -<span class="muRecipe">recipe</span> end-of-stream? [ - <span class="Constant">local-scope</span> - in:address:stream<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - idx:address: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> - len:number<span class="Special"> <- </span>length *s +recipe end-of-stream? [ + <span class="Underlined">local</span>-scope + <span class="Identifier">in</span>:address:stream<span class="Special"> <- </span>next-ingredient + idx:address:number<span class="Special"> <- </span>get *<span class="Identifier">in</span>, index:offset + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get *<span class="Identifier">in</span>, data:offset + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *s result:boolean<span class="Special"> <- </span>greater-or-equal idx, len - <span class="muControl">reply</span> result + reply result ] </pre> </body> diff --git a/html/070display.cc.html b/html/070display.cc.html index f61edd06..61a6395e 100644 --- a/html/070display.cc.html +++ b/html/070display.cc.html @@ -14,12 +14,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.Identifier { color: #804000; } .Constant { color: #00a0a0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .SalientComment { color: #00ffff; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } --> </style> @@ -33,10 +32,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment">//: Take charge of the text-mode display and console.</span> -<span class="Delimiter">:(before "End Globals")</span> -<span class="Comment">// uncomment to debug console programs</span> -<span class="CommentedCode">//? ofstream LOG("log.txt");</span> - <span class="SalientComment">//:: Display management</span> <span class="Delimiter">:(before "End Globals")</span> @@ -68,7 +63,6 @@ Recipe_ordinal[<span class="Constant">"close-console"</span>] = CLOSE_ <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case CLOSE_CONSOLE: <span class="Delimiter">{</span> tb_shutdown<span class="Delimiter">();</span> -<span class="CommentedCode">//? Trace_stream->dump_layer = "all"; //? 1</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -87,6 +81,16 @@ case CLEAR_DISPLAY: <span class="Delimiter">{</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +SYNC_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_ordinal[<span class="Constant">"sync-display"</span>] = SYNC_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case SYNC_DISPLAY: <span class="Delimiter">{</span> + tb_sync<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> CLEAR_LINE_ON_DISPLAY<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> Recipe_ordinal[<span class="Constant">"clear-line-on-display"</span>] = CLEAR_LINE_ON_DISPLAY<span class="Delimiter">;</span> diff --git a/html/071print.mu.html b/html/071print.mu.html index 4da9db86..ce70d068 100644 --- a/html/071print.mu.html +++ b/html/071print.mu.html @@ -13,14 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.muScenario { color: #00af00; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -40,7 +36,7 @@ container screen [ num-columns:number cursor-row:number cursor-column:number - data:address:array:screen-cell + data:address:<span class="Identifier">array</span>:screen-cell ] container screen-cell [ @@ -48,671 +44,673 @@ container screen-cell [ color:number ] -<span class="muRecipe">recipe</span> new-fake-screen [ - <span class="Constant">local-scope</span> - result:address:screen<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><span class="Constant">next-ingredient</span> - height:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">num-rows:offset</span> - *height<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - 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> +recipe <span class="Identifier">new</span>-fake-screen [ + <span class="Underlined">local</span>-scope + result:address:screen<span class="Special"> <- </span><span class="Identifier">new</span> screen:<span class="Identifier">type</span> + width:address:number<span class="Special"> <- </span>get-address *result, num-columns:offset + *width<span class="Special"> <- </span>next-ingredient + height:address:number<span class="Special"> <- </span>get-address *result, num-rows:offset + *height<span class="Special"> <- </span>next-ingredient + row:address:number<span class="Special"> <- </span>get-address *result, cursor-row:offset + *row<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + column:address:number<span class="Special"> <- </span>get-address *result, cursor-column:offset + *column<span class="Special"> <- </span><span class="Identifier">copy</span> 0 bufsize:number<span class="Special"> <- </span>multiply *width, *height - buf:address:address: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 + buf:address:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get-address *result, data:offset + *buf<span class="Special"> <- </span><span class="Identifier">new</span> screen-cell:<span class="Identifier">type</span>, bufsize clear-screen result - <span class="muControl">reply</span> result + reply result ] -<span class="muRecipe">recipe</span> clear-screen [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe clear-screen [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc + { + break-unless sc <span class="Comment"># clear fake screen</span> - buf:address:array:screen-cell<span class="Special"> <- </span>get *sc, <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? + buf:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *sc, data:offset + <span class="Identifier">max</span>:number<span class="Special"> <- </span><span class="Identifier">length</span> *buf + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + done?:boolean<span class="Special"> <- </span>greater-or-equal i, <span class="Identifier">max</span> + break-if 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">[ ]</span> - curr-color:address:character<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> - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + curr-<span class="Identifier">content</span>:address:character<span class="Special"> <- </span>get-address *curr, contents:offset + *curr-<span class="Identifier">content</span><span class="Special"> <- </span><span class="Identifier">copy</span> [ ] + curr-color:address:character<span class="Special"> <- </span>get-address *curr, color:offset + *curr-color<span class="Special"> <- </span><span class="Identifier">copy</span> 7/white + i<span class="Special"> <- </span>add i, 1 + loop + } <span class="Comment"># reset cursor</span> - x:address:number<span class="Special"> <- </span>get-address *sc, <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 *sc, <span class="Constant">cursor-column:offset</span> - *x<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + x:address:number<span class="Special"> <- </span>get-address *sc, cursor-row:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + x<span class="Special"> <- </span>get-address *sc, cursor-column:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> clear-display - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> -] - -<span class="muRecipe">recipe</span> fake-screen-is-empty? [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply-unless</span> sc, <span class="Constant">1/true</span> - buf:address:array:screen-cell<span class="Special"> <- </span>get *sc, <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> + reply sc/same-as-ingredient:0 +] + +recipe sync-screen [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient + { + break-if sc + sync-display + } + <span class="Comment"># do nothing for fake screens</span> +] + +recipe fake-screen-<span class="Identifier">is</span>-empty? [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient + reply-unless sc, 1/true + buf:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *sc, data:offset + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *buf + { done?:boolean<span class="Special"> <- </span>greater-or-equal i, len - <span class="muControl">break-if</span> done? + break-if done? curr:screen-cell<span class="Special"> <- </span>index *buf, i - curr-contents:character<span class="Special"> <- </span>get curr, <span class="Constant">contents:offset</span> - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop-unless</span> curr-contents + curr-contents:character<span class="Special"> <- </span>get curr, contents:offset + i<span class="Special"> <- </span>add i, 1 + loop-unless curr-contents <span class="Comment"># not 0</span> - <span class="muControl">reply</span> <span class="Constant">0/false</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> <span class="Constant">1/true</span> + reply 0/false + } + reply 1/true ] -<span class="muRecipe">recipe</span> print-character [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - c:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe <span class="Identifier">print</span>-character [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient + c:character<span class="Special"> <- </span>next-ingredient + color:number, color-found?:boolean<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># default color to white</span> - <span class="muControl">break-if</span> color-found? - color<span class="Special"> <- </span>copy <span class="Constant">7/white</span> - <span class="Delimiter">}</span> - bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> + break-if color-found? + color<span class="Special"> <- </span><span class="Identifier">copy</span> 7/white + } + bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># default bg-color to black</span> - <span class="muControl">break-if</span> bg-color-found? - bg-color<span class="Special"> <- </span>copy <span class="Constant">0/black</span> - <span class="Delimiter">}</span> - trace <span class="Constant">90</span>, <span class="Constant">[print-character]</span>, c - <span class="Delimiter">{</span> + break-if bg-color-found? + bg-color<span class="Special"> <- </span><span class="Identifier">copy</span> 0/black + } + trace 90, [<span class="Identifier">print</span>-character], c + { <span class="Comment"># if x exists</span> <span class="Comment"># (handle special cases exactly like in the real screen)</span> - <span class="muControl">break-unless</span> sc - width:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-columns:offset</span> - height:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-rows:offset</span> + break-unless sc + width:number<span class="Special"> <- </span>get *sc, num-columns:offset + height:number<span class="Special"> <- </span>get *sc, num-rows:offset <span class="Comment"># if cursor is out of bounds, silently exit</span> - row:address:number<span class="Special"> <- </span>get-address *sc, <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">reply-unless</span> legal?, sc + row:address:number<span class="Special"> <- </span>get-address *sc, cursor-row:offset + legal?:boolean<span class="Special"> <- </span>greater-or-equal *row, 0 + reply-unless legal?, sc legal?<span class="Special"> <- </span>lesser-than *row, height - <span class="muControl">reply-unless</span> legal?, sc - column:address:number<span class="Special"> <- </span>get-address *sc, <span class="Constant">cursor-column:offset</span> - legal?<span class="Special"> <- </span>greater-or-equal *column, <span class="Constant">0</span> - <span class="muControl">reply-unless</span> legal?, sc + reply-unless legal?, sc + column:address:number<span class="Special"> <- </span>get-address *sc, cursor-column:offset + legal?<span class="Special"> <- </span>greater-or-equal *column, 0 + reply-unless legal?, sc legal?<span class="Special"> <- </span>lesser-than *column, width - <span class="muControl">reply-unless</span> legal?, sc + reply-unless legal?, sc <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> -<span class="CommentedCode">#? $print c, [ ], newline?, 10/newline</span> - <span class="muControl">break-unless</span> newline? - <span class="Delimiter">{</span> + { + newline?:boolean<span class="Special"> <- </span>equal c, 10/newline + break-unless newline? + { <span class="Comment"># unless cursor is already at bottom</span> - bottom:number<span class="Special"> <- </span>subtract height, <span class="Constant">1</span> + bottom:number<span class="Special"> <- </span>subtract height, 1 at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *row, bottom - <span class="muControl">break-if</span> at-bottom? + break-if 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + *column<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + *row<span class="Special"> <- </span>add *row, 1 + } + reply sc/same-as-ingredient:0 + } <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:array:screen-cell<span class="Special"> <- </span>get *sc, <span class="Constant">data:offset</span> - len:number<span class="Special"> <- </span>length *buf + buf:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *sc, data:offset + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *buf <span class="Comment"># special-case: backspace</span> - <span class="Delimiter">{</span> - backspace?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">8</span> - <span class="muControl">break-unless</span> backspace? - <span class="Delimiter">{</span> + { + backspace?:boolean<span class="Special"> <- </span>equal c, 8 + break-unless backspace? + { <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> - <span class="muControl">break-if</span> at-left? + at-left?:boolean<span class="Special"> <- </span>lesser-or-equal *column, 0 + break-if at-left? <span class="Comment"># clear previous location</span> - *column<span class="Special"> <- </span>subtract *column, <span class="Constant">1</span> - index<span class="Special"> <- </span>subtract index, <span class="Constant">1</span> + *column<span class="Special"> <- </span>subtract *column, 1 + index<span class="Special"> <- </span>subtract index, 1 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> -<span class="CommentedCode">#? $print [saving character ], c, [ to fake screen ], cursor, 10/newline</span> + cursor-contents:address:character<span class="Special"> <- </span>get-address *cursor, contents:offset + *cursor-contents<span class="Special"> <- </span><span class="Identifier">copy</span> 32/space + cursor-color:address:number<span class="Special"> <- </span>get-address *cursor, color:offset + *cursor-color<span class="Special"> <- </span><span class="Identifier">copy</span> 7/white + } + reply sc/same-as-ingredient:0 + } 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-contents:address:character<span class="Special"> <- </span>get-address *cursor, contents:offset + *cursor-contents<span class="Special"> <- </span><span class="Identifier">copy</span> c + cursor-color:address:number<span class="Special"> <- </span>get-address *cursor, color:offset + *cursor-color<span class="Special"> <- </span><span class="Identifier">copy</span> color <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> + { + right:number<span class="Special"> <- </span>subtract width, 1 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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + break-if at-right? + *column<span class="Special"> <- </span>add *column, 1 + } + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> - print-character-to-display c, color, bg-color - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + <span class="Identifier">print</span>-character-to-display c, color, bg-color + reply sc/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> print-character-at-top-left [ +scenario <span class="Identifier">print</span>-character-at-top-left [ run [ -<span class="CommentedCode">#? $start-tracing #? 3</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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> + 2:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 3:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>: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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">0</span> + 3<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 4<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 5<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 6<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> print-character-color [ +scenario <span class="Identifier">print</span>-character-color [ run [ - <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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97/a</span>, <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97/a, 1/red + 2:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 3:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>: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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># red</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">0</span> + 3<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 4<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 5<span class="Special"> <- </span>1 <span class="Comment"># red</span> + 6<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> print-backspace-character [ +scenario <span class="Identifier">print</span>-backspace-character [ run [ -<span class="CommentedCode">#? $start-tracing #? 3</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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">8</span> <span class="Comment"># backspace</span> - <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 8 <span class="Comment"># backspace</span> + 2:number<span class="Special"> <- </span>get *1:address:screen, cursor-column:offset + 3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 4:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>: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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">32</span> <span class="Comment"># space, not 'a'</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">0</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># cursor column</span> + 4<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 5<span class="Special"> <- </span>32 <span class="Comment"># space, not 'a'</span> + 6<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 7<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> print-extra-backspace-character [ +scenario <span class="Identifier">print</span>-extra-backspace-character [ run [ - <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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">8</span> <span class="Comment"># backspace</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">8</span> <span class="Comment"># backspace</span> - <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 8 <span class="Comment"># backspace</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 8 <span class="Comment"># backspace</span> + 2:number<span class="Special"> <- </span>get *1:address:screen, cursor-column:offset + 3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 4:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>: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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">32</span> <span class="Comment"># space, not 'a'</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">0</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># cursor column</span> + 4<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 5<span class="Special"> <- </span>32 <span class="Comment"># space, not 'a'</span> + 6<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 7<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> print-at-right-margin [ +scenario <span class="Identifier">print</span>-at-right-margin [ run [ - <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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">98</span> <span class="Comment"># 'b'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">99</span> <span class="Comment"># 'c'</span> - <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 2/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 98 <span class="Comment"># 'b'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 99 <span class="Comment"># 'c'</span> + 2:number<span class="Special"> <- </span>get *1:address:screen, cursor-column:offset + 3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 4:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>: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> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># width*height</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">99</span> <span class="Comment"># 'c' over 'b'</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">0</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># cursor column</span> + 4<span class="Special"> <- </span>4 <span class="Comment"># width*height</span> + 5<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 6<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 7<span class="Special"> <- </span>99 <span class="Comment"># 'c' over 'b'</span> + 8<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 9<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> print-newline-character [ +scenario <span class="Identifier">print</span>-newline-character [ run [ -<span class="CommentedCode">#? $start-tracing #? 3</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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span> - <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline + 2:number<span class="Special"> <- </span>get *1:address:screen, cursor-row:offset + 3:number<span class="Special"> <- </span>get *1:address:screen, cursor-column:offset + 4:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 5:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>: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> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">0</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># cursor column</span> + 5<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 6<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 7<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 8<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> print-newline-at-bottom-line [ +scenario <span class="Identifier">print</span>-newline-at-bottom-line [ run [ - <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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span> - <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> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline + 2:number<span class="Special"> <- </span>get *1:address:screen, cursor-row:offset + 3:number<span class="Special"> <- </span>get *1:address:screen, cursor-column:offset ] memory-should-contain [ - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># cursor column</span> ] ] -<span class="muScenario">scenario</span> print-at-bottom-right [ +scenario <span class="Identifier">print</span>-at-bottom-right [ run [ - <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">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">98</span> <span class="Comment"># 'b'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">99</span> <span class="Comment"># 'c'</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">100</span> <span class="Comment"># 'd'</span> - <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 2/width, 2/height + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 98 <span class="Comment"># 'b'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 99 <span class="Comment"># 'c'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 100 <span class="Comment"># 'd'</span> + 2:number<span class="Special"> <- </span>get *1:address:screen, cursor-row:offset + 3:number<span class="Special"> <- </span>get *1:address:screen, cursor-column:offset + 4:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 5:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>: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> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor column</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># width*height</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># unused</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># unused</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">100</span> <span class="Comment"># 'd' over 'b' and 'c' and newline</span> - <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">14</span><span class="Special"> <- </span><span class="Constant">0</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># cursor column</span> + 5<span class="Special"> <- </span>4 <span class="Comment"># width*height</span> + 6<span class="Special"> <- </span>0 <span class="Comment"># unused</span> + 7<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 8<span class="Special"> <- </span>0 <span class="Comment"># unused</span> + 9<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 10<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 11<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 12<span class="Special"> <- </span>100 <span class="Comment"># 'd' over 'b' and 'c' and newline</span> + 13<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 14<span class="Special"> <- </span>0 ] ] -<span class="muRecipe">recipe</span> clear-line [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe clear-line [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, clear line in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - width:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-columns:offset</span> - column:address:number<span class="Special"> <- </span>get-address *sc, <span class="Constant">cursor-column:offset</span> - original-column:number<span class="Special"> <- </span>copy *column + { + break-unless sc + width:number<span class="Special"> <- </span>get *sc, num-columns:offset + column:address:number<span class="Special"> <- </span>get-address *sc, cursor-column:offset + original-column:number<span class="Special"> <- </span><span class="Identifier">copy</span> *column <span class="Comment"># space over the entire line</span> -<span class="CommentedCode">#? $start-tracing #? 1</span> - <span class="Delimiter">{</span> -<span class="CommentedCode">#? $print *column, 10/newline</span> - right:number<span class="Special"> <- </span>subtract width, <span class="Constant">1</span> + { + right:number<span class="Special"> <- </span>subtract width, 1 done?:boolean<span class="Special"> <- </span>greater-or-equal *column, right - <span class="muControl">break-if</span> done? - print-character sc, <span class="Constant">[ ]</span> <span class="Comment"># implicitly updates 'column'</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + break-if done? + <span class="Identifier">print</span>-character sc, [ ] <span class="Comment"># implicitly updates 'column'</span> + loop + } <span class="Comment"># now back to where the cursor was</span> - *column<span class="Special"> <- </span>copy original-column - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + *column<span class="Special"> <- </span><span class="Identifier">copy</span> original-column + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> clear-line-on-display - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + reply sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> cursor-position [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-position [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, lookup cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - row:number<span class="Special"> <- </span>get *sc, <span class="Constant">cursor-row:offset</span> - column:number<span class="Special"> <- </span>get *sc, <span class="Constant">cursor-column:offset</span> - <span class="muControl">reply</span> row, column, sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + { + break-unless sc + row:number<span class="Special"> <- </span>get *sc, cursor-row:offset + column:number<span class="Special"> <- </span>get *sc, cursor-column:offset + reply row, column, sc/same-as-ingredient:0 + } row, column<span class="Special"> <- </span>cursor-position-on-display - <span class="muControl">reply</span> row, column, sc/same-as-ingredient:<span class="Constant">0</span> + reply row, column, sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> move-cursor [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - new-row:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - new-column:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe move-cursor [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Identifier">new</span>-row:number<span class="Special"> <- </span>next-ingredient + <span class="Identifier">new</span>-column:number<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - row:address:number<span class="Special"> <- </span>get-address *sc, <span class="Constant">cursor-row:offset</span> - *row<span class="Special"> <- </span>copy new-row - column:address:number<span class="Special"> <- </span>get-address *sc, <span class="Constant">cursor-column:offset</span> - *column<span class="Special"> <- </span>copy new-column - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + { + break-unless sc + row:address:number<span class="Special"> <- </span>get-address *sc, cursor-row:offset + *row<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-row + column:address:number<span class="Special"> <- </span>get-address *sc, cursor-column:offset + *column<span class="Special"> <- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-column + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> - move-cursor-on-display new-row, new-column - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + move-cursor-on-display <span class="Identifier">new</span>-row, <span class="Identifier">new</span>-column + reply sc/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> clear-line-erases-printed-characters [ +scenario clear-line-erases-printed-characters [ run [ -<span class="CommentedCode">#? $start-tracing #? 4</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> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height <span class="Comment"># print a character</span> - <span class="Constant">1</span>:address:screen<span class="Special"> <- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span> <span class="Comment"># 'a'</span> + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-character 1:address:screen, 97 <span class="Comment"># 'a'</span> <span class="Comment"># move cursor to start of line</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> + 1:address:screen<span class="Special"> <- </span>move-cursor 1:address:screen, 0/row, 0/column <span class="Comment"># clear line</span> - <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">3</span>:array:screen-cell<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:screen-cell + 1:address:screen<span class="Special"> <- </span>clear-line 1:address:screen + 2:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 3:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:screen-cell ] <span class="Comment"># screen should be blank</span> memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># width*height</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">7</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">7</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">7</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">7</span> - <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">7</span> - <span class="Constant">14</span><span class="Special"> <- </span><span class="Constant">0</span> - <span class="Constant">15</span><span class="Special"> <- </span><span class="Constant">7</span> + 3<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 4<span class="Special"> <- </span>0 + 5<span class="Special"> <- </span>7 + 6<span class="Special"> <- </span>0 + 7<span class="Special"> <- </span>7 + 8<span class="Special"> <- </span>0 + 9<span class="Special"> <- </span>7 + 10<span class="Special"> <- </span>0 + 11<span class="Special"> <- </span>7 + 12<span class="Special"> <- </span>0 + 13<span class="Special"> <- </span>7 + 14<span class="Special"> <- </span>0 + 15<span class="Special"> <- </span>7 ] ] -<span class="muRecipe">recipe</span> cursor-down [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-down [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - <span class="Delimiter">{</span> + { + break-unless sc + { <span class="Comment"># increment row unless it's already all the way down</span> - height:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-rows:offset</span> - row:address:number<span class="Special"> <- </span>get-address *sc, <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 - <span class="muControl">break-if</span> at-bottom? - *row<span class="Special"> <- </span>add *row, <span class="Constant">1</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + height:number<span class="Special"> <- </span>get *sc, num-rows:offset + row:address:number<span class="Special"> <- </span>get-address *sc, cursor-row:offset + <span class="Identifier">max</span>:number<span class="Special"> <- </span>subtract height, 1 + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *row, <span class="Identifier">max</span> + break-if at-bottom? + *row<span class="Special"> <- </span>add *row, 1 + } + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> move-cursor-down-on-display - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + reply sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> cursor-up [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-up [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - <span class="Delimiter">{</span> + { + break-unless sc + { <span class="Comment"># decrement row unless it's already all the way up</span> - row:address:number<span class="Special"> <- </span>get-address *sc, <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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + row:address:number<span class="Special"> <- </span>get-address *sc, cursor-row:offset + at-top?:boolean<span class="Special"> <- </span>lesser-or-equal *row, 0 + break-if at-top? + *row<span class="Special"> <- </span>subtract *row, 1 + } + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> move-cursor-up-on-display - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + reply sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> cursor-right [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-right [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - <span class="Delimiter">{</span> + { + break-unless sc + { <span class="Comment"># increment column unless it's already all the way to the right</span> - width:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-columns:offset</span> - column:address:number<span class="Special"> <- </span>get-address *sc, <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 - <span class="muControl">break-if</span> at-bottom? - *column<span class="Special"> <- </span>add *column, <span class="Constant">1</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + width:number<span class="Special"> <- </span>get *sc, num-columns:offset + column:address:number<span class="Special"> <- </span>get-address *sc, cursor-column:offset + <span class="Identifier">max</span>:number<span class="Special"> <- </span>subtract width, 1 + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal *column, <span class="Identifier">max</span> + break-if at-bottom? + *column<span class="Special"> <- </span>add *column, 1 + } + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> move-cursor-right-on-display - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + reply sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> cursor-left [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-left [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - <span class="Delimiter">{</span> + { + break-unless sc + { <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 *sc, <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> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> - <span class="Delimiter">}</span> + column:address:number<span class="Special"> <- </span>get-address *sc, cursor-column:offset + at-top?:boolean<span class="Special"> <- </span>lesser-or-equal *column, 0 + break-if at-top? + *column<span class="Special"> <- </span>subtract *column, 1 + } + reply sc/same-as-ingredient:0 + } <span class="Comment"># otherwise, real screen</span> move-cursor-left-on-display - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + reply sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> cursor-to-start-of-line [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-to-start-of-line [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient row:number, _, sc<span class="Special"> <- </span>cursor-position sc - column:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + column:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 sc<span class="Special"> <- </span>move-cursor sc, row, column - <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span> + reply sc/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> cursor-to-next-line [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe cursor-to-next-line [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient screen<span class="Special"> <- </span>cursor-down screen screen<span class="Special"> <- </span>cursor-to-start-of-line screen - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> + reply screen/same-as-ingredient:0 ] -<span class="muRecipe">recipe</span> screen-width [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe screen-width [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - width:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-columns:offset</span> - <span class="muControl">reply</span> width - <span class="Delimiter">}</span> + { + break-unless sc + width:number<span class="Special"> <- </span>get *sc, num-columns:offset + reply width + } <span class="Comment"># otherwise, real screen</span> width:number<span class="Special"> <- </span>display-width - <span class="muControl">reply</span> width + reply width ] -<span class="muRecipe">recipe</span> screen-height [ - <span class="Constant">local-scope</span> - sc:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe screen-height [ + <span class="Underlined">local</span>-scope + sc:address:screen<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists, move cursor in fake screen</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> sc - height:number<span class="Special"> <- </span>get *sc, <span class="Constant">num-rows:offset</span> - <span class="muControl">reply</span> height - <span class="Delimiter">}</span> + { + break-unless sc + height:number<span class="Special"> <- </span>get *sc, num-rows:offset + reply height + } <span class="Comment"># otherwise, real screen</span> height:number<span class="Special"> <- </span>display-height - <span class="muControl">reply</span> height + reply height ] -<span class="muRecipe">recipe</span> hide-cursor [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe hide-cursor [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists (not real display), do nothing</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">reply</span> screen - <span class="Delimiter">}</span> + { + break-unless screen + reply screen + } <span class="Comment"># otherwise, real screen</span> hide-cursor-on-display - <span class="muControl">reply</span> screen + reply screen ] -<span class="muRecipe">recipe</span> show-cursor [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe show-cursor [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists (not real display), do nothing</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">reply</span> screen - <span class="Delimiter">}</span> + { + break-unless screen + reply screen + } <span class="Comment"># otherwise, real screen</span> show-cursor-on-display - <span class="muControl">reply</span> screen + reply screen ] -<span class="muRecipe">recipe</span> hide-screen [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe hide-screen [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists (not real display), do nothing</span> <span class="Comment"># todo: help test this</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">reply</span> screen - <span class="Delimiter">}</span> + { + break-unless screen + reply screen + } <span class="Comment"># otherwise, real screen</span> hide-display - <span class="muControl">reply</span> screen + reply screen ] -<span class="muRecipe">recipe</span> show-screen [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe show-screen [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient <span class="Comment"># if x exists (not real display), do nothing</span> <span class="Comment"># todo: help test this</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">reply</span> screen - <span class="Delimiter">}</span> + { + break-unless screen + reply screen + } <span class="Comment"># otherwise, real screen</span> show-display - <span class="muControl">reply</span> screen + reply screen ] -<span class="muRecipe">recipe</span> print-string [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe <span class="Identifier">print</span>-string [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + color:number, color-found?:boolean<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># default color to white</span> - <span class="muControl">break-if</span> color-found? - color<span class="Special"> <- </span>copy <span class="Constant">7/white</span> - <span class="Delimiter">}</span> - bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> + break-if color-found? + color<span class="Special"> <- </span><span class="Identifier">copy</span> 7/white + } + bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># default bg-color to black</span> - <span class="muControl">break-if</span> bg-color-found? - bg-color<span class="Special"> <- </span>copy <span class="Constant">0/black</span> - <span class="Delimiter">}</span> - len:number<span class="Special"> <- </span>length *s - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> + break-if bg-color-found? + bg-color<span class="Special"> <- </span><span class="Identifier">copy</span> 0/black + } + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *s + i:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { done?:boolean<span class="Special"> <- </span>greater-or-equal i, len - <span class="muControl">break-if</span> done? + break-if done? c:character<span class="Special"> <- </span>index *s, i - print-character screen, c, color, bg-color - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> + <span class="Identifier">print</span>-character screen, c, color, bg-color + i<span class="Special"> <- </span>add i, 1 + loop + } + reply screen/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> print-string-stops-at-right-margin [ +scenario <span class="Identifier">print</span>-string-stops-at-right-margin [ run [ - <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-string <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 + 1:address:screen<span class="Special"> <- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height + 2:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [abcd] + 1:address:screen<span class="Special"> <- </span><span class="Identifier">print</span>-string 1:address:screen, 2:address:<span class="Identifier">array</span>:character + 3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span>get *1:address:screen, data:offset + 4:<span class="Identifier">array</span>:screen-cell<span class="Special"> <- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>: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> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">98</span> <span class="Comment"># 'b'</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">9</span><span class="Special"> <- </span><span class="Constant">100</span> <span class="Comment"># 'd' overwrites 'c'</span> - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">7</span> <span class="Comment"># white</span> - <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># unused</span> + 4<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 5<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 6<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 7<span class="Special"> <- </span>98 <span class="Comment"># 'b'</span> + 8<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 9<span class="Special"> <- </span>100 <span class="Comment"># 'd' overwrites 'c'</span> + 10<span class="Special"> <- </span>7 <span class="Comment"># white</span> + 11<span class="Special"> <- </span>0 <span class="Comment"># unused</span> ] ] -<span class="muRecipe">recipe</span> print-integer [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - n:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe <span class="Identifier">print</span>-integer [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient + n:number<span class="Special"> <- </span>next-ingredient + color:number, color-found?:boolean<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># default color to white</span> - <span class="muControl">break-if</span> color-found? - color<span class="Special"> <- </span>copy <span class="Constant">7/white</span> - <span class="Delimiter">}</span> - bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> + break-if color-found? + color<span class="Special"> <- </span><span class="Identifier">copy</span> 7/white + } + bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># default bg-color to black</span> - <span class="muControl">break-if</span> bg-color-found? - bg-color<span class="Special"> <- </span>copy <span class="Constant">0/black</span> - <span class="Delimiter">}</span> + break-if bg-color-found? + bg-color<span class="Special"> <- </span><span class="Identifier">copy</span> 0/black + } <span class="Comment"># todo: other bases besides decimal</span> - s:address:array:character<span class="Special"> <- </span>integer-to-decimal-string n - print-string screen, s, color, bg-color - <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>integer-to-decimal-string n + <span class="Identifier">print</span>-string screen, s, color, bg-color + reply screen/same-as-ingredient:0 ] </pre> </body> diff --git a/html/073scenario_screen_test.mu.html b/html/073scenario_screen_test.mu.html index aa6f42b9..556fe973 100644 --- a/html/073scenario_screen_test.mu.html +++ b/html/073scenario_screen_test.mu.html @@ -13,10 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -30,31 +29,31 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># To check our support for screens in scenarios, rewrite tests from print.mu</span> -<span class="muScenario">scenario</span> print-character-at-top-left-2 [ - assume-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span> +scenario <span class="Identifier">print</span>-character-at-top-left-2 [ + <span class="Identifier">assume</span>-screen 3/width, 2/height run [ - screen:address<span class="Special"> <- </span>print-character screen:address, <span class="Constant">97/a</span> + screen:address<span class="Special"> <- </span><span class="Identifier">print</span>-character screen:address, 97/a ] screen-should-contain [ - <span class="Constant"> .a .</span> - <span class="Constant"> . .</span> + .a . + . . ] ] -<span class="muScenario">scenario</span> clear-line-erases-printed-characters-2 [ - assume-screen <span class="Constant">5/width</span>, <span class="Constant">3/height</span> +scenario clear-line-erases-printed-characters-2 [ + <span class="Identifier">assume</span>-screen 5/width, 3/height run [ <span class="Comment"># print a character</span> - screen:address<span class="Special"> <- </span>print-character screen:address, <span class="Constant">97/a</span> + screen:address<span class="Special"> <- </span><span class="Identifier">print</span>-character screen:address, 97/a <span class="Comment"># move cursor to start of line</span> - screen:address<span class="Special"> <- </span>move-cursor screen:address, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> + screen:address<span class="Special"> <- </span>move-cursor screen:address, 0/row, 0/column <span class="Comment"># clear line</span> screen:address<span class="Special"> <- </span>clear-line screen:address ] screen-should-contain [ - <span class="Constant"> . .</span> - <span class="Constant"> . .</span> - <span class="Constant"> . .</span> + . . + . . + . . ] ] </pre> diff --git a/html/074console.mu.html b/html/074console.mu.html index 04b12ea8..f2eb5552 100644 --- a/html/074console.mu.html +++ b/html/074console.mu.html @@ -13,12 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -42,7 +40,7 @@ exclusive-container event [ ] container touch-event [ - type:number + <span class="Identifier">type</span>:number row:number column:number ] @@ -54,94 +52,94 @@ container resize-event [ container console [ index:number - data:address:array:event + data:address:<span class="Identifier">array</span>:event ] -<span class="muRecipe">recipe</span> new-fake-console [ - <span class="Constant">local-scope</span> - result:address:console<span class="Special"> <- </span>new <span class="Constant">console:type</span> - buf:address:address:array:character<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> - *buf<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - idx:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">index:offset</span> - *idx<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="muControl">reply</span> result +recipe <span class="Identifier">new</span>-fake-console [ + <span class="Underlined">local</span>-scope + result:address:console<span class="Special"> <- </span><span class="Identifier">new</span> console:<span class="Identifier">type</span> + buf:address:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>get-address *result, data:offset + *buf<span class="Special"> <- </span>next-ingredient + idx:address:number<span class="Special"> <- </span>get-address *result, index:offset + *idx<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + reply result ] -<span class="muRecipe">recipe</span> read-event [ - <span class="Constant">local-scope</span> - x:address:console<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> x - idx:address:number<span class="Special"> <- </span>get-address *x, <span class="Constant">index:offset</span> - buf:address:array:event<span class="Special"> <- </span>get *x, <span class="Constant">data:offset</span> - <span class="Delimiter">{</span> - max:number<span class="Special"> <- </span>length *buf - done?:boolean<span class="Special"> <- </span>greater-or-equal *idx, max - <span class="muControl">break-unless</span> done? - dummy:address:event<span class="Special"> <- </span>new <span class="Constant">event:type</span> - <span class="muControl">reply</span> *dummy, x/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">1/quit</span> - <span class="Delimiter">}</span> +recipe <span class="Identifier">read</span>-event [ + <span class="Underlined">local</span>-scope + x:address:console<span class="Special"> <- </span>next-ingredient + { + break-unless x + idx:address:number<span class="Special"> <- </span>get-address *x, index:offset + buf:address:<span class="Identifier">array</span>:event<span class="Special"> <- </span>get *x, data:offset + { + <span class="Identifier">max</span>:number<span class="Special"> <- </span><span class="Identifier">length</span> *buf + done?:boolean<span class="Special"> <- </span>greater-or-equal *idx, <span class="Identifier">max</span> + break-unless done? + dummy:address:event<span class="Special"> <- </span><span class="Identifier">new</span> event:<span class="Identifier">type</span> + reply *dummy, x/same-as-ingredient:0, 1/found, 1/<span class="Identifier">quit</span> + } result:event<span class="Special"> <- </span>index *buf, *idx - *idx<span class="Special"> <- </span>add *idx, <span class="Constant">1</span> - <span class="muControl">reply</span> result, x/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> - <span class="Delimiter">}</span> + *idx<span class="Special"> <- </span>add *idx, 1 + reply result, x/same-as-ingredient:0, 1/found, 0/<span class="Identifier">quit</span> + } switch <span class="Comment"># real event source is infrequent; avoid polling it too much</span> result:event, found?:boolean<span class="Special"> <- </span>check-for-interaction - <span class="muControl">reply</span> result, x/same-as-ingredient:<span class="Constant">0</span>, found?, <span class="Constant">0/quit</span> + reply result, x/same-as-ingredient:0, found?, 0/<span class="Identifier">quit</span> ] <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">recipe</span> read-key [ - <span class="Constant">local-scope</span> - console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - x:event, console, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-event console - <span class="muControl">reply-if</span> quit?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit? - <span class="muControl">reply-unless</span> found?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit? - c:address:character<span class="Special"> <- </span>maybe-convert x, <span class="Constant">text:variant</span> - <span class="muControl">reply-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">reply</span> *c, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> +recipe <span class="Identifier">read</span>-key [ + <span class="Underlined">local</span>-scope + console:address<span class="Special"> <- </span>next-ingredient + x:event, console, found?:boolean, <span class="Identifier">quit</span>?:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-event console + reply-if <span class="Identifier">quit</span>?, 0, console/same-as-ingredient:0, found?, <span class="Identifier">quit</span>? + reply-unless found?, 0, console/same-as-ingredient:0, found?, <span class="Identifier">quit</span>? + c:address:character<span class="Special"> <- </span>maybe-convert x, text:variant + reply-unless c, 0, console/same-as-ingredient:0, 0/found, 0/<span class="Identifier">quit</span> + reply *c, console/same-as-ingredient:0, 1/found, 0/<span class="Identifier">quit</span> ] -<span class="muRecipe">recipe</span> send-keys-to-channel [ - <span class="Constant">local-scope</span> - console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - c:character, console, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-key console - <span class="muControl">loop-unless</span> found? - <span class="muControl">break-if</span> quit? - assert c, <span class="Constant">[invalid event, expected text]</span> - screen<span class="Special"> <- </span>print-character screen, c - chan<span class="Special"> <- </span>write chan, c - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> console/same-as-ingredient:<span class="Constant">0</span>, chan/same-as-ingredient:<span class="Constant">1</span>, screen/same-as-ingredient:<span class="Constant">2</span> +recipe send-keys-to-channel [ + <span class="Underlined">local</span>-scope + console:address<span class="Special"> <- </span>next-ingredient + chan:address:channel<span class="Special"> <- </span>next-ingredient + screen:address<span class="Special"> <- </span>next-ingredient + { + c:character, console, found?:boolean, <span class="Identifier">quit</span>?:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-key console + loop-unless found? + break-if <span class="Identifier">quit</span>? + <span class="Identifier">assert</span> c, [invalid event, expected text] + screen<span class="Special"> <- </span><span class="Identifier">print</span>-character screen, c + chan<span class="Special"> <- </span><span class="Identifier">write</span> chan, c + loop + } + reply console/same-as-ingredient:0, chan/same-as-ingredient:1, screen/same-as-ingredient:2 ] -<span class="muRecipe">recipe</span> wait-for-event [ - <span class="Constant">local-scope</span> - console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - _, console, found?:boolean<span class="Special"> <- </span>read-event console - <span class="muControl">loop-unless</span> found? - <span class="Delimiter">}</span> - <span class="muControl">reply</span> console/same-as-ingredient:<span class="Constant">0</span> +recipe wait-for-event [ + <span class="Underlined">local</span>-scope + console:address<span class="Special"> <- </span>next-ingredient + { + _, console, found?:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-event console + loop-unless found? + } + reply console/same-as-ingredient:0 ] <span class="Comment"># use this helper to skip rendering if there's lots of other events queued up</span> -<span class="muRecipe">recipe</span> has-more-events? [ - <span class="Constant">local-scope</span> - console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> console +recipe <span class="Identifier">has</span>-more-events? [ + <span class="Underlined">local</span>-scope + console:address<span class="Special"> <- </span>next-ingredient + { + break-unless console <span class="Comment"># fake consoles should be plenty fast; never skip</span> - <span class="muControl">reply</span> <span class="Constant">0/false</span> - <span class="Delimiter">}</span> + reply 0/false + } result:boolean<span class="Special"> <- </span>interactions-left? - <span class="muControl">reply</span> result + reply result ] </pre> </body> diff --git a/html/075scenario_console.cc.html b/html/075scenario_console.cc.html index 16b68e11..c578c2a8 100644 --- a/html/075scenario_console.cc.html +++ b/html/075scenario_console.cc.html @@ -14,7 +14,6 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -79,12 +78,10 @@ ASSUME_CONSOLE<span class="Delimiter">,</span> Recipe_ordinal[<span class="Constant">"assume-console"</span>] = ASSUME_CONSOLE<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case ASSUME_CONSOLE: <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "aaa: " << current_instruction().ingredients.at(0).name << '\n'; //? 2</span> <span class="Comment">// create a temporary recipe just for parsing; it won't contain valid instructions</span> istringstream in<span class="Delimiter">(</span><span class="Constant">"["</span> + current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name + <span class="Constant">"]"</span><span class="Delimiter">);</span> - recipe r = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + recipe r = slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">);</span> long long int num_events = count_events<span class="Delimiter">(</span>r<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "fff: " << num_events << '\n'; //? 3</span> <span class="Comment">// initialize the events</span> long long int size = num_events*size_of_event<span class="Delimiter">()</span> + <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span> @@ -98,13 +95,23 @@ case ASSUME_CONSOLE: <span class="Delimiter">{</span> Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'type' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">0</span>] = TB_KEY_MOUSE_LEFT<span class="Delimiter">;</span> Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'row' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">1</span>] = to_integer<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span> Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">offset of 'column' in 'mouse-event'</span><span class="Comment">*/</span><span class="Constant">2</span>] = to_integer<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "AA left click: " << Memory[Current_routine->alloc+2] << ' ' << Memory[Current_routine->alloc+3] << '\n'; //? 1</span> Current_routine<span class="Delimiter">-></span>alloc += size_of_event<span class="Delimiter">();</span> <span class="Delimiter">}</span> else if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"press"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - Memory[Current_routine<span class="Delimiter">-></span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'keycode' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> - Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>] = to_integer<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "AA press: " << Memory[Current_routine->alloc+1] << '\n'; //? 3</span> + string key = curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>key<span class="Delimiter">))</span> + Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>] = to_integer<span class="Delimiter">(</span>key<span class="Delimiter">);</span> + else if <span class="Delimiter">(</span>Key<span class="Delimiter">.</span>find<span class="Delimiter">(</span>key<span class="Delimiter">)</span> != Key<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>] = Key[key]<span class="Delimiter">;</span> + else + raise << <span class="Constant">"assume-console: can't press "</span> << key << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Constant">1</span>] < <span class="Constant">256</span><span class="Delimiter">)</span> + <span class="Comment">// these keys are in ascii</span> + Memory[Current_routine<span class="Delimiter">-></span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'text' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">;</span> + else <span class="Delimiter">{</span> + <span class="Comment">// distinguish from unicode</span> + Memory[Current_routine<span class="Delimiter">-></span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'keycode' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-></span>alloc += size_of_event<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Comment">// End Event Handlers</span> @@ -115,13 +122,11 @@ case ASSUME_CONSOLE: <span class="Delimiter">{</span> const char* raw_contents = contents<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> long long int num_keyboard_events = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> long long int curr = <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "AAA: " << num_keyboard_events << '\n'; //? 1</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < num_keyboard_events<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> Memory[Current_routine<span class="Delimiter">-></span>alloc] = <span class="Comment">/*</span><span class="Comment">tag for 'text' variant of 'event' exclusive-container</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">;</span> uint32_t 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> -<span class="CommentedCode">//? cerr << "AA keyboard: " << curr_character << '\n'; //? 3</span> Memory[Current_routine<span class="Delimiter">-></span>alloc+<span class="Comment">/*</span><span class="Comment">skip exclusive container tag</span><span class="Comment">*/</span><span class="Constant">1</span>] = curr_character<span class="Delimiter">;</span> curr += tb_utf8_char_length<span class="Delimiter">(</span>raw_contents[curr]<span class="Delimiter">);</span> Current_routine<span class="Delimiter">-></span>alloc += size_of_event<span class="Delimiter">();</span> @@ -133,24 +138,80 @@ case ASSUME_CONSOLE: <span class="Delimiter">{</span> ensure_space<span class="Delimiter">(</span>size_of_events<span class="Delimiter">());</span> Memory[CONSOLE] = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> Current_routine<span class="Delimiter">-></span>alloc += size_of_events<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << "writing " << event_data_address << " to location " << Memory[CONSOLE]+1 << '\n'; //? 1</span> Memory[Memory[CONSOLE]+<span class="Comment">/*</span><span class="Comment">offset of 'data' in container 'events'</span><span class="Comment">*/</span><span class="Constant">1</span>] = event_data_address<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << Memory[Memory[CONSOLE]+1] << '\n'; //? 1</span> -<span class="CommentedCode">//? cerr << "alloc now " << Current_routine->alloc << '\n'; //? 1</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Globals")</span> +map<string<span class="Delimiter">,</span> long long int> Key<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End One-time Setup")</span> +initialize_key_names<span class="Delimiter">();</span> +<span class="Delimiter">:(code)</span> +void initialize_key_names<span class="Delimiter">()</span> <span class="Delimiter">{</span> + Key[<span class="Constant">"F1"</span>] = TB_KEY_F1<span class="Delimiter">;</span> + Key[<span class="Constant">"F2"</span>] = TB_KEY_F2<span class="Delimiter">;</span> + Key[<span class="Constant">"F3"</span>] = TB_KEY_F3<span class="Delimiter">;</span> + Key[<span class="Constant">"F4"</span>] = TB_KEY_F4<span class="Delimiter">;</span> + Key[<span class="Constant">"F5"</span>] = TB_KEY_F5<span class="Delimiter">;</span> + Key[<span class="Constant">"F6"</span>] = TB_KEY_F6<span class="Delimiter">;</span> + Key[<span class="Constant">"F7"</span>] = TB_KEY_F7<span class="Delimiter">;</span> + Key[<span class="Constant">"F8"</span>] = TB_KEY_F8<span class="Delimiter">;</span> + Key[<span class="Constant">"F9"</span>] = TB_KEY_F9<span class="Delimiter">;</span> + Key[<span class="Constant">"F10"</span>] = TB_KEY_F10<span class="Delimiter">;</span> + Key[<span class="Constant">"F11"</span>] = TB_KEY_F11<span class="Delimiter">;</span> + Key[<span class="Constant">"F12"</span>] = TB_KEY_F12<span class="Delimiter">;</span> + Key[<span class="Constant">"insert"</span>] = TB_KEY_INSERT<span class="Delimiter">;</span> + Key[<span class="Constant">"delete"</span>] = TB_KEY_DELETE<span class="Delimiter">;</span> + Key[<span class="Constant">"home"</span>] = TB_KEY_HOME<span class="Delimiter">;</span> + Key[<span class="Constant">"end"</span>] = TB_KEY_END<span class="Delimiter">;</span> + Key[<span class="Constant">"page-up"</span>] = TB_KEY_PGUP<span class="Delimiter">;</span> + Key[<span class="Constant">"page-down"</span>] = TB_KEY_PGDN<span class="Delimiter">;</span> + Key[<span class="Constant">"up-arrow"</span>] = TB_KEY_ARROW_UP<span class="Delimiter">;</span> + Key[<span class="Constant">"down-arrow"</span>] = TB_KEY_ARROW_DOWN<span class="Delimiter">;</span> + Key[<span class="Constant">"left-arrow"</span>] = TB_KEY_ARROW_LEFT<span class="Delimiter">;</span> + Key[<span class="Constant">"right-arrow"</span>] = TB_KEY_ARROW_RIGHT<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-a"</span>] = TB_KEY_CTRL_A<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-b"</span>] = TB_KEY_CTRL_B<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-c"</span>] = TB_KEY_CTRL_C<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-d"</span>] = TB_KEY_CTRL_D<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-e"</span>] = TB_KEY_CTRL_E<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-f"</span>] = TB_KEY_CTRL_F<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-g"</span>] = TB_KEY_CTRL_G<span class="Delimiter">;</span> + Key[<span class="Constant">"backspace"</span>] = TB_KEY_BACKSPACE<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-h"</span>] = TB_KEY_CTRL_H<span class="Delimiter">;</span> + Key[<span class="Constant">"tab"</span>] = TB_KEY_TAB<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-i"</span>] = TB_KEY_CTRL_I<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-j"</span>] = TB_KEY_CTRL_J<span class="Delimiter">;</span> + Key[<span class="Constant">"enter"</span>] = TB_KEY_NEWLINE<span class="Delimiter">;</span> <span class="Comment">// ignore CR/LF distinction; there is only 'enter'</span> + Key[<span class="Constant">"ctrl-k"</span>] = TB_KEY_CTRL_K<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-l"</span>] = TB_KEY_CTRL_L<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-m"</span>] = TB_KEY_CTRL_M<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-n"</span>] = TB_KEY_CTRL_N<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-o"</span>] = TB_KEY_CTRL_O<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-p"</span>] = TB_KEY_CTRL_P<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-q"</span>] = TB_KEY_CTRL_Q<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-r"</span>] = TB_KEY_CTRL_R<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-s"</span>] = TB_KEY_CTRL_S<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-t"</span>] = TB_KEY_CTRL_T<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-u"</span>] = TB_KEY_CTRL_U<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-v"</span>] = TB_KEY_CTRL_V<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-w"</span>] = TB_KEY_CTRL_W<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-x"</span>] = TB_KEY_CTRL_X<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-y"</span>] = TB_KEY_CTRL_Y<span class="Delimiter">;</span> + Key[<span class="Constant">"ctrl-z"</span>] = TB_KEY_CTRL_Z<span class="Delimiter">;</span> + Key[<span class="Constant">"escape"</span>] = TB_KEY_ESC<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario events_in_scenario)</span> scenario events-in-scenario [ assume-console [ type [abc] left-click <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span> - press <span class="Constant">65515</span> <span class="Comment"># up arrow</span> + press up-arrow type [d] ] run [ <span class="Comment"># 3 keyboard events; each event occupies 4 locations</span> -<span class="CommentedCode">#? $start-tracing #? 2</span> <span class="Constant">1</span>:event<span class="Special"> <- </span>read-event console:address <span class="Constant">5</span>:event<span class="Special"> <- </span>read-event console:address <span class="Constant">9</span>:event<span class="Special"> <- </span>read-event console:address @@ -179,7 +240,7 @@ scenario events-in-scenario [ <span class="Constant">15</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># row</span> <span class="Constant">16</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># column</span> <span class="Constant">17</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># 'keycode'</span> - <span class="Constant">18</span><span class="Special"> <- </span><span class="Constant">65515</span> <span class="Comment"># up arrow</span> + <span class="Constant">18</span><span class="Special"> <- </span><span class="Constant">65517</span> <span class="Comment"># up arrow</span> <span class="Constant">19</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># unused</span> <span class="Constant">20</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># unused</span> <span class="Constant">21</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># 'text'</span> @@ -199,17 +260,13 @@ Recipe_ordinal[<span class="Constant">"replace-in-console"</span>] = R <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case REPLACE_IN_CONSOLE: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> -<span class="CommentedCode">//? cerr << "console: " << Memory[CONSOLE] << '\n'; //? 1</span> if <span class="Delimiter">(</span>!Memory[CONSOLE]<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << <span class="Constant">"console not initialized</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> long long int console_data = Memory[Memory[CONSOLE]+<span class="Constant">1</span>]<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "console data starts at " << console_data << '\n'; //? 1</span> long long int size = Memory[console_data]<span class="Delimiter">;</span> <span class="Comment">// array size</span> -<span class="CommentedCode">//? cerr << "size of console data is " << size << '\n'; //? 1</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">,</span> curr = console_data+<span class="Constant">1</span><span class="Delimiter">;</span> i < size<span class="Delimiter">;</span> ++i<span class="Delimiter">,</span> curr+=size_of_event<span class="Delimiter">())</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << curr << '\n'; //? 1</span> if <span class="Delimiter">(</span>Memory[curr] != <span class="Comment">/*</span><span class="Comment">text</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>Memory[curr+<span class="Constant">1</span>] != ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int n = <span class="Constant">0</span><span class="Delimiter">;</span> n < size_of_event<span class="Delimiter">();</span> ++n<span class="Delimiter">)</span> @@ -223,13 +280,10 @@ long long int count_events<span class="Delimiter">(</span>const recipe& r<sp long long int result = <span class="Constant">0</span><span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> const instruction& curr = r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> -<span class="CommentedCode">//? cerr << "aa: " << curr.name << '\n'; //? 3</span> -<span class="CommentedCode">//? cerr << "bb: " << curr.ingredients.at(0).name << '\n'; //? 1</span> if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"type"</span><span class="Delimiter">)</span> result += unicode_length<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span> else result++<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "cc: " << result << '\n'; //? 1</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/076scenario_console_test.mu.html b/html/076scenario_console_test.mu.html index b33cb4cd..7b38078c 100644 --- a/html/076scenario_console_test.mu.html +++ b/html/076scenario_console_test.mu.html @@ -13,10 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muScenario { color: #00af00; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -32,25 +31,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># scenario_console.mu</span> <span class="Comment"># Tests for console interface.</span> -<span class="muScenario">scenario</span> read-key-in-mu [ - assume-console [ - type <span class="Constant">[abc]</span> +scenario <span class="Identifier">read</span>-key-<span class="Identifier">in</span>-mu [ + <span class="Identifier">assume</span>-console [ + <span class="Identifier">type</span> [abc] ] run [ - <span class="Constant">1</span>:character, console:address, <span class="Constant">2</span>:boolean<span class="Special"> <- </span>read-key console:address - <span class="Constant">3</span>:character, console:address, <span class="Constant">4</span>:boolean<span class="Special"> <- </span>read-key console:address - <span class="Constant">5</span>:character, console:address, <span class="Constant">6</span>:boolean<span class="Special"> <- </span>read-key console:address - <span class="Constant">7</span>:character, console:address, <span class="Constant">8</span>:boolean<span class="Special"> <- </span>read-key console:address + 1:character, console:address, 2:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-key console:address + 3:character, console:address, 4:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-key console:address + 5:character, console:address, 6:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-key console:address + 7:character, console:address, 8:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-key console:address ] memory-should-contain [ - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> - <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">98</span> <span class="Comment"># 'b'</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> - <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">99</span> <span class="Comment"># 'c'</span> - <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">1</span> - <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># eof</span> - <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">1</span> + 1<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 2<span class="Special"> <- </span>1 + 3<span class="Special"> <- </span>98 <span class="Comment"># 'b'</span> + 4<span class="Special"> <- </span>1 + 5<span class="Special"> <- </span>99 <span class="Comment"># 'c'</span> + 6<span class="Special"> <- </span>1 + 7<span class="Special"> <- </span>0 <span class="Comment"># eof</span> + 8<span class="Special"> <- </span>1 ] ] </pre> diff --git a/html/080trace_browser.cc.html b/html/080trace_browser.cc.html index 0cc056d9..9ac50591 100644 --- a/html/080trace_browser.cc.html +++ b/html/080trace_browser.cc.html @@ -14,7 +14,6 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Identifier { color: #804000; } @@ -103,16 +102,12 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter <span class="Delimiter">}</span> if <span class="Delimiter">(</span>key == <span class="Constant">'K'</span> || key == TB_KEY_PGUP<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// page-up is more convoluted</span> -<span class="CommentedCode">//? tb_shutdown(); //? 1</span> -<span class="CommentedCode">//? cerr << "page-up: Top_of_screen is currently " << Top_of_screen << '\n'; //? 1</span> for <span class="Delimiter">(</span>int screen_row = tb_height<span class="Delimiter">();</span> screen_row > <span class="Constant">0</span> && Top_of_screen > <span class="Constant">0</span><span class="Delimiter">;</span> --screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span> --Top_of_screen<span class="Delimiter">;</span> if <span class="Delimiter">(</span>Top_of_screen <= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> while <span class="Delimiter">(</span>Top_of_screen > <span class="Constant">0</span> && Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Top_of_screen<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> --Top_of_screen<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "now " << Top_of_screen << '\n'; //? 1</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? exit(0); //? 1</span> if <span class="Delimiter">(</span>Top_of_screen > <span class="Constant">0</span><span class="Delimiter">)</span> refresh_screen_rows<span class="Delimiter">();</span> <span class="Delimiter">}</span> @@ -132,10 +127,8 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter <span class="Delimiter">}</span> if <span class="Delimiter">(</span>key == TB_KEY_CARRIAGE_RETURN<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// expand lines under current by one level</span> -<span class="CommentedCode">//? tb_shutdown();</span> assert<span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Display_row<span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">());</span> long long int start_index = Trace_index[Display_row]<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "start_index is " << start_index << '\n';</span> long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">// simultaneously compute end_index and min_depth</span> int min_depth = <span class="Constant">9999</span><span class="Delimiter">;</span> @@ -146,18 +139,14 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter assert<span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth > Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>start_index<span class="Delimiter">).</span>depth<span class="Delimiter">);</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth < min_depth<span class="Delimiter">)</span> min_depth = curr_line<span class="Delimiter">.</span>depth<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? cerr << "min_depth is " << min_depth << '\n';</span> long long int end_index = index<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "end_index is " << end_index << '\n';</span> <span class="Comment">// mark as visible all intervening indices at min_depth</span> for <span class="Delimiter">(</span>index = start_index<span class="Delimiter">;</span> index < end_index<span class="Delimiter">;</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace_line& curr_line = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == min_depth<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "adding " << index << '\n';</span> Visible<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>index<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? exit(0);</span> refresh_screen_rows<span class="Delimiter">();</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2<span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/081run_interactive.cc.html b/html/081run_interactive.cc.html index 7b711a4f..79db9059 100644 --- a/html/081run_interactive.cc.html +++ b/html/081run_interactive.cc.html @@ -14,12 +14,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.Identifier { color: #804000; } .traceContains { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } --> </style> @@ -58,7 +57,6 @@ recipe main [ RUN_INTERACTIVE<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> Recipe_ordinal[<span class="Constant">"run-interactive"</span>] = RUN_INTERACTIVE<span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case RUN_INTERACTIVE: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -66,7 +64,7 @@ case RUN_INTERACTIVE: <span class="Delimiter">{</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise << current_recipe_name<span class="Delimiter">()</span> << <span class="Constant">": first ingredient of 'run-interactive' should be a literal string, but got "</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>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + raise << current_recipe_name<span class="Delimiter">()</span> << <span class="Constant">": first ingredient of 'run-interactive' should be a string, but got "</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>to_string<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> bool new_code_pushed_to_stack = run_interactive<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> @@ -138,7 +136,7 @@ load<span class="Delimiter">(</span>string<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 <- 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:recipe, screen:address</span><span class="cSpecial">\n</span><span class="Constant">"</span> + - <span class="Constant">"limit-time r, 750/instructions</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> + @@ -151,6 +149,24 @@ load<span class="Delimiter">(</span>string<span class="Delimiter">(</span> transform_all<span class="Delimiter">();</span> recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Delimiter">:(scenario run_interactive_comments)</span> +recipe main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new [<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: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> + +<span class="Delimiter">:(scenario run_interactive_just_comments_without_trace)</span> +recipe main [ + $close-trace + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new [<span class="Comment"># ab</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">3</span>:array:character<span class="Special"> <- </span>copy *<span class="Constant">2</span>:address:array:character +] + <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> _START_TRACKING_PRODUCTS<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> @@ -206,7 +222,7 @@ case _CLEANUP_RUN_INTERACTIVE: <span class="Delimiter">{</span> <span class="Delimiter">:(code)</span> void cleanup_run_interactive<span class="Delimiter">()</span> <span class="Delimiter">{</span> Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>is_narrowly_collecting<span class="Delimiter">(</span><span class="Constant">"warn"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// hack</span> + if <span class="Delimiter">(</span>Trace_stream && Trace_stream<span class="Delimiter">-></span>is_narrowly_collecting<span class="Delimiter">(</span><span class="Constant">"warn"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// hack</span> delete Trace_stream<span class="Delimiter">;</span> Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -296,7 +312,6 @@ string strip_comments<span class="Delimiter">(</span>string in<span class="Delim else <span class="Delimiter">{</span> while <span class="Delimiter">(</span>i < SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> && in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> ++i<span class="Delimiter">;</span> - if <span class="Delimiter">(</span>i < SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> && in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> ++i<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span> @@ -311,18 +326,26 @@ long long int stringified_value_of_location<span class="Delimiter">(</span>long long long int trace_contents<span class="Delimiter">(</span>const string& layer<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "trace stream exists\n"; //? 1</span> if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span>layer<span class="Delimiter">)</span> <= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << layer << " has something\n"; //? 1</span> ostringstream out<span class="Delimiter">;</span> for <span class="Delimiter">(</span>vector<trace_line>::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>label != layer<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> out << p<span class="Delimiter">-></span>contents<span class="Delimiter">;</span> if <span class="Delimiter">(</span>*--p<span class="Delimiter">-></span>contents<span class="Delimiter">.</span>end<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> out << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - assert<span class="Delimiter">(</span>!out<span class="Delimiter">.</span>str<span class="Delimiter">().</span>empty<span class="Delimiter">());</span> -<span class="CommentedCode">//? cerr << layer << ":\n" << out.str() << "\n--\n"; //? 1</span> - <span class="Identifier">return</span> new_mu_string<span class="Delimiter">(</span>out<span class="Delimiter">.</span>str<span class="Delimiter">());</span> + string result = out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>!result<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + truncate<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Identifier">return</span> new_mu_string<span class="Delimiter">(</span>result<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void truncate<span class="Delimiter">(</span>string& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>x<span class="Delimiter">)</span> > <span class="Constant">512</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + x<span class="Delimiter">.</span>erase<span class="Delimiter">(</span><span class="Constant">512</span><span class="Delimiter">);</span> + *x<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> = <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + *++x<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> = <span class="Constant">'.'</span><span class="Delimiter">;</span> + *++++x<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> = <span class="Constant">'.'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">//: simpler version of run-interactive: doesn't do any running, just loads</span> @@ -348,6 +371,11 @@ case RELOAD: <span class="Delimiter">{</span> <span class="Delimiter">}</span> Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> Disable_redefine_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Comment">// clear any containers in advance</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Type[recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> string code = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> vector<recipe_ordinal> recipes_reloaded = load<span class="Delimiter">(</span>code<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>recipes_reloaded<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/082persist.cc.html b/html/082persist.cc.html index 04b4358d..01788333 100644 --- a/html/082persist.cc.html +++ b/html/082persist.cc.html @@ -14,7 +14,6 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .cSpecial { color: #008000; } -.CommentedCode { color: #6c6c6c; } .PreProc { color: #c000c0; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } @@ -68,7 +67,6 @@ case RESTORE: <span class="Delimiter">{</span> <span class="Delimiter">:(code)</span> string slurp<span class="Delimiter">(</span>const string& filename<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << filename << '\n'; //? 1</span> ostringstream result<span class="Delimiter">;</span> ifstream fin<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">());</span> fin<span class="Delimiter">.</span>peek<span class="Delimiter">();</span> @@ -81,7 +79,6 @@ string slurp<span class="Delimiter">(</span>const string& filename<span clas result << buf<span class="Delimiter">;</span> <span class="Delimiter">}</span> fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << "=> " << result.str(); //? 1</span> <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> diff --git a/html/callcc.mu.html b/html/callcc.mu.html index 20ebd83c..805a182e 100644 --- a/html/callcc.mu.html +++ b/html/callcc.mu.html @@ -13,11 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -31,20 +29,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: saving and reusing call-stacks or continuations</span> -<span class="muRecipe">recipe</span> main [ +recipe main [ c:continuation<span class="Special"> <- </span>f - <span class="muControl">continue-from</span> c <span class="Comment"># <-- ..when you hit this</span> + continue-from c <span class="Comment"># <-- ..when you hit this</span> ] -<span class="muRecipe">recipe</span> f [ +recipe f [ c:continuation<span class="Special"> <- </span>g - <span class="muControl">reply</span> c + reply c ] -<span class="muRecipe">recipe</span> g [ - c:continuation<span class="Special"> <- </span><span class="muControl">current-continuation</span> <span class="Comment"># <-- loop back to here</span> - $print <span class="Constant">1</span> - <span class="muControl">reply</span> c <span class="Comment"># threaded through unmodified after first iteration</span> +recipe g [ + c:continuation<span class="Special"> <- </span>current-continuation <span class="Comment"># <-- loop back to here</span> + $<span class="Identifier">print</span> 1 + reply c <span class="Comment"># threaded through unmodified after first iteration</span> ] </pre> </body> diff --git a/html/channel.mu.html b/html/channel.mu.html index 420eed5e..ce564ded 100644 --- a/html/channel.mu.html +++ b/html/channel.mu.html @@ -13,12 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -32,44 +30,44 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: communicating between routines using channels</span> -<span class="muRecipe">recipe</span> producer [ +recipe producer [ <span class="Comment"># produce numbers 1 to 5 on a channel</span> - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient <span class="Comment"># n = 0</span> - n:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>lesser-than n, <span class="Constant">5</span> - <span class="muControl">break-unless</span> done? + n:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + done?:boolean<span class="Special"> <- </span>lesser-than n, 5 + break-unless done? <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:address:channel<span class="Special"> <- </span>write chan, n - n<span class="Special"> <- </span>add n, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + $<span class="Identifier">print</span> [produce: ], n, [ +] + chan:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> chan, n + n<span class="Special"> <- </span>add n, 1 + loop + } ] -<span class="muRecipe">recipe</span> consumer [ +recipe consumer [ <span class="Comment"># consume and print integers from a channel</span> - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># read an integer from the channel</span> - n:number, chan:address:channel<span class="Special"> <- </span>read chan + n:number, chan:address:channel<span class="Special"> <- </span><span class="Identifier">read</span> chan <span class="Comment"># other threads might get between these prints</span> - $print <span class="Constant">[consume: ]</span>, n:number, <span class="Constant">[ </span> -<span class="Constant">]</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + $<span class="Identifier">print</span> [consume: ], n:number, [ +] + loop + } ] -<span class="muRecipe">recipe</span> main [ - <span class="Constant">local-scope</span> - chan:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">3</span> +recipe main [ + <span class="Underlined">local</span>-scope + chan:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 3 <span class="Comment"># create two background 'routines' that communicate by a channel</span> - routine1:number<span class="Special"> <- </span>start-running <span class="Constant">producer:recipe</span>, chan - routine2:number<span class="Special"> <- </span>start-running <span class="Constant">consumer:recipe</span>, chan + routine1:number<span class="Special"> <- </span>start-running producer:recipe, chan + routine2:number<span class="Special"> <- </span>start-running consumer:recipe, chan wait-for-routine routine1 wait-for-routine routine2 ] diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html index 0eb15641..75e01db0 100644 --- a/html/chessboard.mu.html +++ b/html/chessboard.mu.html @@ -13,15 +13,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .SalientComment { color: #00ffff; } -.muScenario { color: #00af00; } +.CommentedCode { color: #6c6c6c; } +.Underlined { color: #c000c0; text-decoration: underline; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -37,202 +34,195 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># display the position after each move.</span> <span class="Comment"># recipes are mu's names for functions</span> -<span class="muRecipe">recipe</span> main [ +recipe main [ open-console <span class="Comment"># take control of screen, keyboard and mouse</span> <span class="Comment"># The chessboard recipe takes keyboard and screen objects as 'ingredients'.</span> - <span class="Comment">#</span> + # <span class="Comment"># In mu it is good form (though not required) to explicitly show the</span> <span class="Comment"># hardware you rely on.</span> - <span class="Comment">#</span> + # <span class="Comment"># The chessboard also returns the same keyboard and screen objects. In mu it</span> <span class="Comment"># is good form to not modify ingredients of a recipe unless they are also</span> <span class="Comment"># results. Here we clearly modify both keyboard and screen, so we return</span> <span class="Comment"># both.</span> - <span class="Comment">#</span> + # <span class="Comment"># Here the console and screen are both 0, which usually indicates real</span> <span class="Comment"># hardware rather than a fake for testing as you'll see below.</span> - <span class="Constant">0/screen</span>, <span class="Constant">0/console</span><span class="Special"> <- </span>chessboard <span class="Constant">0/screen</span>, <span class="Constant">0/console</span> + 0/screen, 0/console<span class="Special"> <- </span>chessboard 0/screen, 0/console close-console <span class="Comment"># cleanup screen, keyboard and mouse</span> ] <span class="SalientComment">## But enough about mu. Here's what it looks like to run the chessboard program.</span> -<span class="muScenario">scenario</span> print-board-and-read-move [ +scenario <span class="Identifier">print</span>-board-and-<span class="Identifier">read</span>-move [ $close-trace <span class="Comment"># administrivia: most scenarios save and check traces, but this one gets too large/slow</span> <span class="Comment"># we'll make the screen really wide because the program currently prints out a long line</span> - assume-screen <span class="Constant">120/width</span>, <span class="Constant">20/height</span> + <span class="Identifier">assume</span>-screen 120/width, 20/height <span class="Comment"># initialize keyboard to type in a move</span> - assume-console [ - type <span class="Constant">[a2-a4</span> -<span class="Constant">]</span> + <span class="Identifier">assume</span>-console [ + <span class="Identifier">type</span> [a2-a4 +] ] run [ screen:address, console:address<span class="Special"> <- </span>chessboard screen:address, console:address <span class="Comment"># icon for the cursor</span> - screen<span class="Special"> <- </span>print-character screen, <span class="Constant">9251/␣</span> + screen<span class="Special"> <- </span><span class="Identifier">print</span>-character screen, 9251/␣ ] screen-should-contain [ <span class="Comment"># 1 2 3 4 5 6 7 8 9 10 11</span> <span class="Comment"># 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789</span> - <span class="Constant"> .Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves. .</span> - <span class="Constant"> . .</span> - <span class="Constant"> .8 | r n b q k b n r .</span> - <span class="Constant"> .7 | p p p p p p p p .</span> - <span class="Constant"> .6 | .</span> - <span class="Constant"> .5 | .</span> - <span class="Constant"> .4 | P .</span> - <span class="Constant"> .3 | .</span> - <span class="Constant"> .2 | P P P P P P P .</span> - <span class="Constant"> .1 | R N B Q K B N R .</span> - <span class="Constant"> . +---------------- .</span> - <span class="Constant"> . a b c d e f g h .</span> - <span class="Constant"> . .</span> - <span class="Constant"> .Type in your move as <from square>-<to square>. For example: 'a2-a4'. Then press <enter>. .</span> - <span class="Constant"> . .</span> - <span class="Constant"> .Hit 'q' to exit. .</span> - <span class="Constant"> . .</span> - <span class="Constant"> .move: ␣ .</span> - <span class="Constant"> . .</span> - <span class="Constant"> . .</span> + .Stupid text-mode chessboard. White pieces <span class="Identifier">in</span> uppercase; black pieces <span class="Identifier">in</span> lowercase. No checking for legal moves. . + . . + .8 | r n b q k b n r . + .7 | p p p p p p p p . + .6 | . + .5 | . + .4 | P . + .3 | . + .2 | P P P P P P P . + .1 | R N B Q K B N R . + . +---------------- . + . a b c d e f g h . + . . + .Type <span class="Identifier">in</span> your move as <from square>-<to square>. For example: 'a2-a4'. Then press <enter>. . + . . + .Hit 'q' to exit. . + . . + .move: ␣ . + . . + . . ] ] <span class="SalientComment">## Here's how 'chessboard' is implemented.</span> -<span class="muRecipe">recipe</span> chessboard [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - board:address:array:address:array:character<span class="Special"> <- </span>initial-position +recipe chessboard [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient + console:address<span class="Special"> <- </span>next-ingredient + board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>initial-position <span class="Comment"># hook up stdin</span> - stdin:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> - start-running <span class="Constant">send-keys-to-channel:recipe</span>, console, stdin, screen + stdin:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 10/capacity + start-running send-keys-to-channel:recipe, console, stdin, screen <span class="Comment"># buffer lines in stdin</span> - buffered-stdin:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">10/capacity</span> - start-running <span class="Constant">buffer-lines:recipe</span>, stdin, buffered-stdin - <span class="Delimiter">{</span> - msg:address:array:character<span class="Special"> <- </span>new <span class="Constant">[Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.</span> -<span class="Constant">]</span> - print-string screen, msg + buffered-stdin:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 10/capacity + start-running buffer-lines:recipe, stdin, buffered-stdin + { + msg:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [Stupid text-mode chessboard. White pieces <span class="Identifier">in</span> uppercase; black pieces <span class="Identifier">in</span> lowercase. No checking for legal moves. +] + <span class="Identifier">print</span>-string screen, msg cursor-to-next-line screen - print-board screen, board + <span class="Identifier">print</span>-board screen, board cursor-to-next-line screen - msg<span class="Special"> <- </span>new <span class="Constant">[Type in your move as <from square>-<to square>. For example: 'a2-a4'. Then press <enter>.</span> -<span class="Constant">]</span> - print-string screen, msg + msg<span class="Special"> <- </span><span class="Identifier">new</span> [Type <span class="Identifier">in</span> your move as <from square>-<to square>. For example: 'a2-a4'. Then press <enter>. +] + <span class="Identifier">print</span>-string screen, msg cursor-to-next-line screen - msg<span class="Special"> <- </span>new <span class="Constant">[Hit 'q' to exit.</span> -<span class="Constant">]</span> - print-string screen, msg - <span class="Delimiter">{</span> + msg<span class="Special"> <- </span><span class="Identifier">new</span> [Hit 'q' to exit. +] + <span class="Identifier">print</span>-string screen, msg + { cursor-to-next-line screen - msg<span class="Special"> <- </span>new <span class="Constant">[move: ]</span> - print-string screen, msg - m:address:move, quit:boolean, error:boolean<span class="Special"> <- </span>read-move buffered-stdin, screen - <span class="muControl">break-if</span> quit, <span class="Constant">+quit:label</span> + msg<span class="Special"> <- </span><span class="Identifier">new</span> [move: ] + <span class="Identifier">print</span>-string screen, msg + m:address:move, <span class="Identifier">quit</span>:boolean, <span class="Identifier">error</span>:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-move buffered-stdin, screen + break-if <span class="Identifier">quit</span>, +<span class="Identifier">quit</span>:label buffered-stdin<span class="Special"> <- </span>clear-channel buffered-stdin <span class="Comment"># cleanup after error. todo: test this?</span> - <span class="muControl">loop-if</span> error - <span class="Delimiter">}</span> + loop-if <span class="Identifier">error</span> + } board<span class="Special"> <- </span>make-move board, m clear-screen screen - <span class="muControl">loop</span> - <span class="Delimiter">}</span> -<span class="Constant"> +quit</span> + loop + } + +<span class="Identifier">quit</span> ] <span class="SalientComment">## a board is an array of files, a file is an array of characters (squares)</span> -<span class="muRecipe">recipe</span> new-board [ - <span class="Constant">local-scope</span> - initial-position:address:array:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> +recipe <span class="Identifier">new</span>-board [ + <span class="Underlined">local</span>-scope + initial-position:address:<span class="Identifier">array</span>:number<span class="Special"> <- </span>next-ingredient <span class="Comment"># assert(length(initial-position) == 64)</span> - len:number<span class="Special"> <- </span>length *initial-position - 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> + len:number<span class="Special"> <- </span><span class="Identifier">length</span> *initial-position + correct-<span class="Identifier">length</span>?:boolean<span class="Special"> <- </span>equal len, 64 + <span class="Identifier">assert</span> correct-<span class="Identifier">length</span>?, [chessboard had incorrect size] <span class="Comment"># board is an array of pointers to files; file is an array of characters</span> - board:address:array:address:array:character<span class="Special"> <- </span>new <span class="Constant">location:type</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:array:character<span class="Special"> <- </span>index-address *board, col - *file<span class="Special"> <- </span>new-file initial-position, col - col<span class="Special"> <- </span>add col, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> board + board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 8 + col:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + done?:boolean<span class="Special"> <- </span>equal col, 8 + break-if done? + file:address:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index-address *board, col + *file<span class="Special"> <- </span><span class="Identifier">new</span>-file initial-position, col + col<span class="Special"> <- </span>add col, 1 + loop + } + reply board ] -<span class="muRecipe">recipe</span> new-file [ - <span class="Constant">local-scope</span> - position:address:array:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - index:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - index<span class="Special"> <- </span>multiply index, <span class="Constant">8</span> - result:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, <span class="Constant">8</span> - row:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>equal row, <span class="Constant">8</span> - <span class="muControl">break-if</span> done? +recipe <span class="Identifier">new</span>-file [ + <span class="Underlined">local</span>-scope + position:address:<span class="Identifier">array</span>:number<span class="Special"> <- </span>next-ingredient + index:number<span class="Special"> <- </span>next-ingredient + index<span class="Special"> <- </span>multiply index, 8 + result:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, 8 + row:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + done?:boolean<span class="Special"> <- </span>equal row, 8 + break-if done? dest:address:character<span class="Special"> <- </span>index-address *result, row *dest<span class="Special"> <- </span>index *position, index - 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="muControl">reply</span> result + row<span class="Special"> <- </span>add row, 1 + index<span class="Special"> <- </span>add index, 1 + loop + } + reply result ] -<span class="muRecipe">recipe</span> print-board [ - <span class="Constant">local-scope</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - board:address:array:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</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> +recipe <span class="Identifier">print</span>-board [ + <span class="Underlined">local</span>-scope + screen:address<span class="Special"> <- </span>next-ingredient + board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + row:number<span class="Special"> <- </span><span class="Identifier">copy</span> 7 <span class="Comment"># start printing from the top of the board</span> <span class="Comment"># print each row</span> -<span class="CommentedCode">#? $print [printing board to screen ], screen, 10/newline</span> - <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>lesser-than row, <span class="Constant">0</span> - <span class="muControl">break-if</span> done? -<span class="CommentedCode">#? $print [printing rank ], row, 10/newline</span> + { + done?:boolean<span class="Special"> <- </span>lesser-than row, 0 + break-if done? <span class="Comment"># print rank number as a legend</span> - rank:number<span class="Special"> <- </span>add row, <span class="Constant">1</span> - print-integer screen, rank - s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ | ]</span> - print-string screen, s + rank:number<span class="Special"> <- </span>add row, 1 + <span class="Identifier">print</span>-integer screen, rank + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [ | ] + <span class="Identifier">print</span>-string screen, s <span class="Comment"># print each square in the row</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:number, <span class="Constant">8</span> - <span class="muControl">break-if</span> done?:boolean - f:address:array:character<span class="Special"> <- </span>index *board, col + col:number<span class="Special"> <- </span><span class="Identifier">copy</span> 0 + { + done?:boolean<span class="Special"> <- </span>equal col:number, 8 + break-if done?:boolean + f:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *board, col c:character<span class="Special"> <- </span>index *f, row - print-character screen, c - print-character screen, <span class="Constant">32/space</span> - col<span class="Special"> <- </span>add col, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - row<span class="Special"> <- </span>subtract row, <span class="Constant">1</span> + <span class="Identifier">print</span>-character screen, c + <span class="Identifier">print</span>-character screen, 32/space + col<span class="Special"> <- </span>add col, 1 + loop + } + row<span class="Special"> <- </span>subtract row, 1 cursor-to-next-line screen - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + loop + } <span class="Comment"># print file letters as legend</span> -<span class="CommentedCode">#? $print [printing legend</span> -<span class="CommentedCode">#? ] #? 1</span> - s<span class="Special"> <- </span>new <span class="Constant">[ +----------------]</span> - print-string screen, s + s<span class="Special"> <- </span><span class="Identifier">new</span> [ +----------------] + <span class="Identifier">print</span>-string screen, s screen<span class="Special"> <- </span>cursor-to-next-line screen -<span class="CommentedCode">#? screen <- print-character screen, 97 #? 1</span> - s<span class="Special"> <- </span>new <span class="Constant">[ a b c d e f g h]</span> - screen<span class="Special"> <- </span>print-string screen, s + s<span class="Special"> <- </span><span class="Identifier">new</span> [ a b c d e f g h] + screen<span class="Special"> <- </span><span class="Identifier">print</span>-string screen, s screen<span class="Special"> <- </span>cursor-to-next-line screen -<span class="CommentedCode">#? $print [done printing board</span> -<span class="CommentedCode">#? ] #? 1</span> ] <span class="Comment"># board:address:array:address:array:character <- initial-position</span> -<span class="muRecipe">recipe</span> initial-position [ - <span class="Constant">local-scope</span> +recipe initial-position [ + <span class="Underlined">local</span>-scope <span class="Comment"># layout in memory (in raster order):</span> <span class="Comment"># R P _ _ _ _ p r</span> <span class="Comment"># N P _ _ _ _ p n</span> @@ -242,7 +232,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># B P _ _ _ _ p B</span> <span class="Comment"># N P _ _ _ _ p n</span> <span class="Comment"># R P _ _ _ _ p r</span> - initial-position:address:array:number<span class="Special"> <- </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:<span class="Identifier">array</span>:number<span class="Special"> <- </span><span class="Identifier">new</span>-<span class="Identifier">array</span> 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 81/Q, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 113/q, 75/K, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 107/k, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r <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> @@ -251,31 +241,30 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="CommentedCode">#? 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b,</span> <span class="CommentedCode">#? 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,</span> <span class="CommentedCode">#? 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r</span> - board:address:array:address:array:character<span class="Special"> <- </span>new-board initial-position - <span class="muControl">reply</span> board + board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span>-board initial-position + reply board ] -<span class="muScenario">scenario</span> printing-the-board [ - assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span> +scenario printing-the-board [ + <span class="Identifier">assume</span>-screen 30/width, 12/height run [ - <span class="Constant">1</span>:address:array:address:array:character/board<span class="Special"> <- </span>initial-position - screen:address<span class="Special"> <- </span>print-board screen:address, <span class="Constant">1</span>:address:array:address:array:character/board -<span class="CommentedCode">#? $dump-screen #? 1</span> + 1:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board<span class="Special"> <- </span>initial-position + screen:address<span class="Special"> <- </span><span class="Identifier">print</span>-board screen:address, 1:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board ] screen-should-contain [ <span class="Comment"># 012345678901234567890123456789</span> - <span class="Constant"> .8 | r n b q k b n r .</span> - <span class="Constant"> .7 | p p p p p p p p .</span> - <span class="Constant"> .6 | .</span> - <span class="Constant"> .5 | .</span> - <span class="Constant"> .4 | .</span> - <span class="Constant"> .3 | .</span> - <span class="Constant"> .2 | P P P P P P P P .</span> - <span class="Constant"> .1 | R N B Q K B N R .</span> - <span class="Constant"> . +---------------- .</span> - <span class="Constant"> . a b c d e f g h .</span> - <span class="Constant"> . .</span> - <span class="Constant"> . .</span> + .8 | r n b q k b n r . + .7 | p p p p p p p p . + .6 | . + .5 | . + .4 | . + .3 | . + .2 | P P P P P P P P . + .1 | R N B Q K B N R . + . +---------------- . + . a b c d e f g h . + . . + . . ] ] @@ -291,360 +280,360 @@ container move [ <span class="Comment"># result:address:move, quit?:boolean, error?:boolean <- read-move stdin:address:channel, screen:address</span> <span class="Comment"># prints only error messages to screen</span> -<span class="muRecipe">recipe</span> read-move [ - <span class="Constant">local-scope</span> - stdin:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - from-file:number, quit?:boolean, error?:boolean<span class="Special"> <- </span>read-file stdin, screen - <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error? - <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error? +recipe <span class="Identifier">read</span>-move [ + <span class="Underlined">local</span>-scope + stdin:address:channel<span class="Special"> <- </span>next-ingredient + screen:address<span class="Special"> <- </span>next-ingredient + from-file:number, <span class="Identifier">quit</span>?:boolean, <span class="Identifier">error</span>?:boolean<span class="Special"> <- </span><span class="Identifier">read</span>-file stdin, screen + reply-if <span class="Identifier">quit</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? + reply-if <span class="Identifier">error</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? <span class="Comment"># construct the move object</span> - result:address: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 - <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error? - <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error? - error?<span class="Special"> <- </span>expect-from-channel stdin, <span class="Constant">45/dash</span>, screen - <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, error? - 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 - <span class="muControl">reply-if</span> quit?:boolean, <span class="Constant">0/dummy</span>, quit?:boolean, error?:boolean - <span class="muControl">reply-if</span> error?:boolean, <span class="Constant">0/dummy</span>, quit?:boolean, error?:boolean - 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 - <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error? - <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error? - error?<span class="Special"> <- </span>expect-from-channel stdin, <span class="Constant">10/newline</span>, screen - <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, error? - <span class="muControl">reply</span> result, quit?, error? + result:address:move<span class="Special"> <- </span><span class="Identifier">new</span> move:<span class="Identifier">type</span> + x:address:number<span class="Special"> <- </span>get-address *result, from-file:offset + *x<span class="Special"> <- </span><span class="Identifier">copy</span> from-file + x<span class="Special"> <- </span>get-address *result, from-rank:offset + *x, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?<span class="Special"> <- </span><span class="Identifier">read</span>-rank stdin, screen + reply-if <span class="Identifier">quit</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? + reply-if <span class="Identifier">error</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? + <span class="Identifier">error</span>?<span class="Special"> <- </span>expect-from-channel stdin, 45/dash, screen + reply-if <span class="Identifier">error</span>?, 0/dummy, 0/<span class="Identifier">quit</span>, <span class="Identifier">error</span>? + x<span class="Special"> <- </span>get-address *result, to-file:offset + *x, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?<span class="Special"> <- </span><span class="Identifier">read</span>-file stdin, screen + reply-if <span class="Identifier">quit</span>?:boolean, 0/dummy, <span class="Identifier">quit</span>?:boolean, <span class="Identifier">error</span>?:boolean + reply-if <span class="Identifier">error</span>?:boolean, 0/dummy, <span class="Identifier">quit</span>?:boolean, <span class="Identifier">error</span>?:boolean + x:address:number<span class="Special"> <- </span>get-address *result, to-rank:offset + *x, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?<span class="Special"> <- </span><span class="Identifier">read</span>-rank stdin, screen + reply-if <span class="Identifier">quit</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? + reply-if <span class="Identifier">error</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? + <span class="Identifier">error</span>?<span class="Special"> <- </span>expect-from-channel stdin, 10/newline, screen + reply-if <span class="Identifier">error</span>?, 0/dummy, 0/<span class="Identifier">quit</span>, <span class="Identifier">error</span>? + reply result, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>? ] <span class="Comment"># file:number, quit:boolean, error:boolean <- read-file stdin:address:channel, screen:address</span> <span class="Comment"># valid values for file: 0-7</span> -<span class="muRecipe">recipe</span> read-file [ - <span class="Constant">local-scope</span> - stdin:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - c:character, stdin<span class="Special"> <- </span>read stdin - <span class="Delimiter">{</span> - q-pressed?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">81/Q</span> - <span class="muControl">break-unless</span> q-pressed? - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - q-pressed?<span class="Special"> <- </span>equal c, <span class="Constant">113/q</span> - <span class="muControl">break-unless</span> q-pressed? - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - empty-fake-keyboard?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">0/eof</span> - <span class="muControl">break-unless</span> empty-fake-keyboard? - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> - <span class="muControl">break-unless</span> newline? - error-message:address:array:character<span class="Special"> <- </span>new <span class="Constant">[that's not enough]</span> - print-string screen, error-message - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span> - <span class="Delimiter">}</span> - file:number<span class="Special"> <- </span>subtract c, <span class="Constant">97/a</span> +recipe <span class="Identifier">read</span>-file [ + <span class="Underlined">local</span>-scope + stdin:address:channel<span class="Special"> <- </span>next-ingredient + screen:address<span class="Special"> <- </span>next-ingredient + c:character, stdin<span class="Special"> <- </span><span class="Identifier">read</span> stdin + { + q-pressed?:boolean<span class="Special"> <- </span>equal c, 81/Q + break-unless q-pressed? + reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> + } + { + q-pressed?<span class="Special"> <- </span>equal c, 113/q + break-unless q-pressed? + reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> + } + { + empty-fake-keyboard?:boolean<span class="Special"> <- </span>equal c, 0/eof + break-unless empty-fake-keyboard? + reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> + } + { + newline?:boolean<span class="Special"> <- </span>equal c, 10/newline + break-unless newline? + <span class="Identifier">error</span>-message:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [that's not enough] + <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message + reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span> + } + file:number<span class="Special"> <- </span>subtract c, 97/a <span class="Comment"># 'a' <= file <= 'h'</span> - <span class="Delimiter">{</span> - above-min:boolean<span class="Special"> <- </span>greater-or-equal file, <span class="Constant">0</span> - <span class="muControl">break-if</span> above-min - error-message:address:array:character<span class="Special"> <- </span>new <span class="Constant">[file too low: ]</span> - print-string screen, error-message - print-character screen, c + { + above-<span class="Identifier">min</span>:boolean<span class="Special"> <- </span>greater-or-equal file, 0 + break-if above-<span class="Identifier">min</span> + <span class="Identifier">error</span>-message:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [file too low: ] + <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message + <span class="Identifier">print</span>-character screen, c cursor-to-next-line screen - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - below-max:boolean<span class="Special"> <- </span>lesser-than file, <span class="Constant">8</span> - <span class="muControl">break-if</span> below-max - error-message<span class="Special"> <- </span>new <span class="Constant">[file too high: ]</span> - print-string screen, error-message - print-character screen, c - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> file, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span> + reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span> + } + { + below-<span class="Identifier">max</span>:boolean<span class="Special"> <- </span>lesser-than file, 8 + break-if below-<span class="Identifier">max</span> + <span class="Identifier">error</span>-message<span class="Special"> <- </span><span class="Identifier">new</span> [file too high: ] + <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message + <span class="Identifier">print</span>-character screen, c + reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span> + } + reply file, 0/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> ] <span class="Comment"># rank:number <- read-rank stdin:address:channel, screen:address</span> <span class="Comment"># valid values: 0-7, -1 (quit), -2 (error)</span> -<span class="muRecipe">recipe</span> read-rank [ - <span class="Constant">local-scope</span> - stdin:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - c:character, stdin<span class="Special"> <- </span>read stdin - <span class="Delimiter">{</span> - q-pressed?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">8/Q</span> - <span class="muControl">break-unless</span> q-pressed? - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - q-pressed?<span class="Special"> <- </span>equal c, <span class="Constant">113/q</span> - <span class="muControl">break-unless</span> q-pressed? - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10</span> <span class="Comment"># newline</span> - <span class="muControl">break-unless</span> newline? - error-message:address:array:character<span class="Special"> <- </span>new <span class="Constant">[that's not enough]</span> - print-string screen, error-message - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span> - <span class="Delimiter">}</span> - rank:number<span class="Special"> <- </span>subtract c, <span class="Constant">49/'1'</span> +recipe <span class="Identifier">read</span>-rank [ + <span class="Underlined">local</span>-scope + stdin:address:channel<span class="Special"> <- </span>next-ingredient + screen:address<span class="Special"> <- </span>next-ingredient + c:character, stdin<span class="Special"> <- </span><span class="Identifier">read</span> stdin + { + q-pressed?:boolean<span class="Special"> <- </span>equal c, 8/Q + break-unless q-pressed? + reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> + } + { + q-pressed?<span class="Special"> <- </span>equal c, 113/q + break-unless q-pressed? + reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> + } + { + newline?:boolean<span class="Special"> <- </span>equal c, 10 <span class="Comment"># newline</span> + break-unless newline? + <span class="Identifier">error</span>-message:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [that's not enough] + <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message + reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span> + } + rank:number<span class="Special"> <- </span>subtract c, 49/'1' <span class="Comment"># assert'1' <= rank <= '8'</span> - <span class="Delimiter">{</span> - above-min:boolean<span class="Special"> <- </span>greater-or-equal rank, <span class="Constant">0</span> - <span class="muControl">break-if</span> above-min - error-message<span class="Special"> <- </span>new <span class="Constant">[rank too low: ]</span> - print-string screen, error-message - print-character screen, c - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - below-max:boolean<span class="Special"> <- </span>lesser-or-equal rank, <span class="Constant">7</span> - <span class="muControl">break-if</span> below-max - error-message<span class="Special"> <- </span>new <span class="Constant">[rank too high: ]</span> - print-string screen, error-message - print-character screen, c - <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span> - <span class="Delimiter">}</span> - <span class="muControl">reply</span> rank, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span> + { + above-<span class="Identifier">min</span>:boolean<span class="Special"> <- </span>greater-or-equal rank, 0 + break-if above-<span class="Identifier">min</span> + <span class="Identifier">error</span>-message<span class="Special"> <- </span><span class="Identifier">new</span> [rank too low: ] + <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message + <span class="Identifier">print</span>-character screen, c + reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span> + } + { + below-<span class="Identifier">max</span>:boolean<span class="Special"> <- </span>lesser-or-equal rank, 7 + break-if below-<span class="Identifier">max</span> + <span class="Identifier">error</span>-message<span class="Special"> <- </span><span class="Identifier">new</span> [rank too high: ] + <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message + <span class="Identifier">print</span>-character screen, c + reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span> + } + reply rank, 0/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span> ] <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">recipe</span> expect-from-channel [ - <span class="Constant">local-scope</span> - stdin:address:channel<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - expected:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - c:character, stdin<span class="Special"> <- </span>read stdin - <span class="Delimiter">{</span> - match?:boolean<span class="Special"> <- </span>equal c, expected - <span class="muControl">break-if</span> match? - s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[expected character not found]</span> - print-string screen, s - <span class="Delimiter">}</span> - result:boolean<span class="Special"> <- </span>not match? - <span class="muControl">reply</span> result +recipe expect-from-channel [ + <span class="Underlined">local</span>-scope + stdin:address:channel<span class="Special"> <- </span>next-ingredient + expected:character<span class="Special"> <- </span>next-ingredient + screen:address<span class="Special"> <- </span>next-ingredient + c:character, stdin<span class="Special"> <- </span><span class="Identifier">read</span> stdin + { + <span class="Identifier">match</span>?:boolean<span class="Special"> <- </span>equal c, expected + break-if <span class="Identifier">match</span>? + s:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span><span class="Identifier">new</span> [expected character not found] + <span class="Identifier">print</span>-string screen, s + } + result:boolean<span class="Special"> <- </span>not <span class="Identifier">match</span>? + reply result ] -<span class="muScenario">scenario</span> read-move-blocking [ - assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> +scenario <span class="Identifier">read</span>-move-blocking [ + <span class="Identifier">assume</span>-screen 20/width, 2/height run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> <- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 2 + 2:number/routine<span class="Special"> <- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address <span class="Comment"># 'read-move' is waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to pause after coming up (before any keys were pressed)] <span class="Comment"># press 'a'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 97/a + restart 2:number/routine <span class="Comment"># 'read-move' still waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> rank 'a'] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to pause after rank 'a'] <span class="Comment"># press '2'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">50/'2'</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 50/'2' + restart 2:number/routine <span class="Comment"># 'read-move' still waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> file 'a2'] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to pause after file 'a2'] <span class="Comment"># press '-'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">45/'-'</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 45/'-' + restart 2:number/routine <span class="Comment"># 'read-move' still waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?/routine-state, [ -F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> hyphen 'a2-'] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?/routine-state, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to pause after hyphen 'a2-'] <span class="Comment"># press 'a'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 97/a + restart 2:number/routine <span class="Comment"># 'read-move' still waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?/routine-state, [ -F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> rank 'a2-a'] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?/routine-state, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to pause after rank 'a2-a'] <span class="Comment"># press '4'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">52/'4'</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 52/'4' + restart 2:number/routine <span class="Comment"># 'read-move' still waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> file 'a2-a4'] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to pause after file 'a2-a4'] <span class="Comment"># press 'newline'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10</span> <span class="Comment"># newline</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 10 <span class="Comment"># newline</span> + restart 2:number/routine <span class="Comment"># 'read-move' now completes</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number - <span class="Constant">4</span>:boolean/completed?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">1/completed</span> - assert <span class="Constant">4</span>:boolean/completed?, [ -F read-move-blocking: routine failed to terminate on newline] - trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span> + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number + 4:boolean/completed?<span class="Special"> <- </span>equal 3:number/routine-state, 1/completed + <span class="Identifier">assert</span> 4:boolean/completed?, [ +F <span class="Identifier">read</span>-move-blocking: routine failed to terminate on newline] + trace 1, [test], [reached end] ] trace-should-contain [ test: reached end ] ] -<span class="muScenario">scenario</span> read-move-quit [ - assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> +scenario <span class="Identifier">read</span>-move-<span class="Identifier">quit</span> [ + <span class="Identifier">assume</span>-screen 20/width, 2/height run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> <- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 2 + 2:number/routine<span class="Special"> <- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address <span class="Comment"># 'read-move' is waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-quit: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)] + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-<span class="Identifier">quit</span>: routine failed to pause after coming up (before any keys were pressed)] <span class="Comment"># press 'q'</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">113/q</span> - restart <span class="Constant">2</span>:number/routine + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 113/q + restart 2:number/routine <span class="Comment"># 'read-move' completes</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/completed?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">1/completed</span> - assert <span class="Constant">4</span>:boolean/completed?, [ -F read-move-quit: routine failed to terminate on 'q'] - trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span> + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/completed?<span class="Special"> <- </span>equal 3:number/routine-state, 1/completed + <span class="Identifier">assert</span> 4:boolean/completed?, [ +F <span class="Identifier">read</span>-move-<span class="Identifier">quit</span>: routine failed to terminate on 'q'] + trace 1, [test], [reached end] ] trace-should-contain [ test: reached end ] ] -<span class="muScenario">scenario</span> read-move-illegal-file [ - assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> +scenario <span class="Identifier">read</span>-move-illegal-file [ + <span class="Identifier">assume</span>-screen 20/width, 2/height run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> <- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 2 + 2:number/routine<span class="Special"> <- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address <span class="Comment"># 'read-move' is waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-file: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)] - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">50/'2'</span> - restart <span class="Constant">2</span>:number/routine - wait-for-routine <span class="Constant">2</span>:number + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-file: routine failed to pause after coming up (before any keys were pressed)] + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 50/'2' + restart 2:number/routine + wait-for-routine 2:number ] screen-should-contain [ - <span class="Constant"> .file too low: 2 .</span> - <span class="Constant"> . .</span> + .file too low: 2 . + . . ] ] -<span class="muScenario">scenario</span> read-move-illegal-rank [ - assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> +scenario <span class="Identifier">read</span>-move-illegal-rank [ + <span class="Identifier">assume</span>-screen 20/width, 2/height run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> <- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 2 + 2:number/routine<span class="Special"> <- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address <span class="Comment"># 'read-move' is waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-file: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)] - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span> - restart <span class="Constant">2</span>:number/routine - wait-for-routine <span class="Constant">2</span>:number + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-file: routine failed to pause after coming up (before any keys were pressed)] + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 97/a + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 97/a + restart 2:number/routine + wait-for-routine 2:number ] screen-should-contain [ - <span class="Constant"> .rank too high: a .</span> - <span class="Constant"> . .</span> + .rank too high: a . + . . ] ] -<span class="muScenario">scenario</span> read-move-empty [ - assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> +scenario <span class="Identifier">read</span>-move-empty [ + <span class="Identifier">assume</span>-screen 20/width, 2/height run [ - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>new-channel <span class="Constant">2</span> - <span class="Constant">2</span>:number/routine<span class="Special"> <- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address + 1:address:channel<span class="Special"> <- </span><span class="Identifier">new</span>-channel 2 + 2:number/routine<span class="Special"> <- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address <span class="Comment"># 'read-move' is waiting for input</span> - wait-for-routine <span class="Constant">2</span>:number - <span class="Constant">3</span>:number<span class="Special"> <- </span>routine-state <span class="Constant">2</span>:number/id - <span class="Constant">4</span>:boolean/waiting?<span class="Special"> <- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span> - assert <span class="Constant">4</span>:boolean/waiting?, [ -F read-move-file: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)] - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10/newline</span> - <span class="Constant">1</span>:address:channel<span class="Special"> <- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span> - restart <span class="Constant">2</span>:number/routine - wait-for-routine <span class="Constant">2</span>:number + wait-for-routine 2:number + 3:number<span class="Special"> <- </span>routine-state 2:number/<span class="Identifier">id</span> + 4:boolean/waiting?<span class="Special"> <- </span>equal 3:number/routine-state, 3/waiting + <span class="Identifier">assert</span> 4:boolean/waiting?, [ +F <span class="Identifier">read</span>-move-file: routine failed to pause after coming up (before any keys were pressed)] + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 10/newline + 1:address:channel<span class="Special"> <- </span><span class="Identifier">write</span> 1:address:channel, 97/a + restart 2:number/routine + wait-for-routine 2:number ] screen-should-contain [ - <span class="Constant"> .that's not enough .</span> - <span class="Constant"> . .</span> + .that's not enough . + . . ] ] -<span class="muRecipe">recipe</span> make-move [ - <span class="Constant">local-scope</span> - b:address:array:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - m:address:move<span class="Special"> <- </span><span class="Constant">next-ingredient</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:array:character<span class="Special"> <- </span>index *b, from-file +recipe make-move [ + <span class="Underlined">local</span>-scope + b:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>next-ingredient + m:address:move<span class="Special"> <- </span>next-ingredient + from-file:number<span class="Special"> <- </span>get *m, from-file:offset + from-rank:number<span class="Special"> <- </span>get *m, from-rank:offset + to-file:number<span class="Special"> <- </span>get *m, to-file:offset + to-rank:number<span class="Special"> <- </span>get *m, to-rank:offset + f:address:<span class="Identifier">array</span>:character<span class="Special"> <- </span>index *b, from-file src:address:character/square<span class="Special"> <- </span>index-address *f, from-rank f<span class="Special"> <- </span>index *b, 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> - <span class="muControl">reply</span> b/same-as-ingredient:<span class="Constant">0</span> + *dest<span class="Special"> <- </span><span class="Identifier">copy</span> *src + *src<span class="Special"> <- </span><span class="Identifier">copy</span> 32/space + reply b/same-as-ingredient:0 ] -<span class="muScenario">scenario</span> making-a-move [ - assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span> +scenario making-a-move [ + <span class="Identifier">assume</span>-screen 30/width, 12/height run [ - <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">4</span>:address:number<span class="Special"> <- </span>get-address *<span class="Constant">3</span>:address: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: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: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: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: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<span class="Special"> <- </span>print-board screen:address, <span class="Constant">2</span>:address:array:address:array:character/board + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board<span class="Special"> <- </span>initial-position + 3:address:move<span class="Special"> <- </span><span class="Identifier">new</span> move:<span class="Identifier">type</span> + 4:address:number<span class="Special"> <- </span>get-address *3:address:move, from-file:offset + *4:address:number<span class="Special"> <- </span><span class="Identifier">copy</span> 6/g + 5:address:number<span class="Special"> <- </span>get-address *3:address:move, from-rank:offset + *5:address:number<span class="Special"> <- </span><span class="Identifier">copy</span> 1/'2' + 6:address:number<span class="Special"> <- </span>get-address *3:address:move, to-file:offset + *6:address:number<span class="Special"> <- </span><span class="Identifier">copy</span> 6/g + 7:address:number<span class="Special"> <- </span>get-address *3:address:move, to-rank:offset + *7:address:number<span class="Special"> <- </span><span class="Identifier">copy</span> 3/'4' + 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board<span class="Special"> <- </span>make-move 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board, 3:address:move + screen:address<span class="Special"> <- </span><span class="Identifier">print</span>-board screen:address, 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board ] screen-should-contain [ <span class="Comment"># 012345678901234567890123456789</span> - <span class="Constant"> .8 | r n b q k b n r .</span> - <span class="Constant"> .7 | p p p p p p p p .</span> - <span class="Constant"> .6 | .</span> - <span class="Constant"> .5 | .</span> - <span class="Constant"> .4 | P .</span> - <span class="Constant"> .3 | .</span> - <span class="Constant"> .2 | P P P P P P P .</span> - <span class="Constant"> .1 | R N B Q K B N R .</span> - <span class="Constant"> . +---------------- .</span> - <span class="Constant"> . a b c d e f g h .</span> - <span class="Constant"> . .</span> + .8 | r n b q k b n r . + .7 | p p p p p p p p . + .6 | . + .5 | . + .4 | P . + .3 | . + .2 | P P P P P P P . + .1 | R N B Q K B N R . + . +---------------- . + . a b c d e f g h . + . . ] ] </pre> diff --git a/html/console.mu.html b/html/console.mu.html index 7f46529b..203cbd20 100644 --- a/html/console.mu.html +++ b/html/console.mu.html @@ -13,12 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Delimiter { color: #a04060; } .Special { color: #ff6060; } -.Constant { color: #00a0a0; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -31,18 +28,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <body> <pre id='vimCodeElement'> <span class="Comment"># example program: reading events from keyboard or mouse</span> -<span class="Comment">#</span> +# <span class="Comment"># Keeps printing 'a' until you press a key or click on the mouse.</span> -<span class="muRecipe">recipe</span> main [ +recipe main [ open-console - <span class="Delimiter">{</span> - _, found?:boolean<span class="Special"> <- </span>check-for-interaction - <span class="muControl">break-if</span> found? - print-character-to-display <span class="Constant">97</span>, <span class="Constant">7/white</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + { + e:event, found?:boolean<span class="Special"> <- </span>check-for-interaction + break-if found? + <span class="Identifier">print</span>-character-to-display 97, 7/white + loop + } close-console + $<span class="Identifier">print</span> e, 10/newline ] </pre> </body> diff --git a/html/counters.mu.html b/html/counters.mu.html index 9a02adca..45ca7a5d 100644 --- a/html/counters.mu.html +++ b/html/counters.mu.html @@ -13,11 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } +.Underlined { color: #c000c0; text-decoration: underline; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -32,36 +31,36 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># example program: maintain multiple counters with isolated lexical scopes</span> <span class="Comment"># (spaces)</span> -<span class="muRecipe">recipe</span> new-counter [ - <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span> - n:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="muControl">reply</span> <span class="Constant">default-space</span> +recipe <span class="Identifier">new</span>-counter [ + default-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30 + n:number<span class="Special"> <- </span>next-ingredient + reply default-space ] -<span class="muRecipe">recipe</span> increment-counter [ - <span class="Constant">local-scope</span> - <span class="Constant">0</span>:address:array:location/names:new-counter<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span> - x:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - n:number/space:<span class="Constant">1</span><span class="Special"> <- </span>add n:number/space:<span class="Constant">1</span>, x - <span class="muControl">reply</span> n:number/space:<span class="Constant">1</span> +recipe increment-counter [ + <span class="Underlined">local</span>-scope + 0:address:<span class="Identifier">array</span>:location/names:<span class="Identifier">new</span>-counter<span class="Special"> <- </span>next-ingredient <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span> + x:number<span class="Special"> <- </span>next-ingredient + n:number/space:1<span class="Special"> <- </span>add n:number/space:1, x + reply n:number/space:1 ] -<span class="muRecipe">recipe</span> main [ - <span class="Constant">local-scope</span> +recipe main [ + <span class="Underlined">local</span>-scope <span class="Comment"># counter A</span> - a:address:array:location<span class="Special"> <- </span>new-counter <span class="Constant">34</span> + a:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span>-counter 34 <span class="Comment"># counter B</span> - b:address:array:location<span class="Special"> <- </span>new-counter <span class="Constant">23</span> + b:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span>-counter 23 <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> - a-value:number<span class="Special"> <- </span>increment-counter a, <span class="Constant">1</span> + increment-counter a, 1 + b-value:number<span class="Special"> <- </span>increment-counter b, 2 + a-value:number<span class="Special"> <- </span>increment-counter a, 1 <span class="Comment"># check results</span> - $print <span class="Constant">[Contents of counters</span> -<span class="Constant">]</span> + $<span class="Identifier">print</span> [Contents of counters +] <span class="Comment"># trailing space in next line is to help with syntax highlighting</span> - $print <span class="Constant">[a: ]</span>, a-value, <span class="Constant">[ b: ]</span>, b-value, <span class="Constant">[ </span> -<span class="Constant">]</span> + $<span class="Identifier">print</span> [a: ], a-value, [ b: ], b-value, [ +] ] </pre> </body> diff --git a/html/display.mu.html b/html/display.mu.html index baf12e83..fea2d45a 100644 --- a/html/display.mu.html +++ b/html/display.mu.html @@ -13,11 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } --> </style> @@ -31,16 +29,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: managing the display</span> -<span class="muRecipe">recipe</span> main [ +recipe main [ open-console - print-character-to-display <span class="Constant">97</span>, <span class="Constant">1/red</span>, <span class="Constant">2/green</span> - <span class="Constant">1</span>:number/<span class="Special">raw</span>, <span class="Constant">2</span>:number/<span class="Special">raw <- </span>cursor-position-on-display + <span class="Identifier">print</span>-character-to-display 97, 1/red, 2/green + 1:number/<span class="Special">raw</span>, 2:number/<span class="Special">raw <- </span>cursor-position-on-display wait-for-some-interaction clear-display - move-cursor-on-display <span class="Constant">0</span>, <span class="Constant">4</span> - print-character-to-display <span class="Constant">98</span> + move-cursor-on-display 0, 4 + <span class="Identifier">print</span>-character-to-display 98 wait-for-some-interaction - move-cursor-on-display <span class="Constant">0</span>, <span class="Constant">0</span> + move-cursor-on-display 0, 0 clear-line-on-display wait-for-some-interaction move-cursor-down-on-display @@ -51,7 +49,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } wait-for-some-interaction move-cursor-up-on-display wait-for-some-interaction -<span class="CommentedCode">#? $print [aaa] #? 1</span> close-console ] </pre> diff --git a/html/factorial.mu.html b/html/factorial.mu.html index d3837c22..30cf628b 100644 --- a/html/factorial.mu.html +++ b/html/factorial.mu.html @@ -13,13 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.muScenario { color: #00af00; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -33,36 +30,36 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: compute the factorial of 5</span> -<span class="muRecipe">recipe</span> main [ - <span class="Constant">local-scope</span> - x:number<span class="Special"> <- </span>factorial <span class="Constant">5</span> - $print <span class="Constant">[result: ]</span>, x, <span class="Constant">[ </span> -<span class="Constant">]</span> +recipe main [ + <span class="Underlined">local</span>-scope + x:number<span class="Special"> <- </span>factorial 5 + $<span class="Identifier">print</span> [result: ], x, [ +] ] -<span class="muRecipe">recipe</span> factorial [ - <span class="Constant">local-scope</span> - n:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> +recipe factorial [ + <span class="Underlined">local</span>-scope + n:number<span class="Special"> <- </span>next-ingredient + { <span class="Comment"># if n=0 return 1</span> - zero?:boolean<span class="Special"> <- </span>equal n, <span class="Constant">0</span> - <span class="muControl">break-unless</span> zero? - <span class="muControl">reply</span> <span class="Constant">1</span> - <span class="Delimiter">}</span> + zero?:boolean<span class="Special"> <- </span>equal n, 0 + break-unless zero? + reply 1 + } <span class="Comment"># return n * factorial(n-1)</span> - x:number<span class="Special"> <- </span>subtract n, <span class="Constant">1</span> + x:number<span class="Special"> <- </span>subtract n, 1 subresult:number<span class="Special"> <- </span>factorial x result:number<span class="Special"> <- </span>multiply subresult, n - <span class="muControl">reply</span> result + reply result ] <span class="Comment"># unit test</span> -<span class="muScenario">scenario</span> factorial-test [ +scenario factorial-test [ run [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>factorial <span class="Constant">5</span> + 1:number<span class="Special"> <- </span>factorial 5 ] memory-should-contain [ - <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">120</span> + 1<span class="Special"> <- </span>120 ] ] </pre> diff --git a/html/fork.mu.html b/html/fork.mu.html index 09d02860..b75cceac 100644 --- a/html/fork.mu.html +++ b/html/fork.mu.html @@ -13,11 +13,8 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Identifier { color: #804000; } --> </style> @@ -31,19 +28,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: running multiple routines</span> -<span class="muRecipe">recipe</span> main [ - start-running <span class="Constant">thread2:recipe</span> - <span class="Delimiter">{</span> - $print <span class="Constant">34</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> +recipe main [ + start-running thread2:recipe + { + $<span class="Identifier">print</span> 34 + loop + } ] -<span class="muRecipe">recipe</span> thread2 [ - <span class="Delimiter">{</span> - $print <span class="Constant">35</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> +recipe thread2 [ + { + $<span class="Identifier">print</span> 35 + loop + } ] </pre> </body> diff --git a/html/global.mu.html b/html/global.mu.html index 6e2c0491..f94b215c 100644 --- a/html/global.mu.html +++ b/html/global.mu.html @@ -13,10 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -30,17 +29,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: creating and using global variables</span> -<span class="muRecipe">recipe</span> main [ +recipe main [ <span class="Comment"># allocate 5 locations for globals</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> + global-space:address:<span class="Identifier">array</span>:location<span class="Special"> <- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 5 <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> + 1:number/space:global<span class="Special"> <- </span><span class="Identifier">copy</span> 3 foo ] -<span class="muRecipe">recipe</span> foo [ +recipe foo [ <span class="Comment"># ditto for writing to globals</span> - $print <span class="Special">1:number/space:global</span> + $<span class="Identifier">print</span> 1:number/space:global ] </pre> </body> diff --git a/html/screen.mu.html b/html/screen.mu.html index 6efea923..72156547 100644 --- a/html/screen.mu.html +++ b/html/screen.mu.html @@ -13,10 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -29,30 +28,30 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <body> <pre id='vimCodeElement'> <span class="Comment"># example program: managing the display using 'screen' objects</span> -<span class="Comment">#</span> +# <span class="Comment"># The zero screen below means 'use the real screen'. Tests can also use fake</span> <span class="Comment"># screens.</span> -<span class="muRecipe">recipe</span> main [ +recipe main [ open-console - print-character <span class="Constant">0/screen</span>, <span class="Constant">97/a</span>, <span class="Constant">2/red</span> - <span class="Constant">1</span>:number/<span class="Special">raw</span>, <span class="Constant">2</span>:number/<span class="Special">raw <- </span>cursor-position <span class="Constant">0/screen</span> - wait-for-event <span class="Constant">0/console</span> - clear-screen <span class="Constant">0/screen</span> - move-cursor <span class="Constant">0/screen</span>, <span class="Constant">0/row</span>, <span class="Constant">4/column</span> - print-character <span class="Constant">0/screen</span>, <span class="Constant">98/b</span> - wait-for-event <span class="Constant">0/console</span> - move-cursor <span class="Constant">0/screen</span>, <span class="Constant">0/row</span>, <span class="Constant">0/column</span> - clear-line <span class="Constant">0/screen</span> - wait-for-event <span class="Constant">0/console</span> - cursor-down <span class="Constant">0/screen</span> - wait-for-event <span class="Constant">0/console</span> - cursor-right <span class="Constant">0/screen</span> - wait-for-event <span class="Constant">0/console</span> - cursor-left <span class="Constant">0/screen</span> - wait-for-event <span class="Constant">0/console</span> - cursor-up <span class="Constant">0/screen</span> - wait-for-event <span class="Constant">0/console</span> + <span class="Identifier">print</span>-character 0/screen, 97/a, 2/red + 1:number/<span class="Special">raw</span>, 2:number/<span class="Special">raw <- </span>cursor-position 0/screen + wait-for-event 0/console + clear-screen 0/screen + move-cursor 0/screen, 0/row, 4/column + <span class="Identifier">print</span>-character 0/screen, 98/b + wait-for-event 0/console + move-cursor 0/screen, 0/row, 0/column + clear-line 0/screen + wait-for-event 0/console + cursor-down 0/screen + wait-for-event 0/console + cursor-right 0/screen + wait-for-event 0/console + cursor-left 0/screen + wait-for-event 0/console + cursor-up 0/screen + wait-for-event 0/console close-console ] </pre> diff --git a/html/tangle.mu.html b/html/tangle.mu.html index e3dba023..aae321e8 100644 --- a/html/tangle.mu.html +++ b/html/tangle.mu.html @@ -13,12 +13,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } -.Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } -.Delimiter { color: #a04060; } -.muControl { color: #c0a020; } +.Comment { color: #9090ff; } +.Underlined { color: #c000c0; text-decoration: underline; } +.Identifier { color: #804000; } --> </style> @@ -31,40 +29,40 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <body> <pre id='vimCodeElement'> <span class="Comment"># example program: constructing recipes out of order</span> -<span class="Comment">#</span> +# <span class="Comment"># We construct a factorial function with separate base and recursive cases.</span> <span class="Comment"># Compare factorial.mu.</span> -<span class="Comment">#</span> +# <span class="Comment"># This isn't a very tasteful example, just a simple demonstration of</span> <span class="Comment"># possibilities.</span> -<span class="muRecipe">recipe</span> factorial [ - <span class="Constant">local-scope</span> - n:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> -<span class="Constant"> +base-case</span> - <span class="Delimiter">}</span> -<span class="Constant"> +recursive-case</span> +recipe factorial [ + <span class="Underlined">local</span>-scope + n:number<span class="Special"> <- </span>next-ingredient + { + +base-case + } + +recursive-case ] -<span class="muRecipe">after</span> +base-case [ +after +base-case [ <span class="Comment"># if n=0 return 1</span> - zero?:boolean<span class="Special"> <- </span>equal n, <span class="Constant">0</span> - <span class="muControl">break-unless</span> zero? - <span class="muControl">reply</span> <span class="Constant">1</span> + zero?:boolean<span class="Special"> <- </span>equal n, 0 + break-unless zero? + reply 1 ] -<span class="muRecipe">after</span> +recursive-case [ +after +recursive-case [ <span class="Comment"># return n * factorial(n - 1)</span> - x:number<span class="Special"> <- </span>subtract n, <span class="Constant">1</span> + x:number<span class="Special"> <- </span>subtract n, 1 subresult:number<span class="Special"> <- </span>factorial x result:number<span class="Special"> <- </span>multiply subresult, n - <span class="muControl">reply</span> result + reply result ] -<span class="muRecipe">recipe</span> main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>factorial <span class="Constant">5</span> - $print <span class="Constant">[result: ]</span>, <span class="Constant">1</span>:number, [ +recipe main [ + 1:number<span class="Special"> <- </span>factorial 5 + $<span class="Identifier">print</span> [result: ], 1:number, [ ] ] </pre> diff --git a/html/x.mu.html b/html/x.mu.html index 7ff0e1aa..aa8162bc 100644 --- a/html/x.mu.html +++ b/html/x.mu.html @@ -13,10 +13,9 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.muRecipe { color: #ff8700; } .Comment { color: #9090ff; } -.Constant { color: #00a0a0; } .Special { color: #ff6060; } +.Identifier { color: #804000; } --> </style> @@ -30,11 +29,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <pre id='vimCodeElement'> <span class="Comment"># example program: add two numbers</span> -<span class="muRecipe">recipe</span> main [ - <span class="Constant">11</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> - <span class="Constant">12</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> - <span class="Constant">13</span>:number<span class="Special"> <- </span>add <span class="Constant">11</span>:number, <span class="Constant">12</span>:number -<span class="Constant"> $dump-memory</span> +recipe main [ + 11:number<span class="Special"> <- </span><span class="Identifier">copy</span> 1 + 12:number<span class="Special"> <- </span><span class="Identifier">copy</span> 3 + 13:number<span class="Special"> <- </span>add 11:number, 12:number + $dump-memory ] </pre> </body> |