diff options
Diffstat (limited to 'html')
33 files changed, 1180 insertions, 260 deletions
diff --git a/html/010vm.cc.html b/html/010vm.cc.html index 976edf51..69d5dec0 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -295,7 +295,7 @@ reagent::reagent<span class="Delimiter">(</span>string s<span class="Delimiter"> <span class="Delimiter">}</span> string_tree* parse_property_list<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> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span> string_tree* result = new string_tree<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span> result<span class="Delimiter">-></span>right = parse_property_list<span class="Delimiter">(</span>in<span class="Delimiter">);</span> @@ -557,9 +557,16 @@ void dump<span class="Delimiter">(</span>const string_tree* x<span class="Delimi out << <span class="Constant">')'</span><span class="Delimiter">;</span> <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>in && 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">:(before "End Globals")</span> +const string Ignore<span class="Delimiter">(</span><span class="Constant">","</span><span class="Delimiter">);</span> <span class="Comment">// commas are ignored in mu except within [] strings</span> +<span class="Delimiter">:(code)</span> +void skip_whitespace_but_not_newline<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>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + else if <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="Identifier">break</span><span class="Delimiter">;</span> + else 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>Ignore<span class="Delimiter">.</span>find<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> != string::npos<span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + else <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> diff --git a/html/011load.cc.html b/html/011load.cc.html index 7296d1bb..e3be7973 100644 --- a/html/011load.cc.html +++ b/html/011load.cc.html @@ -16,6 +16,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .traceContains { color: #008000; } .traceAbsent { color: #c00000; } .cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -77,7 +78,7 @@ vector<recipe_ordinal> load<span class="Delimiter">(</span>istream& in long long int slurp_recipe<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe result<span class="Delimiter">;</span> result<span class="Delimiter">.</span>name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Comment">// End recipe Refinements</span> if <span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise_error << <span class="Constant">"empty result.name</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> @@ -95,16 +96,17 @@ long long int slurp_recipe<span class="Delimiter">(</span>istream& in<span c <span class="Comment">// End recipe Body(result)</span> get_or_insert<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">))</span> = result<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>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">));</span> +<span class="CommentedCode">//? LOG << "recently added recipe: " << result.name << ' ' << get(Recipe_ordinal, result.name) << '\n';</span> + Recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">));</span> <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> <span class="Delimiter">}</span> void slurp_body<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> recipe& result<span class="Delimiter">)</span> <span class="Delimiter">{</span> in >> std::noskipws<span class="Delimiter">;</span> - skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> raise_error << <span class="Constant">"recipe body must begin with '['</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Comment">// permit trailing comment after '['</span> 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, recipe result)</span> @@ -116,31 +118,22 @@ void slurp_body<span class="Delimiter">(</span>istream& in<span class="Delim bool next_instruction<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> instruction* curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> curr<span class="Delimiter">-></span>clear<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise_error << <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> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise_error << <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> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise_error << <span class="Constant">"2: unbalanced '[' for recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise_error << <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> vector<string> words<span class="Delimiter">;</span> while <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<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> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise_error << <span class="Constant">"3: unbalanced '[' for recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise_error << <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> 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> + skip_whitespace_but_not_newline<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> 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> @@ -193,20 +186,17 @@ 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> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - skip_ignored_characters<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Comment">// End next_word Special-cases</span> ostringstream out<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> + skip_whitespace_and_comments_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Globals")</span> <span class="Comment">// word boundaries</span> -string Terminators<span class="Delimiter">(</span><span class="Constant">"(){}"</span><span class="Delimiter">);</span> -string Ignore<span class="Delimiter">(</span><span class="Constant">","</span><span class="Delimiter">);</span> <span class="Comment">// meaningless except within [] strings</span> +const string Terminators<span class="Delimiter">(</span><span class="Constant">"(){}"</span><span class="Delimiter">);</span> <span class="Delimiter">:(code)</span> void slurp_word<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> char c<span class="Delimiter">;</span> @@ -224,17 +214,23 @@ void slurp_word<span class="Delimiter">(</span>istream& in<span class="Delim <span class="Delimiter">}</span> <span class="Delimiter">}</span> -void skip_ignored_characters<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> || Ignore<span class="Delimiter">.</span>find<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span> - in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> +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>!has_data<span class="Delimiter">(</span>in<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>Ignore<span class="Delimiter">.</span>find<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> != string::npos<span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + else <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -void skip_whitespace_and_comments<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Comment">// confusing; move to the next line only to skip a comment, but never otherwise</span> +void skip_whitespace_and_comments_but_not_newline<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>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + if <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="Identifier">break</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()))</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> - else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + else if <span class="Delimiter">(</span>Ignore<span class="Delimiter">.</span>find<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> != string::npos<span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> else <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -274,19 +270,23 @@ void show_rest_of_stream<span class="Delimiter">(</span>istream& in<span cla <span class="Comment">//: Have tests clean up any recipes they added.</span> <span class="Delimiter">:(before "End Globals")</span> -vector<recipe_ordinal> recently_added_recipes<span class="Delimiter">;</span> +vector<recipe_ordinal> Recently_added_recipes<span class="Delimiter">;</span> 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> - 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="Comment">// don't renumber existing recipes, like 'interactive'</span> - && contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Comment">// in case previous test had duplicate definitions</span> - Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> - Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> +clear_recently_added_recipes<span class="Delimiter">();</span> +<span class="Delimiter">:(code)</span> +void clear_recently_added_recipes<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>Recently_added_recipes<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> >= Reserved_for_tests <span class="Comment">// don't renumber existing recipes, like 'interactive'</span> + && contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Comment">// in case previous test had duplicate definitions</span> + Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> +<span class="CommentedCode">//? LOG << "erase recipe " << Recently_added_recipes.at(i) << ' ' << get(Recipe, Recently_added_recipes.at(i)).name << '\n';</span> + Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Comment">// Clear Other State For Recently_added_recipes</span> + Recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">}</span> -<span class="Comment">// Clear Other State For recently_added_recipes</span> -recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> -<span class="Delimiter">:(code)</span> <span class="Delimiter">:(scenario parse_comment_outside_recipe)</span> <span class="Comment"># this comment will be dropped by the tangler, so we need a dummy recipe to stop that</span> recipe f1 [ ] diff --git a/html/013update_operation.cc.html b/html/013update_operation.cc.html index 7a6c5f78..a84aff0d 100644 --- a/html/013update_operation.cc.html +++ b/html/013update_operation.cc.html @@ -39,15 +39,17 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Delimiter">:(code)</span> void update_instruction_operations<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- compute instruction operations for recipe "</span> << get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << "--- compute instruction operations for recipe " << get(Recipe, r).name << '\n';</span> - for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - instruction& inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> +<span class="CommentedCode">//? cerr << "--- compute instruction operations for recipe " << caller.name << '\n';</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction& inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise_error << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"instruction "</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" has no recipe</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"instruction "</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" has no recipe</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> inst<span class="Delimiter">.</span>operation = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + <span class="Comment">// End Instruction Operation Checks</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> diff --git a/html/014literal_string.cc.html b/html/014literal_string.cc.html index 024a0efc..157b2fa4 100644 --- a/html/014literal_string.cc.html +++ b/html/014literal_string.cc.html @@ -57,8 +57,7 @@ put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Delimiter">:(before "End next_word Special-cases")</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string result = slurp_quoted<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_and_comments_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/020run.cc.html b/html/020run.cc.html index e5ee3061..d0213a69 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -256,7 +256,7 @@ void load_permanently<span class="Delimiter">(</span>string filename<span class= load<span class="Delimiter">(</span>fin<span class="Delimiter">);</span> fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span> <span class="Comment">// freeze everything so it doesn't get cleared by tests</span> - recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + Recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Comment">// End load_permanently.</span> <span class="Delimiter">}</span> diff --git a/html/029tools.cc.html b/html/029tools.cc.html index 4b78fe12..5355d922 100644 --- a/html/029tools.cc.html +++ b/html/029tools.cc.html @@ -16,6 +16,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .traceContains { color: #008000; } .SalientComment { color: #00ffff; } .cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } @@ -335,6 +336,32 @@ case _DUMP_MEMORY: <span class="Delimiter">{</span> dump_memory<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + +<span class="Comment">//: In times of real extremis we need to create a whole new modality for debug</span> +<span class="Comment">//: logs, independent of other changes to the screen or Trace_stream.</span> + +<span class="Delimiter">:(before "End Globals")</span> +ofstream LOG<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End One-time Setup")</span> +<span class="CommentedCode">//? LOG.open("log");</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_LOG<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$log"</span><span class="Delimiter">,</span> _LOG<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +case _LOG: <span class="Delimiter">{</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case _LOG: <span class="Delimiter">{</span> + ostringstream out<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << print_mu<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + LOG << out<span class="Delimiter">.</span>str<span class="Delimiter">()</span> << <span class="Constant">"(length: "</span> << get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"length"</span><span class="Delimiter">)</span> << <span class="Constant">'/'</span> << contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"length"</span><span class="Delimiter">))</span> << <span class="Constant">")</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/030container.cc.html b/html/030container.cc.html index 8ef0dda6..77c582c7 100644 --- a/html/030container.cc.html +++ b/html/030container.cc.html @@ -171,7 +171,7 @@ case GET: <span class="Delimiter">{</span> <span class="Delimiter">}</span> reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// new copy for every invocation</span> <span class="Comment">// Update GET base in Check</span> - if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise_error << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'get' should be a container, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -309,7 +309,7 @@ case GET_ADDRESS: <span class="Delimiter">{</span> <span class="Delimiter">}</span> reagent base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// Update GET_ADDRESS base in Check</span> - if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type || !base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise_error << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'get-address' should be a container, but got "</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -438,7 +438,7 @@ else if <span class="Delimiter">(</span>command == <span class="Constant">" <span class="Delimiter">:(code)</span> void insert_container<span class="Delimiter">(</span>const string& command<span class="Delimiter">,</span> kind_of_type kind<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> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Comment">// End container Name Refinements</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"--- defining "</span> << command << <span class="Constant">' '</span> << name << end<span class="Delimiter">();</span> @@ -449,7 +449,7 @@ void insert_container<span class="Delimiter">(</span>const string& command<s trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"type number: "</span> << get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">"'container' must begin with '['"</span><span class="Delimiter">);</span> type_info& info = get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">));</span> - recently_added_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">));</span> + Recently_added_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">));</span> info<span class="Delimiter">.</span>name = name<span class="Delimiter">;</span> info<span class="Delimiter">.</span>kind = kind<span class="Delimiter">;</span> while <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> @@ -505,22 +505,22 @@ recipe main [ <span class="Comment">//: ensure types created in one scenario don't leak outside it.</span> <span class="Delimiter">:(before "End Globals")</span> -vector<type_ordinal> recently_added_types<span class="Delimiter">;</span> +vector<type_ordinal> Recently_added_types<span class="Delimiter">;</span> <span class="Delimiter">:(before "End load_permanently")</span> <span class="Comment">//: for non-tests</span> -recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">:(before "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> - if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> +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> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + Type_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> <span class="Comment">// todo: why do I explicitly need to provide this?</span> - for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>Type<span class="Delimiter">.</span>at<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>elements<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> - delete Type<span class="Delimiter">.</span>at<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>Type<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>elements<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + delete Type<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> <span class="Delimiter">}</span> - Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> -recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Comment">// delete recent type references</span> -<span class="Comment">// can't rely on recently_added_types to cleanup Type_ordinal, because of deliberately misbehaving tests with references to undefined types</span> +<span class="Comment">// can't rely on Recently_added_types to cleanup Type_ordinal, because of deliberately misbehaving tests with references to undefined types</span> map<string<span class="Delimiter">,</span> type_ordinal>::iterator p = Type_ordinal<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> while<span class="Delimiter">(</span>p != Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> <span class="Comment">// save current item</span> @@ -568,17 +568,19 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Delimiter">:(code)</span> void check_or_set_invalid_types<span class="Delimiter">(</span>const recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction& inst = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction& inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> check_or_set_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> - maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">),</span> <span class="Constant">"'"</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">"'"</span><span class="Delimiter">);</span> + maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">"'"</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">"'"</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>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> check_or_set_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> - maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">),</span> <span class="Constant">"'"</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">"'"</span><span class="Delimiter">);</span> + maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">"'"</span>+inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span>+<span class="Constant">"'"</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + <span class="Comment">// End check_or_set_invalid_types</span> <span class="Delimiter">}</span> void check_or_set_invalid_types<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> const string_tree* type_name<span class="Delimiter">,</span> const string& block<span class="Delimiter">,</span> const string& name<span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/031address.cc.html b/html/031address.cc.html index 5a58fc2f..cabdc541 100644 --- a/html/031address.cc.html +++ b/html/031address.cc.html @@ -96,6 +96,13 @@ void lookup_memory<span class="Delimiter">(</span>reagent& x<span class="Del drop_one_lookup<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario canonize_non_pointer_fails_without_crashing)</span> +<span class="Special">% Hide_errors = true;</span> +recipe foo [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset +] +<span class="Comment"># don't crash</span> + <span class="Delimiter">:(after "bool types_strictly_match(reagent lhs, reagent rhs)")</span> if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> @@ -123,6 +130,10 @@ bool canonize_type<span class="Delimiter">(</span>reagent& r<span class="Del <span class="Delimiter">}</span> void drop_address_from_type<span class="Delimiter">(</span>reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error << <span class="Constant">"can't drop address from "</span> << debug_string<span class="Delimiter">(</span>r<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> type_tree* tmp = r<span class="Delimiter">.</span>type<span class="Delimiter">;</span> r<span class="Delimiter">.</span>type = tmp<span class="Delimiter">-></span>right<span class="Delimiter">;</span> tmp<span class="Delimiter">-></span>right = <span class="Constant">NULL</span><span class="Delimiter">;</span> diff --git a/html/036call_reply.cc.html b/html/036call_reply.cc.html index 1784c8f9..dac5314a 100644 --- a/html/036call_reply.cc.html +++ b/html/036call_reply.cc.html @@ -51,60 +51,29 @@ REPLY<span class="Delimiter">,</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"reply"</span><span class="Delimiter">,</span> REPLY<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> case REPLY: <span class="Delimiter">{</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// continue to process rest of *caller* instruction</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// checks will be performed by a transform below</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> case REPLY: <span class="Delimiter">{</span> <span class="Comment">// Starting Reply</span> - const instruction& reply_inst = current_instruction<span class="Delimiter">();</span> <span class="Comment">// save pointer into recipe before pop</span> - const string& callee = current_recipe_name<span class="Delimiter">();</span> if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"trace"</span><span class="Delimiter">)</span> << <span class="Constant">"reply: decrementing callstack depth from "</span> << Trace_stream<span class="Delimiter">-></span>callstack_depth << end<span class="Delimiter">();</span> --Trace_stream<span class="Delimiter">-></span>callstack_depth<span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>callstack_depth >= <span class="Constant">0</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>callstack_depth < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + <span class="Identifier">goto</span> stop_running_current_routine<span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>pop_front<span class="Delimiter">();</span> <span class="Comment">// just in case 'main' returns a value, drop it for now</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">goto</span> stop_running_current_routine<span class="Delimiter">;</span> const instruction& caller_instruction = current_instruction<span class="Delimiter">();</span> - <span class="Comment">// check types with the caller</span> - if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">)</span> > SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise_error << <span class="Constant">"too few values replied from "</span> << callee << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise_error << maybe<span class="Delimiter">(</span>callee<span class="Delimiter">)</span> << <span class="Constant">"reply ingredient "</span> << reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string << <span class="Constant">" can't be saved in "</span> << caller_instruction<span class="Delimiter">.</span>products<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> - reagent lhs = reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> - reagent rhs = caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> - canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">);</span> - raise_error << debug_string<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" vs "</span> << debug_string<span class="Delimiter">(</span>rhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Comment">// End reply Type Mismatch Error</span> - <span class="Identifier">goto</span> finish_reply<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>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"result "</span> << i << <span class="Constant">" is "</span> << to_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> << end<span class="Delimiter">();</span> + <span class="Comment">// make reply products available to caller</span> copy<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> ingredients<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>products<span class="Delimiter">,</span> products<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> - <span class="Comment">// check that any reply ingredients with /same-as-ingredient connect up</span> - <span class="Comment">// the corresponding ingredient and product in the caller.</span> - for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"result "</span> << i << <span class="Constant">" is "</span> << to_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> << end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"same-as-ingredient"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> - string_tree* tmp = property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"same-as-ingredient"</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>!tmp || tmp<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise_error << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'same-as-ingredient' metadata should take exactly one value in "</span> << reply_inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - <span class="Identifier">goto</span> finish_reply<span class="Delimiter">;</span> - <span class="Delimiter">}</span> - long long int ingredient_index = to_integer<span class="Delimiter">(</span>tmp<span class="Delimiter">-></span>value<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>ingredient_index >= SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> - raise_error << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'same-as-ingredient' metadata overflows ingredients in: "</span> << caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> - if <span class="Delimiter">(</span>!is_dummy<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> && caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>value != caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>value<span class="Delimiter">)</span> - raise_error << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"'"</span> << caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' should write to "</span> << caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>original_string << <span class="Constant">" rather than "</span> << caller_instruction<span class="Delimiter">.</span>products<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> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> <span class="Comment">// End Reply</span> - finish_reply: <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// continue to process rest of *caller* instruction</span> <span class="Delimiter">}</span> @@ -122,6 +91,60 @@ recipe f [ <span class="traceContains">+mem: storing 2 in location 3</span> <span class="traceContains">+mem: storing 35 in location 4</span> +<span class="Comment">//: Types in reply instructions are checked ahead of time.</span> + +<span class="Delimiter">:(before "End Checks")</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_types_of_reply_instructions<span class="Delimiter">);</span> +<span class="Delimiter">:(code)</span> +void check_types_of_reply_instructions<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<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>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& caller_instruction = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>operation < MAX_PRIMITIVE_RECIPES<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + const recipe& callee = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> caller_instruction<span class="Delimiter">.</span>operation<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>callee<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& reply_inst = callee<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>operation != REPLY<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// check types with the caller</span> + if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">)</span> > SIZE<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"too few values replied from "</span> << callee<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise_error << maybe<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"reply ingredient "</span> << reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string << <span class="Constant">" can't be saved in "</span> << caller_instruction<span class="Delimiter">.</span>products<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> + reagent lhs = reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + reagent rhs = caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">);</span> + raise_error << debug_string<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="Constant">" vs "</span> << debug_string<span class="Delimiter">(</span>rhs<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Comment">// End reply Type Mismatch Error</span> + <span class="Identifier">goto</span> finish_reply_check<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Comment">// check that any reply ingredients with /same-as-ingredient connect up</span> + <span class="Comment">// the corresponding ingredient and product in the caller.</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"same-as-ingredient"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + string_tree* tmp = property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"same-as-ingredient"</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!tmp || tmp<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'same-as-ingredient' metadata should take exactly one value in "</span> << reply_inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">goto</span> finish_reply_check<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + long long int ingredient_index = to_integer<span class="Delimiter">(</span>tmp<span class="Delimiter">-></span>value<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>ingredient_index >= SIZE<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'same-as-ingredient' metadata overflows ingredients in: "</span> << caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>!is_dummy<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> && caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name != caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>name<span class="Delimiter">)</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"'"</span> << caller_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' should write to "</span> << caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>original_string << <span class="Constant">" rather than "</span> << caller_instruction<span class="Delimiter">.</span>products<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> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + finish_reply_check:<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario reply_type_mismatch)</span> <span class="Special">% Hide_errors = true;</span> recipe main [ diff --git a/html/042name.cc.html b/html/042name.cc.html index aa0a1fe9..08b875ef 100644 --- a/html/042name.cc.html +++ b/html/042name.cc.html @@ -59,9 +59,9 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Delimiter">:(before "End Globals")</span> map<recipe_ordinal<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> long long int> > Name<span class="Delimiter">;</span> -<span class="Delimiter">:(after "Clear Other State For recently_added_recipes")</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> - Name<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> +<span class="Delimiter">:(after "Clear Other State For Recently_added_recipes")</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> + Name<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> diff --git a/html/054dilated_reagent.cc.html b/html/054dilated_reagent.cc.html index 02f714e4..1d908069 100644 --- a/html/054dilated_reagent.cc.html +++ b/html/054dilated_reagent.cc.html @@ -67,7 +67,7 @@ bool start_of_dilated_reagent<span class="Delimiter">(</span>istream& in<spa if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'{'</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> long long int pos = in<span class="Delimiter">.</span>tellg<span class="Delimiter">();</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Comment">// slurp '{'</span> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> char next = in<span class="Delimiter">.</span>peek<span class="Delimiter">();</span> in<span class="Delimiter">.</span>seekg<span class="Delimiter">(</span>pos<span class="Delimiter">);</span> <span class="Identifier">return</span> next != <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> diff --git a/html/055parse_tree.cc.html b/html/055parse_tree.cc.html index 14142686..1d97dee4 100644 --- a/html/055parse_tree.cc.html +++ b/html/055parse_tree.cc.html @@ -60,7 +60,7 @@ string_tree* parse_string_tree<span class="Delimiter">(</span>const string& <span class="Delimiter">}</span> string_tree* parse_string_tree<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> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> @@ -76,8 +76,7 @@ string_tree* parse_string_tree<span class="Delimiter">(</span>istream& in<sp while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">));</span> *curr = new string_tree<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> - skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> - skip_ignored_characters<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'('</span><span class="Delimiter">)</span> <span class="Delimiter">(</span>*curr<span class="Delimiter">)-></span>left = parse_string_tree<span class="Delimiter">(</span>in<span class="Delimiter">);</span> else diff --git a/html/056recipe_header.cc.html b/html/056recipe_header.cc.html index a1c6dd82..08cc8fdd 100644 --- a/html/056recipe_header.cc.html +++ b/html/056recipe_header.cc.html @@ -13,16 +13,17 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } -.traceContains { color: #008000; } .SalientComment { color: #00ffff; } -.cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } +.Error { color: #ffffff; background-color: #ff6060; padding-bottom: 1px; } +.Delimiter { color: #a04060; } +.traceContains { color: #008000; } .traceAbsent { color: #c00000; } +.cSpecial { color: #008000; } .Comment { color: #9090ff; } -.Delimiter { color: #a04060; } +.Constant { color: #00a0a0; } .Special { color: #ff6060; } .Identifier { color: #804000; } -.Constant { color: #00a0a0; } -.CommentedCode { color: #6c6c6c; } --> </style> @@ -59,7 +60,6 @@ vector<reagent> products<span class="Delimiter">;</span> has_header = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End recipe Refinements")</span> -skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"recipe has a header; parsing"</span> << end<span class="Delimiter">();</span> load_recipe_header<span class="Delimiter">(</span>in<span class="Delimiter">,</span> result<span class="Delimiter">);</span> @@ -68,18 +68,18 @@ if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span c <span class="Delimiter">:(code)</span> void load_recipe_header<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> recipe& result<span class="Delimiter">)</span> <span class="Delimiter">{</span> result<span class="Delimiter">.</span>has_header = <span class="Constant">true</span><span class="Delimiter">;</span> - while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">)</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string s = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>s == <span class="Constant">"->"</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> result<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>s<span class="Delimiter">));</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"header ingredient: "</span> << result<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>back<span class="Delimiter">().</span>original_string << end<span class="Delimiter">();</span> - skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Delimiter">}</span> - while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">)</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'['</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string s = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> result<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>s<span class="Delimiter">));</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"header product: "</span> << result<span class="Delimiter">.</span>products<span class="Delimiter">.</span>back<span class="Delimiter">().</span>original_string << end<span class="Delimiter">();</span> - skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// End Load Recipe Header(result)</span> <span class="Delimiter">}</span> @@ -108,6 +108,34 @@ recipe bar [ ] <span class="traceContains">+mem: storing 4 in location 1</span> +<span class="Delimiter">:(scenario recipe_handles_missing_bracket)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main +<span class="Error">]</span> +<span class="traceContains">+error: recipe body must begin with '['</span> + +<span class="Delimiter">:(scenario recipe_handles_missing_bracket_2)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main + local-scope + <span class="Delimiter">{</span> + <span class="Delimiter">}</span> +<span class="Error">]</span> +<span class="Comment"># doesn't overflow line when reading header</span> +<span class="traceAbsent">-parse: header ingredient: local-scope</span> +<span class="traceContains">+error: recipe body must begin with '['</span> + +<span class="Delimiter">:(scenario recipe_handles_missing_bracket_3)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main <span class="Comment"># comment</span> + local-scope + <span class="Delimiter">{</span> + <span class="Delimiter">}</span> +<span class="Error">]</span> +<span class="Comment"># doesn't overflow line when reading header</span> +<span class="traceAbsent">-parse: header ingredient: local-scope</span> +<span class="traceContains">+error: recipe body must begin with '['</span> + <span class="Delimiter">:(after "Begin debug_string(recipe x)")</span> out << <span class="Constant">"ingredients:</span><span class="cSpecial">\n</span><span class="Constant">"</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>x<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> diff --git a/html/057static_dispatch.cc.html b/html/057static_dispatch.cc.html index 1c7b28b7..04d02ab2 100644 --- a/html/057static_dispatch.cc.html +++ b/html/057static_dispatch.cc.html @@ -15,12 +15,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .traceContains { color: #008000; } .traceAbsent { color: #c00000; } +.Identifier { color: #804000; } .cSpecial { color: #008000; } -.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.Identifier { color: #804000; } +.CommentedCode { color: #6c6c6c; } .Constant { color: #00a0a0; } --> </style> @@ -56,10 +56,10 @@ recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delim map<string<span class="Delimiter">,</span> vector<recipe_ordinal> > Recipe_variants<span class="Delimiter">;</span> <span class="Delimiter">:(before "End One-time Setup")</span> put<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> <span class="Constant">"main"</span><span class="Delimiter">,</span> vector<recipe_ordinal><span class="Delimiter">());</span> <span class="Comment">// since we manually added main to Recipe_ordinal</span> -<span class="Delimiter">:(before "End Setup")</span> +<span class="Delimiter">:(before "Clear Other State For Recently_added_recipes")</span> for <span class="Delimiter">(</span>map<string<span class="Delimiter">,</span> vector<recipe_ordinal> >::iterator p = Recipe_variants<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe_variants<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> >= Reserved_for_tests<span class="Delimiter">)</span> + if <span class="Delimiter">(</span>find<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> Recently_added_recipes<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> != Recently_added_recipes<span class="Delimiter">.</span>end<span class="Delimiter">())</span> p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// just leave a ghost</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -67,30 +67,41 @@ for <span class="Delimiter">(</span>map<string<span class="Delimiter">,</span <span class="Delimiter">:(before "End Load Recipe Header(result)")</span> if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> const recipe_ordinal r = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> - if <span class="Delimiter">((</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>has_header<span class="Delimiter">)</span> - && !variant_already_exists<span class="Delimiter">(</span>result<span class="Delimiter">))</span> <span class="Delimiter">{</span> - string new_name = next_unused_recipe_name<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> - put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> - get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">));</span> +<span class="CommentedCode">//? LOG << "checking " << r << " " << result.name << '\n';</span> +<span class="CommentedCode">//? cerr << result.name << ": " << contains_key(Recipe, r) << (contains_key(Recipe, r) ? get(Recipe, r).has_header : 0) << matching_variant_name(result) << '\n';</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>has_header<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string new_name = matching_variant_name<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>new_name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + <span class="Comment">// variant doesn't already exist</span> + new_name = next_unused_recipe_name<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> +<span class="CommentedCode">//? LOG << "adding a variant of " << result.name << ": " << new_name << " is now " << Next_recipe_ordinal << '\n';</span> + put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> + get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">));</span> + <span class="Delimiter">}</span> result<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> +<span class="CommentedCode">//? cerr << "=> " << new_name << '\n';</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// save first variant</span> +<span class="CommentedCode">//? LOG << "saving first variant of " << result.name << ": " << Next_recipe_ordinal << '\n';</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> -bool variant_already_exists<span class="Delimiter">(</span>const recipe& rr<span class="Delimiter">)</span> <span class="Delimiter">{</span> +string matching_variant_name<span class="Delimiter">(</span>const recipe& rr<span class="Delimiter">)</span> <span class="Delimiter">{</span> const vector<recipe_ordinal>& variants = get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> rr<span class="Delimiter">.</span>name<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> - && all_reagents_match<span class="Delimiter">(</span>rr<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))))</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> +<span class="CommentedCode">//? LOG << "checking variant " << variants.at(i) << " of " << rr.name << '\n';</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + const recipe& candidate = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>!all_reagents_match<span class="Delimiter">(</span>rr<span class="Delimiter">,</span> candidate<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? LOG << " exists\n";</span> + <span class="Identifier">return</span> candidate<span class="Delimiter">.</span>name<span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? LOG << " does not exist\n";</span> + <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> bool all_reagents_match<span class="Delimiter">(</span>const recipe& r1<span class="Delimiter">,</span> const recipe& r2<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -155,6 +166,17 @@ recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delim ] <span class="traceContains">+mem: storing 2 in location 7</span> +<span class="Comment">//: support recipe headers in a previous transform to fill in missing types</span> +<span class="Delimiter">:(before "End check_or_set_invalid_types")</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>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + check_or_set_invalid_types<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> + maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">"recipe header ingredient"</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>caller<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + check_or_set_invalid_types<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> + maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">"recipe header product"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + <span class="Comment">//: after filling in all missing types (because we'll be introducing 'blank' types in this transform in a later layer, for shape-shifting recipes)</span> <span class="Delimiter">:(after "End Type Modifying Transforms")</span> Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>resolve_ambiguous_calls<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> @@ -188,6 +210,9 @@ void replace_best_variant<span class="Delimiter">(</span>instruction& inst<s <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// End Instruction Dispatch(inst, best_score)</span> + if <span class="Delimiter">(</span>best_score == -<span class="Constant">1</span> && get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">)</span> >= MAX_PRIMITIVE_RECIPES<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error << maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"failed to find a matching call for '"</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="Delimiter">}</span> <span class="Delimiter">}</span> long long int variant_score<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> recipe_ordinal variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -235,6 +260,7 @@ long long int variant_score<span class="Delimiter">(</span>const instruction& <span class="Delimiter">}</span> const vector<reagent>& header_products = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>header_products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"mismatch: product "</span> << i << end<span class="Delimiter">();</span> <span class="CommentedCode">//? cerr << "mismatch: product " << i << '\n';</span> @@ -302,6 +328,55 @@ recipe equal x:number<span class="Delimiter">,</span> y:number <span class="Deli <span class="Comment"># comparing booleans continues to use primitive</span> <span class="traceContains">+mem: storing 1 in location 6</span> +<span class="Delimiter">:(scenario static_dispatch_works_with_dummy_results_for_containers)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + _<span class="Special"> <- </span>test <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> +] +recipe test a:number <span class="Delimiter">-></span> z:point [ + local-scope + load-ingredients + z<span class="Special"> <- </span>merge a<span class="Delimiter">,</span> <span class="Constant">0</span> +] +recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-></span> z:point [ + local-scope + load-ingredients + z<span class="Special"> <- </span>merge a<span class="Delimiter">,</span> b +] +$error: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_first_use)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + x:address:foo<span class="Special"> <- </span>new foo:type + test x +] +container foo [ + x:number +] +recipe test a:address:foo <span class="Delimiter">-></span> z:number [ + local-scope + load-ingredients + z:number<span class="Special"> <- </span>get *a<span class="Delimiter">,</span> x:offset +] +$error: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_second_use)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + x:address:foo<span class="Special"> <- </span>new foo:type + test x +] +recipe test a:address:foo <span class="Delimiter">-></span> z:number [ + local-scope + load-ingredients + z:number<span class="Special"> <- </span>get *a<span class="Delimiter">,</span> x:offset +] +container foo [ + x:number +] +$error: <span class="Constant">0</span> + <span class="Delimiter">:(scenario static_dispatch_prefers_literals_to_be_numbers_rather_than_addresses)</span> recipe main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>foo <span class="Constant">0</span> @@ -428,6 +503,30 @@ string header_label<span class="Delimiter">(</span>recipe_ordinal r<span class=" out << <span class="Constant">' '</span> << caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string<span class="Delimiter">;</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario reload_variant_retains_other_variants)</span> +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>foo <span class="Constant">1</span>:number +] +recipe foo x:number <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">34</span> +] +recipe foo x:address:number <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +recipe! foo x:address:number <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">36</span> +] +<span class="traceContains">+mem: storing 34 in location 2</span> +$error: <span class="Constant">0</span> +$warn: <span class="Constant">0</span> </pre> </body> </html> diff --git a/html/059shape_shifting_recipe.cc.html b/html/059shape_shifting_recipe.cc.html index ce450999..4b895042 100644 --- a/html/059shape_shifting_recipe.cc.html +++ b/html/059shape_shifting_recipe.cc.html @@ -79,20 +79,20 @@ if <span class="Delimiter">(</span>contains_type_ingredient_name<span class="Del <span class="Comment">//: *specializing* existing recipes.</span> <span class="Comment">//:</span> <span class="Comment">//: Keep track of these new recipes in a separate variable in addition to</span> -<span class="Comment">//: recently_added_recipes, so that edit/ can clear them before reloading to</span> +<span class="Comment">//: Recently_added_recipes, so that edit/ can clear them before reloading to</span> <span class="Comment">//: regenerate errors.</span> <span class="Delimiter">:(before "End Globals")</span> -vector<recipe_ordinal> recently_added_shape_shifting_recipes<span class="Delimiter">;</span> +vector<recipe_ordinal> Recently_added_shape_shifting_recipes<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> <span class="CommentedCode">//? cerr << "setup: clearing recently-added shape-shifting recipes\n";</span> -recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Comment">//: make sure we don't clear any of these recipes when we start running tests</span> <span class="Delimiter">:(before "End Loading .mu Files")</span> -recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> -recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="CommentedCode">//? cerr << "clearing recently-added shape-shifting recipes\n";</span> -recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Comment">//: save original name of specialized recipes</span> <span class="Delimiter">:(before "End recipe Fields")</span> @@ -107,26 +107,58 @@ if <span class="Delimiter">(</span>best_score == -<span class="Constant">1</span <span class="CommentedCode">//? cerr << "no variant found for " << inst.name << "; searching for variant with suitable type ingredients" << '\n';</span> recipe_ordinal exemplar = pick_matching_shape_shifting_variant<span class="Delimiter">(</span>variants<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> best_score<span class="Delimiter">);</span> if <span class="Delimiter">(</span>exemplar<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << "specializing " << inst.name << '\n';</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"found variant to specialize: "</span> << exemplar << <span class="Constant">' '</span> << get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">).</span>name << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << "found variant to specialize: " << exemplar << ' ' << get(Recipe, exemplar).name << '\n';</span> + LOG << <span class="Constant">"found variant to specialize: "</span> << exemplar << <span class="Constant">' '</span> << header<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> recipe_ordinal new_recipe_ordinal = new_variant<span class="Delimiter">(</span>exemplar<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">);</span> variants<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_recipe_ordinal<span class="Delimiter">);</span> <span class="Comment">// perform all transforms on the new specialization</span> const string& new_name = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>back<span class="Delimiter">()).</span>name<span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"transforming new specialization: "</span> << new_name << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << "transforming new specialization: " << new_name << '\n';</span> + LOG << <span class="Constant">"transforming new specialization: "</span> << header<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>back<span class="Delimiter">()))</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</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> <span class="Delimiter">(</span>*Transform<span class="Delimiter">.</span>at<span class="Delimiter">(</span>t<span class="Delimiter">))(</span>new_recipe_ordinal<span class="Delimiter">);</span> <span class="Delimiter">}</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">).</span>transformed_until = SIZE<span class="Delimiter">(</span>Transform<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">;</span> -<span class="CommentedCode">//? cerr << "-- replacing " << inst.name << " with " << get(Recipe, variants.back()).name << '\n' << debug_string(get(Recipe, variants.back()));</span> + LOG << <span class="Constant">"replacing "</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" with "</span> << get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>back<span class="Delimiter">()).</span>name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> inst<span class="Delimiter">.</span>name = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>back<span class="Delimiter">()).</span>name<span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"new specialization: "</span> << inst<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> -<span class="CommentedCode">//? cerr << "new specialization: " << inst.name << '\n';</span> + LOG << <span class="Constant">"new specialization: "</span> << inst<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Comment">//: make sure we have no unspecialized shape-shifting recipes being called</span> +<span class="Comment">//: before running mu programs</span> + +<span class="Delimiter">:(before "End Instruction Operation Checks")</span> +<span class="CommentedCode">//? LOG << inst.operation << " " << contains_key(Recipe, inst.operation) << '\n';</span> +if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">)</span> && inst<span class="Delimiter">.</span>operation >= MAX_PRIMITIVE_RECIPES + && any_type_ingredient_in_header<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? LOG << header(caller) << "instruction " << inst.name << " has no valid specialization\n";</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"instruction "</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" has no valid specialization</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(code)</span> +string header<span class="Delimiter">(</span>const recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!caller<span class="Delimiter">.</span>has_header<span class="Delimiter">)</span> <span class="Identifier">return</span> maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + ostringstream out<span class="Delimiter">;</span> + out << caller<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>i > <span class="Constant">0</span><span class="Delimiter">)</span> out << <span class="Constant">','</span><span class="Delimiter">;</span> + out << <span class="Constant">' '</span> << debug_string<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + out << <span class="Constant">" ->"</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>caller<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>i > <span class="Constant">0</span><span class="Delimiter">)</span> out << <span class="Constant">','</span><span class="Delimiter">;</span> + out << <span class="Constant">' '</span> << debug_string<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + out << <span class="Constant">": "</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + recipe_ordinal pick_matching_shape_shifting_variant<span class="Delimiter">(</span>vector<recipe_ordinal>& variants<span class="Delimiter">,</span> const instruction& inst<span class="Delimiter">,</span> long long int& best_score<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="CommentedCode">//? cerr << "---- " << inst.name << ": " << non_ghost_size(variants) << '\n';</span> recipe_ordinal result = <span class="Constant">0</span><span class="Delimiter">;</span> @@ -173,6 +205,7 @@ long long int shape_shifting_variant_score<span class="Delimiter">(</span>const <span class="Delimiter">}</span> const vector<reagent>& header_products = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>!deeply_equal_concrete_types<span class="Delimiter">(</span>header_products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"mismatch: product "</span> << i << end<span class="Delimiter">();</span> <span class="CommentedCode">//? cerr << "mismatch: product " << i << '\n';</span> @@ -270,8 +303,8 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla <span class="Comment">// make a copy</span> assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">));</span> assert<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">));</span> - recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_recipe_ordinal<span class="Delimiter">);</span> - recently_added_shape_shifting_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_recipe_ordinal<span class="Delimiter">);</span> + Recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_recipe_ordinal<span class="Delimiter">);</span> + Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_recipe_ordinal<span class="Delimiter">);</span> put<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">));</span> recipe& new_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">);</span> new_recipe<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> diff --git a/html/060immutable.cc.html b/html/060immutable.cc.html new file mode 100644 index 00000000..8d8c7633 --- /dev/null +++ b/html/060immutable.cc.html @@ -0,0 +1,389 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>Mu - 060immutable.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="cpp"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.traceContains { color: #008000; } +.Identifier { color: #804000; } +.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Addresses passed into of a recipe are meant to be immutable unless they're</span> +<span class="Comment">//: also products. This layer will start enforcing this check.</span> + +<span class="Delimiter">:(scenario can_modify_value_ingredients)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + local-scope + p:address:point<span class="Special"> <- </span>new point:type + foo *p +] +recipe foo p:point [ + local-scope + load-ingredients + x:address:number<span class="Special"> <- </span>get-address p<span class="Delimiter">,</span> x:offset + *x<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +$warn: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario can_modify_ingredients_that_are_also_products)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + local-scope + p:address:point<span class="Special"> <- </span>new point:type + p<span class="Special"> <- </span>foo p +] +recipe foo p:address:point <span class="Delimiter">-></span> p:address:point [ + local-scope + load-ingredients + x:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset + *x<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +$warn: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario ignore_literal_ingredients_for_immutability_checks)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + local-scope + p:address:d1<span class="Special"> <- </span>new d1:type + q:number<span class="Special"> <- </span>foo p +] +recipe foo p:address:d1 <span class="Delimiter">-></span> q:number [ + local-scope + load-ingredients + x:address:d1<span class="Special"> <- </span>new d1:type + y:address:number<span class="Special"> <- </span>get-address *x<span class="Delimiter">,</span> p:offset <span class="Comment"># ignore this 'p'</span> + q<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +container d1 [ + p:number + q:number +] +$warn: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario cannot_take_address_inside_immutable_ingredients)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + local-scope + p:address:point<span class="Special"> <- </span>new point:type + foo p +] +recipe foo p:address:point [ + local-scope + load-ingredients + x:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset + *x<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+warn: foo: cannot modify ingredient p after instruction 'x:address:number <- get-address *p, x:offset' because it's not also a product of foo</span> + +<span class="Delimiter">:(scenario cannot_call_mutating_recipes_on_immutable_ingredients)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + local-scope + p:address:point<span class="Special"> <- </span>new point:type + foo p +] +recipe foo p:address:point [ + local-scope + load-ingredients + bar p +] +recipe bar p:address:point <span class="Delimiter">-></span> p:address:point [ + local-scope + load-ingredients + x:address:number<span class="Special"> <- </span>get-address *p<span class="Delimiter">,</span> x:offset + *x<span class="Special"> <- </span>copy <span class="Constant">34</span> +] +<span class="traceContains">+warn: foo: cannot modify ingredient p at instruction 'bar p' because it's not also a product of foo</span> + +<span class="Delimiter">:(scenario cannot_modify_copies_of_immutable_ingredients)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + local-scope + p:address:point<span class="Special"> <- </span>new point:type + foo p +] +recipe foo p:address:point [ + local-scope + load-ingredients + q:address:point<span class="Special"> <- </span>copy p + x:address:number<span class="Special"> <- </span>get-address *q<span class="Delimiter">,</span> x:offset +] +<span class="traceContains">+warn: foo: cannot modify q after instruction 'x:address:number <- get-address *q, x:offset' because that would modify ingredient p which is not also a product of foo</span> + +<span class="Delimiter">:(scenario can_traverse_immutable_ingredients)</span> +<span class="Special">% Hide_warnings = true;</span> +container test-list [ + next:address:test-list +] +recipe main [ + local-scope + p:address:test-list<span class="Special"> <- </span>new test-list:type + foo p +] +recipe foo p:address:test-list [ + local-scope + load-ingredients + p2:address:test-list<span class="Special"> <- </span>bar p +] +recipe bar x:address:test-list <span class="Delimiter">-></span> y:address:test-list [ + local-scope + load-ingredients + y<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset +] +$warn: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario handle_optional_ingredients_in_immutability_checks)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + k:address:number<span class="Special"> <- </span>new number:type + test k +] +<span class="Comment"># recipe taking an immutable address ingredient</span> +recipe test k:address:number [ + local-scope + load-ingredients + foo k +] +<span class="Comment"># ..calling a recipe with an optional address ingredient</span> +recipe foo <span class="Delimiter">-></span> [ + local-scope + load-ingredients + k:address:number<span class="Delimiter">,</span> found?:boolean<span class="Special"> <- </span>next-ingredient +] +$warn: <span class="Constant">0</span> + +<span class="Delimiter">:(before "End Transforms")</span> +Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_immutable_ingredients<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> + +<span class="Delimiter">:(code)</span> +void check_immutable_ingredients<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// to ensure a reagent isn't modified, it suffices to show that we never</span> + <span class="Comment">// call get-address or index-address with it, and that any non-primitive</span> + <span class="Comment">// recipe calls in the body aren't returning it as a product.</span> + const recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> +<span class="CommentedCode">//? cerr << caller.name << '\n';</span> + if <span class="Delimiter">(</span>!caller<span class="Delimiter">.</span>has_header<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// skip check for old-style recipes calling next-ingredient directly</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const reagent& current_ingredient = caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +<span class="CommentedCode">//? cerr << " " << current_ingredient.original_string << '\n';</span> + if <span class="Delimiter">(</span>!is_mu_address<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// will be copied</span> + if <span class="Delimiter">(</span>is_present_in_products<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// not expected to be immutable</span> + <span class="Comment">// End Immutable Ingredients Special-cases</span> + set<string> immutable_vars<span class="Delimiter">;</span> + immutable_vars<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +<span class="CommentedCode">//? cerr << " " << inst.to_string() << '\n';</span> + check_immutable_ingredient_in_instruction<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> immutable_vars<span class="Delimiter">,</span> current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">,</span> caller<span class="Delimiter">);</span> + update_aliases<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> immutable_vars<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void update_aliases<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> set<string>& current_ingredient_and_aliases<span class="Delimiter">)</span> <span class="Delimiter">{</span> + set<long long int> current_ingredient_indices = ingredient_indices<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> current_ingredient_and_aliases<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// primitive recipe</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == COPY<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>set<long long int>::iterator p = current_ingredient_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != current_ingredient_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + current_ingredient_and_aliases<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>*p<span class="Delimiter">).</span>name<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + <span class="Comment">// defined recipe</span> + set<long long int> contained_in_product_indices = scan_contained_in_product_indices<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> current_ingredient_indices<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>set<long long int>::iterator p = contained_in_product_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != contained_in_product_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>*p < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">))</span> + current_ingredient_and_aliases<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>*p<span class="Delimiter">).</span>name<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +set<long long int> scan_contained_in_product_indices<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> set<long long int>& ingredient_indices<span class="Delimiter">)</span> <span class="Delimiter">{</span> + set<string> selected_ingredient_names<span class="Delimiter">;</span> + const recipe& callee = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>set<long long int>::iterator p = ingredient_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != ingredient_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>*p >= SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// optional immutable ingredient</span> + selected_ingredient_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>*p<span class="Delimiter">).</span>name<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + set<long long int> 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>callee<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const reagent& current_product = callee<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + const string_tree* contained_in_name = property<span class="Delimiter">(</span>current_product<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>contained_in_name && selected_ingredient_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>contained_in_name<span class="Delimiter">-></span>value<span class="Delimiter">)</span> != selected_ingredient_names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenarios transform)</span> +<span class="Delimiter">:(scenario immutability_infects_contained_in_variables)</span> +<span class="Special">% Hide_warnings = true;</span> +container test-list [ + next:address:test-list +] +recipe main [ + local-scope + p:address:test-list<span class="Special"> <- </span>new test-list:type + foo p +] +recipe foo p:address:test-list [ <span class="Comment"># p is immutable</span> + local-scope + load-ingredients + p2:address:test-list<span class="Special"> <- </span>test-next p <span class="Comment"># p2 is immutable</span> + p3:address:address:test-list<span class="Special"> <- </span>get-address *p2<span class="Delimiter">,</span> next:offset <span class="Comment"># signal modification of p2</span> +] +recipe test-next x:address:test-list <span class="Delimiter">-></span> y:address:test-list/contained-in:x [ + local-scope + load-ingredients + y<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset +] +<span class="traceContains">+warn: foo: cannot modify p2 after instruction 'p3:address:address:test-list <- get-address *p2, next:offset' because that would modify ingredient p which is not also a product of foo</span> + +<span class="Delimiter">:(code)</span> +void check_immutable_ingredient_in_instruction<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> const set<string>& current_ingredient_and_aliases<span class="Delimiter">,</span> const string& original_ingredient_name<span class="Delimiter">,</span> const recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> + set<long long int> current_ingredient_indices = ingredient_indices<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> current_ingredient_and_aliases<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>current_ingredient_indices<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// ingredient not found in call</span> + for <span class="Delimiter">(</span>set<long long int>::iterator p = current_ingredient_indices<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != current_ingredient_indices<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const long long int current_ingredient_index = *p<span class="Delimiter">;</span> +<span class="CommentedCode">//? cerr << " ingredient index: " << *p << '\n';</span> + reagent current_ingredient = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>current_ingredient_index<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">);</span> + const string& current_ingredient_name = current_ingredient<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// primitive recipe</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == GET_ADDRESS || inst<span class="Delimiter">.</span>operation == INDEX_ADDRESS<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>current_ingredient_name == original_ingredient_name<span class="Delimiter">)</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify ingredient "</span> << current_ingredient_name << <span class="Constant">" after instruction '"</span> << inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' because it's not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + else + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify "</span> << current_ingredient_name << <span class="Constant">" after instruction '"</span> << inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' because that would modify ingredient "</span> << original_ingredient_name << <span class="Constant">" which is not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + <span class="Comment">// defined recipe</span> + if <span class="Delimiter">(</span>!is_mu_address<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// making a copy is ok</span> + if <span class="Delimiter">(</span>is_modified_in_recipe<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation<span class="Delimiter">,</span> current_ingredient_index<span class="Delimiter">,</span> caller<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>current_ingredient_name == original_ingredient_name<span class="Delimiter">)</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify ingredient "</span> << current_ingredient_name << <span class="Constant">" at instruction '"</span> << inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' because it's not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + else + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"cannot modify "</span> << current_ingredient_name << <span class="Constant">" after instruction '"</span> << inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' because that would modify ingredient "</span> << original_ingredient_name << <span class="Constant">" which is not also a product of "</span> << caller<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +bool is_modified_in_recipe<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">,</span> long long int ingredient_index<span class="Delimiter">,</span> const recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const recipe& callee = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!callee<span class="Delimiter">.</span>has_header<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"can't check mutability of ingredients in "</span> << callee<span class="Delimiter">.</span>name << <span class="Constant">" because it uses 'next-ingredient' directly, rather than a recipe header.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>ingredient_index >= SIZE<span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// optional immutable ingredient</span> + <span class="Identifier">return</span> is_present_in_products<span class="Delimiter">(</span>callee<span class="Delimiter">,</span> callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>name<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool is_present_in_products<span class="Delimiter">(</span>const recipe& callee<span class="Delimiter">,</span> const string& ingredient_name<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>callee<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>callee<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name == ingredient_name<span class="Delimiter">)</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool is_present_in_ingredients<span class="Delimiter">(</span>const recipe& callee<span class="Delimiter">,</span> const string& ingredient_name<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>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>callee<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name == ingredient_name<span class="Delimiter">)</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +set<long long int> ingredient_indices<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> const set<string>& ingredient_names<span class="Delimiter">)</span> <span class="Delimiter">{</span> + set<long long int> 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>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>ingredient_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">)</span> != ingredient_names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Sometimes you want to pass in two addresses, one pointing inside the</span> +<span class="Comment">//: other. For example, you want to delete a node from a linked list. You</span> +<span class="Comment">//: can't pass both pointers back out, because if a caller tries to make both</span> +<span class="Comment">//: identical then you can't tell which value will be written on the way out.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Experimental solution: just tell mu that one points inside the other.</span> +<span class="Comment">//: This way we can return just one pointer as high up as necessary to capture</span> +<span class="Comment">//: all modifications performed by a recipe.</span> +<span class="Comment">//:</span> +<span class="Comment">//: We'll see if we end up wanting to abuse /contained-in for other reasons.</span> + +<span class="Delimiter">:(scenarios transform)</span> +<span class="Delimiter">:(scenario can_modify_contained_in_addresses)</span> +<span class="Special">% Hide_warnings = true;</span> +container test-list [ + next:address:test-list +] +recipe main [ + local-scope + p:address:test-list<span class="Special"> <- </span>new test-list:type + foo p +] +recipe foo p:address:test-list <span class="Delimiter">-></span> p:address:test-list [ + local-scope + load-ingredients + p2:address:test-list<span class="Special"> <- </span>test-next p + p<span class="Special"> <- </span>test-remove p2<span class="Delimiter">,</span> p +] +recipe test-next x:address:test-list <span class="Delimiter">-></span> y:address:test-list [ + local-scope + load-ingredients + y<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset +] +recipe test-remove x:address:test-list/contained-in:from<span class="Delimiter">,</span> from:address:test-list <span class="Delimiter">-></span> from:address:test-list [ + local-scope + load-ingredients + x2:address:address:test-list<span class="Special"> <- </span>get-address *x<span class="Delimiter">,</span> next:offset <span class="Comment"># pretend modification</span> +] +$warn: <span class="Constant">0</span> + +<span class="Delimiter">:(before "End Immutable Ingredients Special-cases")</span> +if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + const string_tree* tmp = property<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>tmp<span class="Delimiter">-></span>left || tmp<span class="Delimiter">-></span>right + || !is_present_in_ingredients<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> tmp<span class="Delimiter">-></span>value<span class="Delimiter">)</span> + || !is_present_in_products<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> tmp<span class="Delimiter">-></span>value<span class="Delimiter">))</span> + raise_error << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"contained-in can only point to another ingredient+product, but got "</span> << debug_string<span class="Delimiter">(</span>property<span class="Delimiter">(</span>current_ingredient<span class="Delimiter">,</span> <span class="Constant">"contained-in"</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/061abandon_checks.cc.html b/html/061abandon_checks.cc.html new file mode 100644 index 00000000..9f91f90e --- /dev/null +++ b/html/061abandon_checks.cc.html @@ -0,0 +1,159 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>Mu - 061abandon_checks.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="cpp"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.Comment { color: #9090ff; } +.Delimiter { color: #a04060; } +.Special { color: #ff6060; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Delimiter">:(scenarios transform)</span> <span class="Comment">// many of the tests below are *extremely* unsafe</span> +<span class="Delimiter">:(scenario abandon_in_same_recipe_as_new)</span> +recipe test [ + x:address:number<span class="Special"> <- </span>new number:type + abandon x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario abandon_in_separate_recipe_from_new)</span> +recipe test [ + x:address:number<span class="Special"> <- </span>test-new + test-abandon x +] +recipe test-new <span class="Delimiter">-></span> result:address:number [ + result<span class="Special"> <- </span>new number:type +] +recipe test-abandon x:address:number [ + load-ingredients + abandon x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario define_after_abandon_in_same_recipe_as_new)</span> +recipe test [ + x:address:number<span class="Special"> <- </span>new number:type + abandon x + x<span class="Special"> <- </span>new number:type + reply x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario define_after_abandon_in_separate_recipe_from_new)</span> +recipe test [ + x:address:number<span class="Special"> <- </span>test-new + test-abandon x + x<span class="Special"> <- </span>test-new + reply x +] +recipe test-new <span class="Delimiter">-></span> result:address:number [ + result<span class="Special"> <- </span>new number:type +] +recipe test-abandon x:address:number [ + load-ingredients + abandon x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario abandon_inside_loop_initializing_variable)</span> +recipe test [ + <span class="Delimiter">{</span> + x:address:number<span class="Special"> <- </span>new number:type + abandon x + loop + <span class="Delimiter">}</span> +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario abandon_inside_loop_initializing_variable_2)</span> +recipe test [ + <span class="Delimiter">{</span> + x:address:number<span class="Special"> <- </span>test-new + test-abandon x + loop + <span class="Delimiter">}</span> +] +recipe test-new <span class="Delimiter">-></span> result:address:number [ + result<span class="Special"> <- </span>new number:type +] +recipe test-abandon x:address:number [ + load-ingredients + abandon x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario abandon_inside_loop_initializing_variable_3)</span> +recipe test [ + <span class="Delimiter">{</span> + x:address:number<span class="Special"> <- </span>test-new + test-abandon x + x:address:number<span class="Special"> <- </span>test-new <span class="Comment"># modify x to a new value</span> + y:address:number<span class="Special"> <- </span>copy x <span class="Comment"># use x after reinitialization</span> + loop + <span class="Delimiter">}</span> +] +recipe test-new <span class="Delimiter">-></span> result:address:number [ + result<span class="Special"> <- </span>new number:type +] +recipe test-abandon x:address:number [ + load-ingredients + abandon x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario abandon_inside_loop_initializing_variable_4)</span> +container test-list [ + value:number + next:address:test-list +] +recipe test-cleanup x:address:test-list [ + load-ingredients + <span class="Delimiter">{</span> + next:address:test-list<span class="Special"> <- </span>test-next x + test-abandon x + x<span class="Special"> <- </span>copy next + loop + <span class="Delimiter">}</span> +] +recipe test-next x:address:test-list <span class="Delimiter">-></span> result:address:test-list/contained-in:x [ + load-ingredients + result<span class="Special"> <- </span>get *x<span class="Delimiter">,</span> next:offset +] +recipe test-abandon x:address:test-list [ + load-ingredients + abandon x +] +<span class="Comment"># no warnings</span> + +<span class="Delimiter">:(scenario abandon_non_unique_address_after_define)</span> +recipe test [ + x:address:number<span class="Special"> <- </span>new number:type + y:address:number<span class="Special"> <- </span>copy x + abandon x + y:address:number<span class="Special"> <- </span>new number:type <span class="Comment"># overwrite alias</span> + z:address:number<span class="Special"> <- </span>copy y +] +<span class="Comment"># no warnings</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/073list.mu.html b/html/073list.mu.html index a14399dd..2097a4e6 100644 --- a/html/073list.mu.html +++ b/html/073list.mu.html @@ -43,15 +43,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } next:address:list:_elem ] -<span class="muRecipe">recipe</span> push x:_elem, in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem [ +<span class="muRecipe">recipe</span> push x:_elem, in:address:list:_elem<span class="muRecipe"> -> </span>in:address:list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> + result:address:list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> val:address:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">value:offset</span> *val<span class="Special"> <- </span>copy x next:address:address:list:_elem<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 + <span class="muControl">reply</span> result <span class="Comment"># needed explicitly because we need to replace 'in' with 'result'</span> ] <span class="muRecipe">recipe</span> first in:address:list:_elem<span class="muRecipe"> -> </span>result:_elem [ @@ -60,8 +60,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } result<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> ] -<span class="Comment"># result:address:list <- rest in:address:list</span> -<span class="muRecipe">recipe</span> rest in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem [ +<span class="muRecipe">recipe</span> rest in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem/contained-in:in [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> @@ -112,7 +111,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> in - $print <span class="Constant">[000]</span>, <span class="Constant">10/newline</span> buf<span class="Special"> <- </span>append buf, <span class="Constant">48/0</span> <span class="muControl">reply</span> <span class="Delimiter">}</span> diff --git a/html/075duplex_list.mu.html b/html/075duplex_list.mu.html index f2094cde..4a0abcbb 100644 --- a/html/075duplex_list.mu.html +++ b/html/075duplex_list.mu.html @@ -40,17 +40,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } prev:address:duplex-list:_elem ] -<span class="muRecipe">recipe</span> push x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem [ +<span class="Comment"># should I say in/contained-in:result, allow ingredients to refer to products?</span> +<span class="muRecipe">recipe</span> push x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> + result:address:duplex-list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> val:address:_elem<span class="Special"> <- </span>get-address *result, <span class="Constant">value:offset</span> *val<span class="Special"> <- </span>copy x next:address:address:duplex-list:_elem<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 - prev:address:address:duplex-list:_elem<span class="Special"> <- </span>get-address *in, <span class="Constant">prev:offset</span> - *prev<span class="Special"> <- </span>copy result + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> in + prev:address:address:duplex-list:_elem<span class="Special"> <- </span>get-address *in, <span class="Constant">prev:offset</span> + *prev<span class="Special"> <- </span>copy result + <span class="Delimiter">}</span> + <span class="muControl">reply</span> result <span class="Comment"># needed explicitly because we need to replace 'in' with 'result'</span> ] <span class="muRecipe">recipe</span> first in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:_elem [ @@ -60,14 +64,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } result<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> ] -<span class="muRecipe">recipe</span> next in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem [ +<span class="muRecipe">recipe</span> next in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem/contained-in:in [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> result<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> ] -<span class="muRecipe">recipe</span> prev in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem [ +<span class="muRecipe">recipe</span> prev in:address:duplex-list:_elem<span class="muRecipe"> -> </span>result:address:duplex-list:_elem/contained-in:in [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> in, <span class="Constant">0</span> @@ -116,11 +120,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># Inserts 'x' after 'in'. Returns some pointer into the list.</span> -<span class="muRecipe">recipe</span> insert x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>new-node:address:duplex-list:_elem [ +<span class="Comment"># insert 'x' after 'in'</span> +<span class="muRecipe">recipe</span> insert x:_elem, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - new-node<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> + new-node:address:duplex-list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(duplex-list _elem): type<span class="Delimiter">}</span> val:address:_elem<span class="Special"> <- </span>get-address *new-node, <span class="Constant">value:offset</span> *val<span class="Special"> <- </span>copy x next-node:address:duplex-list:_elem<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> @@ -134,11 +138,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } y<span class="Special"> <- </span>get-address *new-node, <span class="Constant">next:offset</span> *y<span class="Special"> <- </span>copy next-node <span class="Comment"># if next-node is not null</span> - <span class="muControl">reply-unless</span> next-node, new-node + <span class="muControl">reply-unless</span> next-node <span class="Comment"># next-node.prev = new-node</span> y<span class="Special"> <- </span>get-address *next-node, <span class="Constant">prev:offset</span> *y<span class="Special"> <- </span>copy new-node - <span class="muControl">reply</span> new-node <span class="Comment"># just signalling something changed; don't rely on the result</span> ] <span class="muScenario">scenario</span> inserting-into-duplex-list [ @@ -219,7 +222,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character - <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>insert <span class="Constant">6</span>, <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>insert <span class="Constant">6</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character @@ -249,38 +252,37 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<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"># remove 'x' from its surrounding list 'in'</span> <span class="Comment">#</span> -<span class="Comment"># Returns null if and only if list is empty. Beware: in that case any pointers</span> -<span class="Comment"># to the head are now invalid.</span> -<span class="muRecipe">recipe</span> remove in:address:duplex-list:_elem<span class="muRecipe"> -> </span>next-node:address:duplex-list:_elem [ +<span class="Comment"># Returns null if and only if list is empty. Beware: in that case any other</span> +<span class="Comment"># pointers to the head are now invalid.</span> +<span class="muRecipe">recipe</span> remove x:address:duplex-list:_elem/contained-in:in, in:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if 'in' is null, return</span> - <span class="muControl">reply-unless</span> in, in - next-node:address:duplex-list:_elem<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> - prev-node:address:duplex-list:_elem<span class="Special"> <- </span>get *in, <span class="Constant">prev:offset</span> - <span class="Comment"># null in's pointers</span> - x:address:address:duplex-list:_elem<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="Comment"># if 'x' is null, return</span> + <span class="muControl">reply-unless</span> x + next-node:address:duplex-list:_elem<span class="Special"> <- </span>get *x, <span class="Constant">next:offset</span> + prev-node:address:duplex-list:_elem<span class="Special"> <- </span>get *x, <span class="Constant">prev:offset</span> + <span class="Comment"># null x's pointers</span> + tmp:address:address:duplex-list:_elem<span class="Special"> <- </span>get-address *x, <span class="Constant">next:offset</span> + *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> + tmp<span class="Special"> <- </span>get-address *x, <span class="Constant">prev:offset</span> + *tmp<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Comment"># if next-node is not null, set its prev pointer</span> <span class="Delimiter">{</span> - <span class="Comment"># if next-node is not null</span> <span class="muControl">break-unless</span> 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 + tmp<span class="Special"> <- </span>get-address *next-node, <span class="Constant">prev:offset</span> + *tmp<span class="Special"> <- </span>copy prev-node <span class="Delimiter">}</span> + <span class="Comment"># if prev-node is not null, set its next pointer and return</span> <span class="Delimiter">{</span> - <span class="Comment"># if prev-node is not null</span> <span class="muControl">break-unless</span> 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 + tmp<span class="Special"> <- </span>get-address *prev-node, <span class="Constant">next:offset</span> + *tmp<span class="Special"> <- </span>copy next-node + <span class="muControl">reply</span> <span class="Delimiter">}</span> + <span class="Comment"># if prev-node is null, then we removed the node at 'in'</span> + <span class="Comment"># return the new head rather than the old 'in'</span> <span class="muControl">reply</span> next-node ] @@ -290,7 +292,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># 2 points at second element</span> - <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">0</span> <span class="Comment"># check structure like before</span> <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character @@ -317,8 +319,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list:character - <span class="Comment"># removing from head? return value matters.</span> - <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character <span class="Comment"># check structure like before</span> <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">3</span>:character<span class="Special"> <- </span>first <span class="Constant">2</span>:address:duplex-list:character @@ -346,7 +347,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Comment"># delete last element</span> <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>next <span class="Constant">2</span>:address:duplex-list:character - <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:duplex-list:character + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">2</span>:address:duplex-list:character, <span class="Constant">0</span> <span class="Comment"># check structure like before</span> <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:duplex-list:character @@ -371,20 +372,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muScenario">scenario</span> removing-from-singleton-list [ run [ <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - <span class="Constant">2</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:duplex-list:character - <span class="Constant">3</span>:address:duplex-list:character<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">next:offset</span> - <span class="Constant">4</span>:address:duplex-list:character<span class="Special"> <- </span>get *<span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">prev:offset</span> + <span class="Constant">1</span>:address:duplex-list:character<span class="Special"> <- </span>remove <span class="Constant">1</span>:address:duplex-list:character, <span class="Constant">1</span>:address:duplex-list:character ] memory-should-contain [ - <span class="Constant">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> + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># back to an empty list</span> ] ] <span class="Comment"># remove values between 'start' and 'end' (both exclusive)</span> <span class="Comment"># also clear pointers back out from start/end for hygiene</span> -<span class="muRecipe">recipe</span> remove-between start:address:duplex-list:_elem, end:address:duplex-list:_elem<span class="muRecipe"> -> </span>start:address:duplex-list:_elem [ +<span class="muRecipe">recipe</span> remove-between start:address:duplex-list:_elem, end:address:duplex-list:_elem/contained-in:start<span class="muRecipe"> -> </span>start:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> start @@ -491,8 +488,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -<span class="Comment"># Inserts list beginning at 'new' after 'in'. Returns some pointer into the list.</span> -<span class="muRecipe">recipe</span> insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ +<span class="Comment"># insert list beginning at 'new' after 'in'</span> +<span class="muRecipe">recipe</span> insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem/contained-in:in<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> in @@ -518,7 +515,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *dest<span class="Special"> <- </span>copy in ] -<span class="muRecipe">recipe</span> append in:address:duplex-list:_elem, new:address:duplex-list:_elem<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ +<span class="muRecipe">recipe</span> append in:address:duplex-list:_elem, new:address:duplex-list:_elem/contained-in:in<span class="muRecipe"> -> </span>in:address:duplex-list:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> last:address:duplex-list:_elem<span class="Special"> <- </span>last in diff --git a/html/080display.cc.html b/html/080display.cc.html index bf3ad0c8..88a10a41 100644 --- a/html/080display.cc.html +++ b/html/080display.cc.html @@ -14,6 +14,7 @@ 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; } @@ -444,7 +445,11 @@ case CHECK_FOR_INTERACTION: <span class="Delimiter">{</span> <span class="Comment">// treat keys within ascii as unicode characters</span> if <span class="Delimiter">(</span>event_type == TB_EVENT_KEY && event<span class="Delimiter">.</span>key < <span class="Constant">0xff</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">text event</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> - if <span class="Delimiter">(</span>event<span class="Delimiter">.</span>key == TB_KEY_CTRL_C<span class="Delimiter">)</span> tb_shutdown<span class="Delimiter">(),</span> exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>event<span class="Delimiter">.</span>key == TB_KEY_CTRL_C<span class="Delimiter">)</span> <span class="Delimiter">{</span> + tb_shutdown<span class="Delimiter">();</span> +<span class="CommentedCode">//? LOG << "exit\n";</span> + exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> if <span class="Delimiter">(</span>event<span class="Delimiter">.</span>key == TB_KEY_BACKSPACE2<span class="Delimiter">)</span> event<span class="Delimiter">.</span>key = TB_KEY_BACKSPACE<span class="Delimiter">;</span> if <span class="Delimiter">(</span>event<span class="Delimiter">.</span>key == TB_KEY_CARRIAGE_RETURN<span class="Delimiter">)</span> event<span class="Delimiter">.</span>key = TB_KEY_NEWLINE<span class="Delimiter">;</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>key<span class="Delimiter">);</span> diff --git a/html/082scenario_screen.cc.html b/html/082scenario_screen.cc.html index bca387d9..85ef4880 100644 --- a/html/082scenario_screen.cc.html +++ b/html/082scenario_screen.cc.html @@ -196,6 +196,7 @@ case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span> <span class="CommentedCode">//? cerr << SIZE(get(Recipe_variants, "insert")) << '\n';</span> <span class="CommentedCode">//? cerr << debug_string(get(Recipe, get(Recipe_ordinal, "insert_4"))) << '\n';</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> check_screen<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="Constant">1</span><span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -212,6 +213,7 @@ case SCREEN_SHOULD_CONTAIN_IN_COLOR: <span class="Delimiter">{</span> case SCREEN_SHOULD_CONTAIN_IN_COLOR: <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> 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> + assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span> check_screen<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -257,12 +259,12 @@ void check_screen<span class="Delimiter">(</span>const string& expected_cont <span class="Comment">// filter out other colors</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> != <span class="Constant">0</span> && Memory[addr] == curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> != <span class="Constant">0</span> && get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> == curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>color == -<span class="Constant">1</span> || color == get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr+cell_color_offset<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// contents match but color is off</span> if <span class="Delimiter">(</span>Current_scenario && !Scenario_testing_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// genuine test in a mu file</span> - raise_error << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": expected screen location ("</span> << row << <span class="Constant">", "</span> << column << <span class="Constant">", address "</span> << addr << <span class="Constant">", value "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">))</span> << <span class="Constant">") to be in color "</span> << color << <span class="Constant">" instead of "</span> << no_scientific<span class="Delimiter">(</span>Memory[addr+cell_color_offset]<span class="Delimiter">)</span> << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise_error << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": expected screen location ("</span> << row << <span class="Constant">", "</span> << column << <span class="Constant">", address "</span> << addr << <span class="Constant">", value "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">))</span> << <span class="Constant">") to be in color "</span> << color << <span class="Constant">" instead of "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr+cell_color_offset<span class="Delimiter">))</span> << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// just testing check_screen</span> @@ -283,7 +285,7 @@ void check_screen<span class="Delimiter">(</span>const string& expected_cont expected_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">3</span>] = static_cast<unsigned char><span class="Delimiter">(</span>curr<span class="Delimiter">),</span> expected_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> expected_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> char actual_pretty[<span class="Constant">10</span>] = <span class="Delimiter">{</span><span class="Constant">0</span><span class="Delimiter">};</span> - if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> < <span class="Constant">256</span> && !iscntrl<span class="Delimiter">(</span>Memory[addr]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)</span> < <span class="Constant">256</span> && !iscntrl<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)))</span> <span class="Delimiter">{</span> <span class="Comment">// " ('<curr>')"</span> actual_pretty[<span class="Constant">0</span>] = <span class="Constant">' '</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">1</span>] = <span class="Constant">'('</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">2</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">3</span>] = static_cast<unsigned char><span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> addr<span class="Delimiter">)),</span> actual_pretty[<span class="Constant">4</span>] = <span class="cSpecial">'\''</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">5</span>] = <span class="Constant">')'</span><span class="Delimiter">,</span> actual_pretty[<span class="Constant">6</span>] = <span class="cSpecial">'\0'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/084console.mu.html b/html/084console.mu.html index b8619762..4065e18b 100644 --- a/html/084console.mu.html +++ b/html/084console.mu.html @@ -54,17 +54,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="muData">container</span> console [ - index:number - data:address:array:event + current-event-index:number + events:address:array:event ] <span class="muRecipe">recipe</span> new-fake-console events:address:array:event<span class="muRecipe"> -> </span>result:address:console [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result:address:console<span class="Special"> <- </span>new <span class="Constant">console:type</span> - buf:address:address:array:event<span class="Special"> <- </span>get-address *result, <span class="Constant">data:offset</span> + buf:address:address:array:event<span class="Special"> <- </span>get-address *result, <span class="Constant">events:offset</span> *buf<span class="Special"> <- </span>copy events - idx:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">index:offset</span> + idx:address:number<span class="Special"> <- </span>get-address *result, <span class="Constant">current-event-index:offset</span> *idx<span class="Special"> <- </span>copy <span class="Constant">0</span> ] @@ -73,17 +73,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> console - idx:address:number<span class="Special"> <- </span>get-address *console, <span class="Constant">index:offset</span> - buf:address:array:event<span class="Special"> <- </span>get *console, <span class="Constant">data:offset</span> + current-event-index:address:number<span class="Special"> <- </span>get-address *console, <span class="Constant">current-event-index:offset</span> + buf:address:array:event<span class="Special"> <- </span>get *console, <span class="Constant">events:offset</span> <span class="Delimiter">{</span> max:number<span class="Special"> <- </span>length *buf - done?:boolean<span class="Special"> <- </span>greater-or-equal *idx, max + done?:boolean<span class="Special"> <- </span>greater-or-equal *current-event-index, 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, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">1/quit</span> <span class="Delimiter">}</span> - result<span class="Special"> <- </span>index *buf, *idx - *idx<span class="Special"> <- </span>add *idx, <span class="Constant">1</span> + result<span class="Special"> <- </span>index *buf, *current-event-index + *current-event-index<span class="Special"> <- </span>add *current-event-index, <span class="Constant">1</span> <span class="muControl">reply</span> result, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> <span class="Delimiter">}</span> switch <span class="Comment"># real event source is infrequent; avoid polling it too much</span> diff --git a/html/090trace_browser.cc.html b/html/090trace_browser.cc.html index 3da39a9b..7cc79bce 100644 --- a/html/090trace_browser.cc.html +++ b/html/090trace_browser.cc.html @@ -63,14 +63,13 @@ map<int<span class="Delimiter">,</span> long long int> Trace_index<span cl <span class="Delimiter">:(code)</span> void start_trace_browser<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="Delimiter">;</span> - cerr << <span class="Constant">"computing depth to display</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + cerr << <span class="Constant">"computing min depth to display</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> long long int min_depth = <span class="Constant">9999</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>Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">);</span> ++i<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>i<span class="Delimiter">);</span> - if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth < min_depth<span class="Delimiter">)</span> min_depth = curr_line<span class="Delimiter">.</span>depth<span class="Delimiter">;</span> <span class="Delimiter">}</span> - cerr << <span class="Constant">"depth is "</span> << min_depth << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + cerr << <span class="Constant">"min depth is "</span> << min_depth << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> cerr << <span class="Constant">"computing lines to display</span><span class="cSpecial">\n</span><span class="Constant">"</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>Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>depth == min_depth<span class="Delimiter">)</span> @@ -123,7 +122,7 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter while <span class="Delimiter">(</span>Top_of_screen > <span class="Constant">0</span> && !contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> Top_of_screen<span class="Delimiter">))</span> --Top_of_screen<span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>Top_of_screen > <span class="Constant">0</span><span class="Delimiter">)</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> if <span class="Delimiter">(</span>key == <span class="Constant">'G'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -150,7 +149,6 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> index<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> trace_line& 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 == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth > 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> @@ -174,7 +172,6 @@ void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Visible<span class="Delimiter">,</span> index<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> trace_line& 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 == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth <= initial_depth<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> long long int end_index = index<span class="Delimiter">;</span> @@ -215,7 +212,7 @@ void render<span class="Delimiter">()</span> <span class="Delimiter">{</span> long long int delta = lines_hidden<span class="Delimiter">(</span>screen_row<span class="Delimiter">);</span> <span class="Comment">// home-brew escape sequence for red</span> if <span class="Delimiter">(</span>delta > <span class="Constant">999</span><span class="Delimiter">)</span> out << <span class="Constant">"{"</span><span class="Delimiter">;</span> - out << <span class="Constant">" ("</span> << lines_hidden<span class="Delimiter">(</span>screen_row<span class="Delimiter">)</span> << <span class="Constant">")"</span><span class="Delimiter">;</span> + out << <span class="Constant">" ("</span> << delta << <span class="Constant">")"</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>delta > <span class="Constant">999</span><span class="Delimiter">)</span> out << <span class="Constant">"}"</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> render_line<span class="Delimiter">(</span>screen_row<span class="Delimiter">,</span> out<span class="Delimiter">.</span>str<span class="Delimiter">());</span> @@ -262,6 +259,14 @@ void load_trace<span class="Delimiter">(</span>const char* filename<span class=" <span class="Delimiter">}</span> Trace_stream = new trace_stream<span class="Delimiter">;</span> while <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>tin<span class="Delimiter">))</span> <span class="Delimiter">{</span> + tin >> std::noskipws<span class="Delimiter">;</span> + skip_whitespace_but_not_newline<span class="Delimiter">(</span>tin<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!isdigit<span class="Delimiter">(</span>tin<span class="Delimiter">.</span>peek<span class="Delimiter">()))</span> <span class="Delimiter">{</span> + string dummy<span class="Delimiter">;</span> + getline<span class="Delimiter">(</span>tin<span class="Delimiter">,</span> dummy<span class="Delimiter">);</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + tin >> std::skipws<span class="Delimiter">;</span> int depth<span class="Delimiter">;</span> tin >> depth<span class="Delimiter">;</span> string label<span class="Delimiter">;</span> @@ -271,6 +276,7 @@ void load_trace<span class="Delimiter">(</span>const char* filename<span class=" getline<span class="Delimiter">(</span>tin<span class="Delimiter">,</span> line<span class="Delimiter">);</span> Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>trace_line<span class="Delimiter">(</span>depth<span class="Delimiter">,</span> label<span class="Delimiter">,</span> line<span class="Delimiter">));</span> <span class="Delimiter">}</span> + cerr << <span class="Constant">"lines read: "</span> << Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> </body> diff --git a/html/091run_interactive.cc.html b/html/091run_interactive.cc.html index 94a1284a..703fd5c1 100644 --- a/html/091run_interactive.cc.html +++ b/html/091run_interactive.cc.html @@ -96,6 +96,8 @@ bool Track_most_recent_products = <span class="Constant">false</span><span class <span class="Delimiter">:(before "End Tracing")</span> trace_stream* Save_trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> string Save_trace_file<span class="Delimiter">;</span> +vector<recipe_ordinal> Save_recently_added_recipes<span class="Delimiter">;</span> +vector<recipe_ordinal> Save_recently_added_shape_shifting_recipes<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> Track_most_recent_products = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> @@ -113,7 +115,7 @@ bool run_interactive<span class="Delimiter">(</span>long long int address<span c string command = trim<span class="Delimiter">(</span>strip_comments<span class="Delimiter">(</span>read_mu_string<span class="Delimiter">(</span>address<span class="Delimiter">)));</span> if <span class="Delimiter">(</span>command<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> Name[get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"interactive"</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> - run_code_begin<span class="Delimiter">();</span> + run_code_begin<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">snapshot_recently_added_recipes</span><span class="Comment">*/</span><span class="Constant">true</span><span class="Delimiter">);</span> <span class="Comment">// don't kill the current routine on parse errors</span> routine* save_current_routine = Current_routine<span class="Delimiter">;</span> Current_routine = <span class="Constant">NULL</span><span class="Delimiter">;</span> @@ -140,12 +142,18 @@ bool run_interactive<span class="Delimiter">(</span>long long int address<span c <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -void run_code_begin<span class="Delimiter">()</span> <span class="Delimiter">{</span> +void run_code_begin<span class="Delimiter">(</span>bool snapshot_recently_added_recipes<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="CommentedCode">//? cerr << "loading new trace\n";</span> <span class="Comment">// stuff to undo later, in run_code_end()</span> Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> Hide_errors = <span class="Constant">true</span><span class="Delimiter">;</span> Disable_redefine_warnings = <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>snapshot_recently_added_recipes<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Save_recently_added_recipes = Recently_added_recipes<span class="Delimiter">;</span> + Recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + Save_recently_added_shape_shifting_recipes = Recently_added_shape_shifting_recipes<span class="Delimiter">;</span> + Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + <span class="Delimiter">}</span> Save_trace_stream = Trace_stream<span class="Delimiter">;</span> Save_trace_file = Trace_file<span class="Delimiter">;</span> Trace_file = <span class="Constant">""</span><span class="Delimiter">;</span> @@ -164,6 +172,13 @@ void run_code_end<span class="Delimiter">()</span> <span class="Delimiter">{</sp Trace_file = Save_trace_file<span class="Delimiter">;</span> Save_trace_file<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"interactive"</span><span class="Delimiter">));</span> <span class="Comment">// keep past sandboxes from inserting errors</span> + if <span class="Delimiter">(</span>!Save_recently_added_recipes<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + clear_recently_added_recipes<span class="Delimiter">();</span> + Recently_added_recipes = Save_recently_added_recipes<span class="Delimiter">;</span> + Save_recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + Recently_added_shape_shifting_recipes = Save_recently_added_shape_shifting_recipes<span class="Delimiter">;</span> + Save_recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Load Recipes")</span> @@ -185,7 +200,7 @@ load<span class="Delimiter">(</span>string<span class="Delimiter">(</span> <span class="Constant">"reply output, warnings, screen, stashes, completed?</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> transform_all<span class="Delimiter">();</span> -recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +Recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Comment">//: adjust errors/warnings in the sandbox</span> <span class="Delimiter">:(after "string maybe(string s)")</span> @@ -338,6 +353,31 @@ b:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># no errors</span> <span class="traceContains">+mem: storing 0 in location 3</span> +<span class="Delimiter">:(code)</span> +void test_run_interactive_cleans_up_any_created_specializations<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// define a generic recipe</span> + assert<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">));</span> + load<span class="Delimiter">(</span><span class="Constant">"recipe foo x:_elem -> n:number [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" reply 34</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// foo</span> + assert<span class="Delimiter">(</span>variant_count<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Comment">// run-interactive a call that specializes this recipe</span> + run<span class="Delimiter">(</span><span class="Constant">"recipe main [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" 1:number/raw <- copy 0</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" 2:address:array:character <- new [foo 1:number/raw]</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" run-interactive 2:address:array:character</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">)</span> == <span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">// foo, main</span> + <span class="Comment">// check that number of variants doesn't change</span> + CHECK_EQ<span class="Delimiter">(</span>variant_count<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +long long int variant_count<span class="Delimiter">(</span>string recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> recipe_name<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> non_ghost_size<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> recipe_name<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(before "End Globals")</span> string Most_recent_products<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> @@ -456,29 +496,29 @@ case RELOAD: <span class="Delimiter">{</span> case RELOAD: <span class="Delimiter">{</span> <span class="CommentedCode">//? cerr << "== reload\n";</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>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> - Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + 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>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> + Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recently_added_types<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> for <span class="Delimiter">(</span>map<string<span class="Delimiter">,</span> vector<recipe_ordinal> >::iterator p = Recipe_variants<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe_variants<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="CommentedCode">//? cerr << p->first << ":\n";</span> vector<recipe_ordinal>& variants = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>find<span class="Delimiter">(</span>recently_added_shape_shifting_recipes<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> recently_added_shape_shifting_recipes<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> != recently_added_shape_shifting_recipes<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>find<span class="Delimiter">(</span>Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> != Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> <span class="CommentedCode">//? cerr << " " << variants.at(i) << ' ' << get(Recipe, variants.at(i)).name << '\n';</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// ghost</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>recently_added_shape_shifting_recipes<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << "erasing " << get(Recipe, recently_added_shape_shifting_recipes.at(i)).name << '\n';</span> - Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> recently_added_shape_shifting_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> - Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_shape_shifting_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Recently_added_shape_shifting_recipes<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? LOG << "erasing " << get(Recipe, Recently_added_shape_shifting_recipes.at(i)).name << '\n';</span> + Recipe_ordinal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">);</span> + Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> - recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + Recently_added_shape_shifting_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> string code = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> - run_code_begin<span class="Delimiter">();</span> + run_code_begin<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">snapshot_recently_added_recipes</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> routine* save_current_routine = Current_routine<span class="Delimiter">;</span> Current_routine = <span class="Constant">NULL</span><span class="Delimiter">;</span> vector<recipe_ordinal> recipes_reloaded = load<span class="Delimiter">(</span>code<span class="Delimiter">);</span> @@ -506,6 +546,32 @@ recipe main [ <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">34</span> ] <span class="traceContains">+mem: storing 34 in location 1</span> + +<span class="Delimiter">:(code)</span> +void test_reload_cleans_up_any_created_specializations<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// define a generic recipe and a call to it</span> + assert<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>variant_count<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Comment">// a call that specializes this recipe</span> + run<span class="Delimiter">(</span><span class="Constant">"recipe main [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" x:address:array:character <- new [recipe foo x:_elem -> n:number [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"load-ingredients</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"reply 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">"recipe main2 [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"load-ingredients</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"x:number <- copy 34</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"foo x:number</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">" reload x</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> + <span class="Comment">// check that number of variants includes specialization</span> + assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">)</span> == <span class="Constant">4</span><span class="Delimiter">);</span> <span class="Comment">// foo, main, main2, foo specialization</span> + CHECK_EQ<span class="Delimiter">(</span>variant_count<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">),</span> <span class="Constant">2</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html index 338e92dc..16230411 100644 --- a/html/chessboard.mu.html +++ b/html/chessboard.mu.html @@ -276,7 +276,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># prints only error messages to screen</span> -<span class="muRecipe">recipe</span> read-move stdin:address:channel, screen:address:screen<span class="muRecipe"> -> </span>result:address:move, quit?:boolean, error?:boolean [ +<span class="muRecipe">recipe</span> read-move stdin:address:channel, screen:address:screen<span class="muRecipe"> -> </span>result:address:move, quit?:boolean, error?:boolean, stdin:address:channel, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> from-file:number, quit?:boolean, error?:boolean<span class="Special"> <- </span>read-file stdin, screen @@ -306,7 +306,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># valid values for file: 0-7</span> -<span class="muRecipe">recipe</span> read-file stdin:address:channel, screen:address:screen<span class="muRecipe"> -> </span>file:number, quit:boolean, error:boolean [ +<span class="muRecipe">recipe</span> read-file stdin:address:channel, screen:address:screen<span class="muRecipe"> -> </span>file:number, quit:boolean, error:boolean, stdin:address:channel, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> c:character, stdin<span class="Special"> <- </span>read stdin @@ -399,7 +399,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <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 stdin:address:channel, expected:character, screen:address:screen<span class="muRecipe"> -> </span>result:boolean [ +<span class="muRecipe">recipe</span> expect-from-channel stdin:address:channel, expected:character, screen:address:screen<span class="muRecipe"> -> </span>result:boolean, stdin:address:channel, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> c:character, stdin<span class="Special"> <- </span>read stdin diff --git a/html/edit/001-editor.mu.html b/html/edit/001-editor.mu.html index 59982193..11d1cb9d 100644 --- a/html/edit/001-editor.mu.html +++ b/html/edit/001-editor.mu.html @@ -287,7 +287,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span> ] -<span class="muRecipe">recipe</span> clear-rest-of-screen screen:address:screen, row:number, left:number, right:number [ +<span class="muRecipe">recipe</span> clear-rest-of-screen screen:address:screen, row:number, left:number, right:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> row<span class="Special"> <- </span>add row, <span class="Constant">1</span> diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html index efed71b6..2585450c 100644 --- a/html/edit/002-typing.mu.html +++ b/html/edit/002-typing.mu.html @@ -46,7 +46,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } close-console ] -<span class="muRecipe">recipe</span> editor-event-loop screen:address:screen, console:address:console, editor:address:editor-data [ +<span class="muRecipe">recipe</span> editor-event-loop screen:address:screen, console:address:console, editor:address:editor-data<span class="muRecipe"> -> </span>screen:address:screen, console:address:console, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> @@ -80,7 +80,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># process click, return if it was on current editor</span> -<span class="muRecipe">recipe</span> move-cursor-in-editor screen:address:screen, editor:address:editor-data, t:touch-event<span class="muRecipe"> -> </span>in-focus?:boolean [ +<span class="muRecipe">recipe</span> move-cursor-in-editor screen:address:screen, editor:address:editor-data, t:touch-event<span class="muRecipe"> -> </span>in-focus?:boolean, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="muControl">reply-unless</span> editor, <span class="Constant">0/false</span> @@ -294,7 +294,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] <span class="Comment"># helper for tests</span> -<span class="muRecipe">recipe</span> editor-render screen:address:screen, editor:address:editor-data<span class="muRecipe"> -> </span>screen:address:screen [ +<span class="muRecipe">recipe</span> editor-render screen:address:screen, editor:address:editor-data<span class="muRecipe"> -> </span>screen:address:screen, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> @@ -1047,7 +1047,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## helpers</span> -<span class="muRecipe">recipe</span> draw-horizontal screen:address:screen, row:number, x:number, right:number [ +<span class="muRecipe">recipe</span> draw-horizontal screen:address:screen, row:number, x:number, right:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> style:character, style-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> diff --git a/html/edit/003-shortcuts.mu.html b/html/edit/003-shortcuts.mu.html index 5518a680..0f7a60da 100644 --- a/html/edit/003-shortcuts.mu.html +++ b/html/edit/003-shortcuts.mu.html @@ -118,6 +118,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> before-cursor:address:address:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + data:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> <span class="Comment"># if at start of text (before-cursor at § sentinel), return</span> prev:address:duplex-list:character<span class="Special"> <- </span>prev *before-cursor go-render?, backspaced-cell<span class="Special"> <- </span>copy <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span> @@ -126,7 +127,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } original-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> editor, scroll?:boolean<span class="Special"> <- </span>move-cursor-coordinates-left editor backspaced-cell:address:duplex-list:character<span class="Special"> <- </span>copy *before-cursor - remove *before-cursor <span class="Comment"># will also neatly trim next/prev pointers in backspaced-cell/*before-cursor</span> + data<span class="Special"> <- </span>remove *before-cursor, data <span class="Comment"># will also neatly trim next/prev pointers in backspaced-cell/*before-cursor</span> *before-cursor<span class="Special"> <- </span>copy prev go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">reply-if</span> scroll? @@ -367,11 +368,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> before-cursor:address:address:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + data:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> deleted-cell:address:duplex-list:character<span class="Special"> <- </span>next *before-cursor go-render?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">reply-unless</span> deleted-cell currc:character<span class="Special"> <- </span>get *deleted-cell, <span class="Constant">value:offset</span> - remove deleted-cell + data<span class="Special"> <- </span>remove deleted-cell, data deleted-newline?:boolean<span class="Special"> <- </span>equal currc, <span class="Constant">10/newline</span> go-render?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> <span class="muControl">reply-if</span> deleted-newline? @@ -1278,7 +1280,7 @@ def] <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-to-start-of-line editor:address:editor-data [ +<span class="muRecipe">recipe</span> move-to-start-of-line editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># update cursor column</span> @@ -1449,7 +1451,7 @@ def] <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> move-to-end-of-line editor:address:editor-data [ +<span class="muRecipe">recipe</span> move-to-end-of-line editor:address:editor-data<span class="muRecipe"> -> </span>editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> before-cursor:address:address:duplex-list:character<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> @@ -1579,7 +1581,7 @@ def] <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> delete-to-start-of-line editor:address:editor-data<span class="muRecipe"> -> </span>result:address:duplex-list:character [ +<span class="muRecipe">recipe</span> delete-to-start-of-line editor:address:editor-data<span class="muRecipe"> -> </span>result:address:duplex-list:character, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># compute range to delete</span> @@ -1713,7 +1715,7 @@ def] <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> delete-to-end-of-line editor:address:editor-data<span class="muRecipe"> -> </span>result:address:duplex-list:character [ +<span class="muRecipe">recipe</span> delete-to-end-of-line editor:address:editor-data<span class="muRecipe"> -> </span>result:address:duplex-list:character, editor:address:editor-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># compute range to delete</span> diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html index a2001520..7b632086 100644 --- a/html/edit/004-programming-environment.mu.html +++ b/html/edit/004-programming-environment.mu.html @@ -56,7 +56,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } sandbox-in-focus?:boolean <span class="Comment"># false => cursor in recipes; true => cursor in current-sandbox</span> ] -<span class="muRecipe">recipe</span> new-programming-environment screen:address:screen, initial-recipe-contents:address:array:character, initial-sandbox-contents:address:array:character<span class="muRecipe"> -> </span>result:address:programming-environment-data [ +<span class="muRecipe">recipe</span> new-programming-environment screen:address:screen, initial-recipe-contents:address:array:character, initial-sandbox-contents:address:array:character<span class="muRecipe"> -> </span>result:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> width:number<span class="Special"> <- </span>screen-width screen @@ -82,7 +82,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *current-sandbox<span class="Special"> <- </span>new-editor initial-sandbox-contents, screen, new-left, width/right ] -<span class="muRecipe">recipe</span> event-loop screen:address:screen, console:address:console, env:address:programming-environment-data [ +<span class="muRecipe">recipe</span> event-loop screen:address:screen, console:address:console, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, console:address:console, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> @@ -141,7 +141,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> more-events? - env<span class="Special"> <- </span>resize screen, env + env, screen<span class="Special"> <- </span>resize screen, env screen<span class="Special"> <- </span>render-all screen, env render-all-on-no-more-events?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="Comment"># full render done</span> <span class="Delimiter">}</span> @@ -214,7 +214,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> resize screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>env:address:programming-environment-data [ +<span class="muRecipe">recipe</span> resize screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> clear-screen screen <span class="Comment"># update screen dimensions</span> @@ -633,7 +633,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## helpers</span> -<span class="muRecipe">recipe</span> draw-vertical screen:address:screen, col:number, y:number, bottom:number [ +<span class="muRecipe">recipe</span> draw-vertical screen:address:screen, col:number, y:number, bottom:number<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> style:character, style-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index 9c219526..0b3e3926 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -20,6 +20,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } +.CommentedCode { color: #6c6c6c; } .Delimiter { color: #a04060; } .muScenario { color: #00af00; } --> @@ -149,6 +150,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">{</span> do-run?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65532/F4</span> <span class="muControl">break-unless</span> do-run? +<span class="CommentedCode">#? $log [F4 pressed]</span> status:address:array:character<span class="Special"> <- </span>new <span class="Constant">[running... ]</span> screen<span class="Special"> <- </span>update-status screen, status, <span class="Constant">245/grey</span> error?:boolean, env, screen<span class="Special"> <- </span>run-sandboxes env, screen @@ -261,6 +263,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> +<span class="CommentedCode">#? $log [render sandbox side]</span> trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render sandbox side]</span> current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> left:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> @@ -274,9 +277,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } clear-rest-of-screen screen, row, left, left, right ] -<span class="muRecipe">recipe</span> render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ +<span class="muRecipe">recipe</span> render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen, sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> +<span class="CommentedCode">#? $log [render sandbox]</span> <span class="muControl">reply-unless</span> sandbox screen-height:number<span class="Special"> <- </span>screen-height screen at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal row, screen-height diff --git a/html/edit/006-sandbox-edit.mu.html b/html/edit/006-sandbox-edit.mu.html index 2381ec45..d902c4b7 100644 --- a/html/edit/006-sandbox-edit.mu.html +++ b/html/edit/006-sandbox-edit.mu.html @@ -131,7 +131,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } result<span class="Special"> <- </span>not first ] -<span class="muRecipe">recipe</span> extract-sandbox env:address:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>result:address:sandbox-data [ +<span class="muRecipe">recipe</span> extract-sandbox env:address:programming-environment-data, click-row:number<span class="muRecipe"> -> </span>result:address:sandbox-data, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># assert click-row >= sandbox.starting-row-on-screen</span> diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html index f563b266..6d289afa 100644 --- a/html/edit/007-sandbox-delete.mu.html +++ b/html/edit/007-sandbox-delete.mu.html @@ -111,7 +111,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="Delimiter">}</span> ] -<span class="muRecipe">recipe</span> delete-sandbox t:touch-event, env:address:programming-environment-data<span class="muRecipe"> -> </span>was-delete?:boolean [ +<span class="muRecipe">recipe</span> delete-sandbox t:touch-event, env:address:programming-environment-data<span class="muRecipe"> -> </span>was-delete?:boolean, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> click-column:number<span class="Special"> <- </span>get t, <span class="Constant">column:offset</span> diff --git a/html/edit/010-warnings.mu.html b/html/edit/010-warnings.mu.html index 6d746bf5..c675b386 100644 --- a/html/edit/010-warnings.mu.html +++ b/html/edit/010-warnings.mu.html @@ -44,6 +44,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe!</span> update-recipes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -> </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> +<span class="CommentedCode">#? $log [update recipes]</span> recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> in:address:array:character<span class="Special"> <- </span>editor-contents recipes save <span class="Constant">[recipes.mu]</span>, in @@ -85,6 +86,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="muRecipe">recipe!</span> update-sandbox sandbox:address:sandbox-data<span class="muRecipe"> -> </span>sandbox:address:sandbox-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> +<span class="CommentedCode">#? $log [update sandbox]</span> data:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">data:offset</span> response:address:address:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">response:offset</span> warnings:address:address:array:character<span class="Special"> <- </span>get-address *sandbox, <span class="Constant">warnings:offset</span> @@ -235,6 +237,66 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] +<span class="muScenario">scenario</span> run-avoids-spurious-warnings-on-reloading-shape-shifting-recipes [ + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> + assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span> + <span class="Comment"># overload a well-known shape-shifting recipe</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe length l:address:list:_elem -> n:number [</span> +<span class="Constant">]</span>] + <span class="Comment"># call code that uses other variants of it, but not it itself</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[x:address:list:number <- copy 0</span> +<span class="Constant">to-text x]</span> + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + <span class="Comment"># run it once</span> + assume-console [ + press F4 + ] + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + <span class="Comment"># no errors anywhere on screen (can't check anything else, since to-text will return an address)</span> + screen-should-contain-in-color <span class="Constant">1/red</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . <- .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] + <span class="Comment"># rerun everything</span> + assume-console [ + press F4 + ] + run [ + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + ] + <span class="Comment"># still no errors</span> + screen-should-contain-in-color <span class="Constant">1/red</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . <- .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] +] + <span class="muScenario">scenario</span> run-shows-missing-type-warnings [ trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span> |