1 //: Calls can also generate products, using 'reply' or 'return'.
  2 
  3 :(scenario return)
  4 def main [
  5   1:num, 2:num <- f 34
  6 ]
  7 def f [
  8   12:num <- next-ingredient
  9   13:num <- add 1, 12:num
 10   return 12:num, 13:num
 11 ]
 12 pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
proc printXyz*() = echo "xyz"

proc foo*(x: int) = echo "B.foo"
"Delimiter">; i < SIZE(ingredients); ++i) 52 ¦ trace(9998, "run") << "result " << i << " is " << to_string(ingredients.at(i)) << end(); 53 // make return products available to caller 54 copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin())); 55 // End Return 56 break; // continue to process rest of *caller* instruction 57 } 58 59 //: Types in return instructions are checked ahead of time. 60 61 :(before "End Checks") 62 Transform.push_back(check_types_of_return_instructions); // idempotent 63 :(code) 64 void check_types_of_return_instructions(const recipe_ordinal r) { 65 const recipe& caller = get(Recipe, r); 66 trace(9991, "transform") << "--- check types of return instructions in recipe " << caller.name << end(); 67 for (int i = 0; i < SIZE(caller.steps); ++i) { 68 ¦ const instruction& caller_instruction = caller.steps.at(i); 69 ¦ if (caller_instruction.is_label) continue; 70 ¦ if (caller_instruction.products.empty()) continue; 71 ¦ if (is_primitive(caller_instruction.operation)) continue; 72 ¦ const recipe& callee = get(Recipe, caller_instruction.operation); 73 ¦ for (int i = 0; i < SIZE(callee.steps); ++i) { 74 ¦ ¦ const instruction& return_inst = callee.steps.at(i); 75 ¦ ¦ if (return_inst.operation != RETURN) continue; 76 ¦ ¦ // check types with the caller 77 ¦ ¦ if (SIZE(caller_instruction.products) > SIZE(return_inst.ingredients)) { 78 ¦ ¦ ¦ raise << maybe(caller.name) << "too few values returned from " << callee.name << '\n' << end(); 79 ¦ ¦ ¦ break; 80 ¦ ¦ } 81 ¦ ¦ for (int i = 0; i < SIZE(caller_instruction.products); ++i) { 82 ¦ ¦ ¦ reagent/*copy*/ lhs = return_inst.ingredients.at(i); 83 ¦ ¦ ¦ reagent/*copy*/ rhs = caller_instruction.products.at(i); 84 ¦ ¦ ¦ // End Check RETURN Copy(lhs, rhs) 85 ¦ ¦ ¦ if (!types_coercible(rhs, lhs)) { 86 ¦ ¦ ¦ ¦ raise << maybe(callee.name) << return_inst.name << " ingredient '" << lhs.original_string << "' can't be saved in '" << rhs.original_string << "'\n" << end(); 87 ¦ ¦ ¦ ¦ raise << " ['" << to_string(lhs.type) << "' vs '" << to_string(rhs.type) << "']\n" << end(); 88 ¦ ¦ ¦ ¦ goto finish_return_check; 89 ¦ ¦ ¦ } 90 ¦ ¦ } 91 ¦ ¦ // check that any return ingredients with /same-as-ingredient connect up 92 ¦ ¦ // the corresponding ingredient and product in the caller. 93 ¦ ¦ for (int i = 0; i < SIZE(caller_instruction.products); ++i) { 94 ¦ ¦ ¦ if (has_property(return_inst.ingredients.at(i), "same-as-ingredient")) { 95 ¦ ¦ ¦ ¦ string_tree* tmp = property(return_inst.ingredients.at(i), "same-as-ingredient"); 96 ¦ ¦ ¦ ¦ if (!tmp || !tmp->atom) { 97 ¦ ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "'same-as-ingredient' metadata should take exactly one value in '" << to_original_string(return_inst) << "'\n" << end(); 98 ¦ ¦ ¦ ¦ ¦ goto finish_return_check; 99 ¦ ¦ ¦ ¦ } 100 ¦ ¦ ¦ ¦ int ingredient_index = to_integer(tmp->value); 101 ¦ ¦ ¦ ¦ if (ingredient_index >= SIZE(caller_instruction.ingredients)) { 102 ¦ ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "too few ingredients in '" << to_original_string(caller_instruction) << "'\n" << end(); 103 ¦ ¦ ¦ ¦ ¦ goto finish_return_check; 104 ¦ ¦ ¦ ¦ } 105 ¦ ¦ ¦ ¦ if (!is_dummy(caller_instruction.products.at(i)) && !is_literal(caller_instruction.ingredients.at(ingredient_index)) && caller_instruction.products.at(i).name != caller_instruction.ingredients.at(ingredient_index).name) { 106 ¦ ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "'" << to_original_string(caller_instruction) << "' should write to '" << caller_instruction.ingredients.at(ingredient_index).original_string << "' rather than '" << caller_instruction.products.at(i).original_string << "'\n" << end(); 107 ¦ ¦ ¦ ¦ } 108 ¦ ¦ ¦ } 109 ¦ ¦ } 110 ¦ ¦ finish_return_check:; 111 ¦ } 112 } 113 } 114 115 bool is_primitive(recipe_ordinal r) { 116 return r < MAX_PRIMITIVE_RECIPES; 117 } 118 119 :(scenario return_type_mismatch) 120 % Hide_errors = true; 121 def main [ 122 3:num <- f 2 123 ] 124 def f [ 125 12:num <- next-ingredient 126 13:num <- copy 35 127 14:point <- copy 12:point/raw 128 return 14:point 129 ] 130 +error: f: return ingredient '14:point' can't be saved in '3:num' 131 132 //: In Mu we'd like to assume that any instruction doesn't modify its 133 //: ingredients unless they're also products. The /same-as-ingredient inside 134 //: the recipe's 'return' indicates that an ingredient is intended to be 135 //: modified in place, and will help catch accidental misuse of such 136 //: 'ingredient-products' (sometimes called in-out parameters in other 137 //: languages). 138 139 :(scenario return_same_as_ingredient) 140 % Hide_errors = true; 141 def main [ 142 1:num <- copy 0 143 2:num <- test1 1:num # call with different ingredient and product 144 ] 145 def test1 [ 146 10:num <- next-ingredient 147 return 10:num/same-as-ingredient:0 148 ] 149 +error: main: '2:num <- test1 1:num' should write to '1:num' rather than '2:num' 150 151 :(scenario return_same_as_ingredient_dummy) 152 def main [ 153 1:num <- copy 0 154 _ <- test1 1:num # call with different ingredient and product 155 ] 156 def test1 [ 157 10:num <- next-ingredient 158 return 10:num/same-as-ingredient:0 159 ] 160 $error: 0 161 162 :(code) 163 string to_string(const vector<double>& in) { 164 if (in.empty()) return "[]"; 165 ostringstream out; 166 if (SIZE(in) == 1) { 167 ¦ out << no_scientific(in.at(0)); 168 ¦ return out.str(); 169 } 170 out << "["; 171 for (int i = 0; i < SIZE(in); ++i) { 172 ¦ if (i > 0) out << ", "; 173 ¦ out << no_scientific(in.at(i)); 174 } 175 out << "]"; 176 return out.str(); 177 }