diff options
Diffstat (limited to 'html')
-rw-r--r-- | html/042name.cc.html | 2 | ||||
-rw-r--r-- | html/053recipe_header.cc.html | 28 | ||||
-rw-r--r-- | html/056shape_shifting_recipe.cc.html | 1 | ||||
-rw-r--r-- | html/071recipe.cc.html | 18 | ||||
-rw-r--r-- | html/081print.mu.html | 363 | ||||
-rw-r--r-- | html/084console.mu.html | 10 | ||||
-rw-r--r-- | html/088file.mu.html | 40 | ||||
-rw-r--r-- | html/091socket.cc.html | 43 | ||||
-rw-r--r-- | html/092socket.mu.html | 212 |
9 files changed, 348 insertions, 369 deletions
diff --git a/html/042name.cc.html b/html/042name.cc.html index d7027161..098fee41 100644 --- a/html/042name.cc.html +++ b/html/042name.cc.html @@ -93,6 +93,7 @@ Name = Name_snapshot<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>ingredient<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!already_transformed<span class="Delimiter">(</span>ingredient<span class="Delimiter">,</span> names<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">"use before set: '"</span> << ingredient<span class="Delimiter">.</span>name << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Comment">// use-before-set Error</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">int</span> v = lookup_name<span class="Delimiter">(</span>ingredient<span class="Delimiter">,</span> r<span class="Delimiter">);</span> @@ -135,6 +136,7 @@ Name = Name_snapshot<span class="Delimiter">;</span> <span class="Normal">bool</span> is_disqualified<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">mutable</span><span class="Comment">*/</span> reagent& x<span class="Delimiter">,</span> <span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> string& recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> << <span class="Constant">"missing type for '"</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">"' in '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Comment">// missing-type Error 1</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> diff --git a/html/053recipe_header.cc.html b/html/053recipe_header.cc.html index d379b46a..021db5f4 100644 --- a/html/053recipe_header.cc.html +++ b/html/053recipe_header.cc.html @@ -258,6 +258,34 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Comment">//: more useful error messages if someone forgets 'load-ingredients'</span> + +<span class="Delimiter">:(scenario load_ingredients_missing_error)</span> +<span class="Special">% Hide_errors = true;</span> +<span class="muRecipe">def</span> foo a:num [ + local-scope + <span class="Normal">b</span>:num<span class="Special"> <- </span>add a:num<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+error: foo: use before set: 'a'</span> +<span class="traceContains">+error: did you forget 'load-ingredients'?</span> + +<span class="Delimiter">:(after "use-before-set Error")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>is_present_in_ingredients<span class="Delimiter">(</span>caller<span class="Delimiter">,</span> ingredient<span class="Delimiter">.</span>name<span class="Delimiter">))</span> + raise << <span class="Constant">" did you forget 'load-ingredients'?</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + +<span class="Delimiter">:(scenario load_ingredients_missing_error_2)</span> +<span class="Special">% Hide_errors = true;</span> +<span class="muRecipe">def</span> foo a:num [ + local-scope + <span class="Normal">b</span>:num<span class="Special"> <- </span>add a<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+error: foo: missing type for 'a' in 'b:num <- add a, 1'</span> +<span class="traceContains">+error: did you forget 'load-ingredients'?</span> + +<span class="Delimiter">:(after "missing-type Error 1")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>is_present_in_ingredients<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> recipe_name<span class="Delimiter">)),</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> + raise << <span class="Constant">" did you forget 'load-ingredients'?</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="SalientComment">//:: Check all calls against headers.</span> <span class="Delimiter">:(scenario show_clear_error_on_bad_call)</span> diff --git a/html/056shape_shifting_recipe.cc.html b/html/056shape_shifting_recipe.cc.html index fa7aa789..32aef874 100644 --- a/html/056shape_shifting_recipe.cc.html +++ b/html/056shape_shifting_recipe.cc.html @@ -361,6 +361,7 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla <span class="Normal">void</span> accumulate_type_ingredients<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* exemplar_type<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* refinement_type<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree*>& mappings<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& exemplar<span class="Delimiter">,</span> <span class="Normal">const</span> reagent& exemplar_reagent<span class="Delimiter">,</span> <span class="Normal">const</span> instruction& call_instruction<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& caller_recipe<span class="Delimiter">,</span> <span class="Normal">bool</span>* error<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!exemplar_type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!refinement_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// probably a bug in mu</span> <span class="Comment">// todo: make this smarter; only flag an error if exemplar_type contains some *new* type ingredient</span> raise << maybe<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"missing type ingredient for "</span> << exemplar_reagent<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> raise << <span class="Constant">" (called from '"</span> << to_original_string<span class="Delimiter">(</span>call_instruction<span class="Delimiter">)</span> << <span class="Constant">"')</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> diff --git a/html/071recipe.cc.html b/html/071recipe.cc.html index 2a63b5e8..7db245d8 100644 --- a/html/071recipe.cc.html +++ b/html/071recipe.cc.html @@ -375,7 +375,7 @@ $error: <span class="Constant">0</span> <span class="Delimiter">}</span> ] <span class="Comment"># error should be as if foo is not a recipe</span> -<span class="traceContains">+error: main: missing type for foo in 'break-if foo'</span> +<span class="traceContains">+error: main: missing type for 'foo' in 'break-if foo'</span> <span class="Delimiter">:(before "End JUMP_IF Checks")</span> check_for_recipe_literals<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">));</span> @@ -384,10 +384,22 @@ check_for_recipe_literals<span class="Delimiter">(</span>inst<span class="Delimi <span class="Delimiter">:(code)</span> <span class="Normal">void</span> check_for_recipe_literals<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_recipe<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"missing type for "</span> << 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">" in '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_recipe<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"missing type for '"</span> << 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">"' in '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_present_in_ingredients<span class="Delimiter">(</span>caller<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> + raise << <span class="Constant">" did you forget 'load-ingredients'?</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario load_ingredients_missing_error_3)</span> +<span class="Special">% Hide_errors = true;</span> +<span class="muRecipe">def</span> foo <span class="Delimiter">{</span>f: <span class="Delimiter">(</span>recipe num<span class="muRecipe"> -> </span>num<span class="Delimiter">)}</span> [ + local-scope + <span class="Normal">b</span>:num<span class="Special"> <- </span>call f<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+error: foo: missing type for 'f' in 'b:num <- call f, 1'</span> +<span class="traceContains">+error: did you forget 'load-ingredients'?</span> </pre> </body> </html> diff --git a/html/081print.mu.html b/html/081print.mu.html index 4955c3b1..241cf857 100644 --- a/html/081print.mu.html +++ b/html/081print.mu.html @@ -62,44 +62,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> clear-screen screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="Comment"># clear fake screen</span> - buf:&:@:screen-cell <span class="Special"><-</span> get *screen, <span class="Constant">data:offset</span> - max:num <span class="Special"><-</span> length *buf - i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> - <span class="Delimiter">{</span> - done?:bool <span class="Special"><-</span> greater-or-equal i, max - <span class="muControl">break-if</span> done? - curr:screen-cell <span class="Special"><-</span> merge <span class="Constant">0/empty</span>, <span class="Constant">7/white</span> - *buf <span class="Special"><-</span> put-index *buf, i, curr - i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="Comment"># reset cursor</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>,<span class="Constant"> 0</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>,<span class="Constant"> 0</span> + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + clear-display <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - clear-display + <span class="Comment"># fake screen</span> + buf:&:@:screen-cell <span class="Special"><-</span> get *screen, <span class="Constant">data:offset</span> + max:num <span class="Special"><-</span> length *buf + i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> + <span class="Delimiter">{</span> + done?:bool <span class="Special"><-</span> greater-or-equal i, max + <span class="muControl">break-if</span> done? + curr:screen-cell <span class="Special"><-</span> merge <span class="Constant">0/empty</span>, <span class="Constant">7/white</span> + *buf <span class="Special"><-</span> put-index *buf, i, curr + i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># reset cursor</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>,<span class="Constant"> 0</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>,<span class="Constant"> 0</span> ] <span class="muRecipe">def</span> sync-screen screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> screen - sync-display - <span class="Delimiter">}</span> - <span class="Comment"># do nothing for fake screens</span> + <span class="muControl">return-if</span> screen <span class="Comment"># do nothing for fake screens</span> + sync-display ] <span class="muRecipe">def</span> fake-screen-is-empty? screen:&:screen<span class="muRecipe"> -> </span>result:bool [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="muControl">return-unless</span> screen, <span class="Constant">1/true</span> + <span class="muControl">return-unless</span> screen, <span class="Constant">1/true</span> <span class="Comment"># do nothing for real screens</span> buf:&:@:screen-cell <span class="Special"><-</span> get *screen, <span class="Constant">data:offset</span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> len:num <span class="Special"><-</span> length *buf @@ -134,76 +130,76 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color c2:num <span class="Special"><-</span> character-to-code c trace<span class="Constant"> 90</span>, <span class="Constant">[print-character]</span>, c2 <span class="Delimiter">{</span> - <span class="Comment"># if x exists</span> - <span class="Comment"># (handle special cases exactly like in the real screen)</span> - <span class="muControl">break-unless</span> screen - width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> - height:num <span class="Special"><-</span> get *screen, <span class="Constant">num-rows:offset</span> - <span class="Comment"># if cursor is out of bounds, silently exit</span> - row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> - legal?:bool <span class="Special"><-</span> greater-or-equal row,<span class="Constant"> 0</span> - <span class="muControl">return-unless</span> legal? - legal? <span class="Special"><-</span> lesser-than row, height - <span class="muControl">return-unless</span> legal? - column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> - legal? <span class="Special"><-</span> greater-or-equal column,<span class="Constant"> 0</span> - <span class="muControl">return-unless</span> legal? - legal? <span class="Special"><-</span> lesser-than column, width - <span class="muControl">return-unless</span> legal? + <span class="Comment"># real screen</span> + <span class="muControl">break-if</span> screen + print-character-to-display c, color, bg-color + <span class="muControl">return</span> + <span class="Delimiter">}</span> + <span class="Comment"># fake screen</span> + <span class="Comment"># (handle special cases exactly like in the real screen)</span> + width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> + height:num <span class="Special"><-</span> get *screen, <span class="Constant">num-rows:offset</span> + <span class="Comment"># if cursor is out of bounds, silently exit</span> + row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> + legal?:bool <span class="Special"><-</span> greater-or-equal row,<span class="Constant"> 0</span> + <span class="muControl">return-unless</span> legal? + legal? <span class="Special"><-</span> lesser-than row, height + <span class="muControl">return-unless</span> legal? + column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> + legal? <span class="Special"><-</span> greater-or-equal column,<span class="Constant"> 0</span> + <span class="muControl">return-unless</span> legal? + legal? <span class="Special"><-</span> lesser-than column, width + <span class="muControl">return-unless</span> legal? <span class="CommentedCode">#? $print [print-character (], row, [, ], column, [): ], c, 10/newline</span> - <span class="Comment"># special-case: newline</span> - <span class="Delimiter">{</span> - newline?:bool <span class="Special"><-</span> equal c, <span class="Constant">10/newline</span> - <span class="muControl">break-unless</span> newline? - <span class="Delimiter">{</span> - <span class="Comment"># unless cursor is already at bottom</span> - bottom:num <span class="Special"><-</span> subtract height,<span class="Constant"> 1</span> - at-bottom?:bool <span class="Special"><-</span> greater-or-equal row, bottom - <span class="muControl">break-if</span> at-bottom? - <span class="Comment"># move it to the next row</span> - column <span class="Special"><-</span> copy<span class="Constant"> 0</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column - row <span class="Special"><-</span> add row,<span class="Constant"> 1</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, row - <span class="Delimiter">}</span> - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># save character in fake screen</span> - index:num <span class="Special"><-</span> multiply row, width - index <span class="Special"><-</span> add index, column - buf:&:@:screen-cell <span class="Special"><-</span> get *screen, <span class="Constant">data:offset</span> - len:num <span class="Special"><-</span> length *buf - <span class="Comment"># special-case: backspace</span> + <span class="Comment"># special-case: newline</span> + <span class="Delimiter">{</span> + newline?:bool <span class="Special"><-</span> equal c, <span class="Constant">10/newline</span> + <span class="muControl">break-unless</span> newline? <span class="Delimiter">{</span> - backspace?:bool <span class="Special"><-</span> equal c,<span class="Constant"> 8</span> - <span class="muControl">break-unless</span> backspace? - <span class="Delimiter">{</span> - <span class="Comment"># unless cursor is already at left margin</span> - at-left?:bool <span class="Special"><-</span> lesser-or-equal column,<span class="Constant"> 0</span> - <span class="muControl">break-if</span> at-left? - <span class="Comment"># clear previous location</span> - column <span class="Special"><-</span> subtract column,<span class="Constant"> 1</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column - index <span class="Special"><-</span> subtract index,<span class="Constant"> 1</span> - cursor:screen-cell <span class="Special"><-</span> merge <span class="Constant">32/space</span>, <span class="Constant">7/white</span> - *buf <span class="Special"><-</span> put-index *buf, index, cursor - <span class="Delimiter">}</span> - <span class="muControl">return</span> + <span class="Comment"># unless cursor is already at bottom</span> + bottom:num <span class="Special"><-</span> subtract height,<span class="Constant"> 1</span> + at-bottom?:bool <span class="Special"><-</span> greater-or-equal row, bottom + <span class="muControl">break-if</span> at-bottom? + <span class="Comment"># move it to the next row</span> + column <span class="Special"><-</span> copy<span class="Constant"> 0</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column + row <span class="Special"><-</span> add row,<span class="Constant"> 1</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, row <span class="Delimiter">}</span> - cursor:screen-cell <span class="Special"><-</span> merge c, color - *buf <span class="Special"><-</span> put-index *buf, index, cursor - <span class="Comment"># increment column unless it's already all the way to the right</span> + <span class="muControl">return</span> + <span class="Delimiter">}</span> + <span class="Comment"># save character in fake screen</span> + index:num <span class="Special"><-</span> multiply row, width + index <span class="Special"><-</span> add index, column + buf:&:@:screen-cell <span class="Special"><-</span> get *screen, <span class="Constant">data:offset</span> + len:num <span class="Special"><-</span> length *buf + <span class="Comment"># special-case: backspace</span> + <span class="Delimiter">{</span> + backspace?:bool <span class="Special"><-</span> equal c,<span class="Constant"> 8</span> + <span class="muControl">break-unless</span> backspace? <span class="Delimiter">{</span> - right:num <span class="Special"><-</span> subtract width,<span class="Constant"> 1</span> - at-right?:bool <span class="Special"><-</span> greater-or-equal column, right - <span class="muControl">break-if</span> at-right? - column <span class="Special"><-</span> add column,<span class="Constant"> 1</span> + <span class="Comment"># unless cursor is already at left margin</span> + at-left?:bool <span class="Special"><-</span> lesser-or-equal column,<span class="Constant"> 0</span> + <span class="muControl">break-if</span> at-left? + <span class="Comment"># clear previous location</span> + column <span class="Special"><-</span> subtract column,<span class="Constant"> 1</span> *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column + index <span class="Special"><-</span> subtract index,<span class="Constant"> 1</span> + cursor:screen-cell <span class="Special"><-</span> merge <span class="Constant">32/space</span>, <span class="Constant">7/white</span> + *buf <span class="Special"><-</span> put-index *buf, index, cursor <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - print-character-to-display c, color, bg-color + cursor:screen-cell <span class="Special"><-</span> merge c, color + *buf <span class="Special"><-</span> put-index *buf, index, cursor + <span class="Comment"># increment column unless it's already all the way to the right</span> + <span class="Delimiter">{</span> + right:num <span class="Special"><-</span> subtract width,<span class="Constant"> 1</span> + at-right?:bool <span class="Special"><-</span> greater-or-equal column, right + <span class="muControl">break-if</span> at-right? + column <span class="Special"><-</span> add column,<span class="Constant"> 1</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column + <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> print-character-at-top-left [ @@ -400,27 +396,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> space:char <span class="Special"><-</span> copy <span class="Constant">0/nul</span> - <span class="Comment"># if x exists, clear line in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> - column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> - original-column:num <span class="Special"><-</span> copy column - <span class="Comment"># space over the entire line</span> - <span class="Delimiter">{</span> - right:num <span class="Special"><-</span> subtract width,<span class="Constant"> 1</span> - done?:bool <span class="Special"><-</span> greater-or-equal column, right - <span class="muControl">break-if</span> done? - print screen, space - column <span class="Special"><-</span> add column,<span class="Constant"> 1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - <span class="Comment"># now back to where the cursor was</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, original-column + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + clear-line-on-display <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - clear-line-on-display + <span class="Comment"># fake screen</span> + width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> + column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> + original-column:num <span class="Special"><-</span> copy column + <span class="Comment"># space over the entire line</span> + <span class="Delimiter">{</span> + right:num <span class="Special"><-</span> subtract width,<span class="Constant"> 1</span> + done?:bool <span class="Special"><-</span> greater-or-equal column, right + <span class="muControl">break-if</span> done? + print screen, space + column <span class="Special"><-</span> add column,<span class="Constant"> 1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># now back to where the cursor was</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, original-column ] <span class="muRecipe">def</span> clear-line-until screen:&:screen, right:num/inclusive<span class="muRecipe"> -> </span>screen:&:screen [ @@ -446,28 +442,29 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> cursor-position screen:&:screen<span class="muRecipe"> -> </span>row:num, column:num [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, lookup cursor in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> - column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + row, column <span class="Special"><-</span> cursor-position-on-display <span class="muControl">return</span> <span class="Delimiter">}</span> - row, column <span class="Special"><-</span> cursor-position-on-display + <span class="Comment"># fake screen</span> + row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> + column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> ] <span class="muRecipe">def</span> move-cursor screen:&:screen, new-row:num, new-column:num<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, new-row - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, new-column + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + move-cursor-on-display new-row, new-column <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - move-cursor-on-display new-row, new-column + <span class="Comment"># fake screen</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, new-row + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, new-column ] <span class="muScenario">scenario</span> clear-line-erases-printed-characters [ @@ -504,85 +501,73 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> cursor-down screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="Delimiter">{</span> - <span class="Comment"># increment row unless it's already all the way down</span> - height:num <span class="Special"><-</span> get *screen, <span class="Constant">num-rows:offset</span> - row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> - max:num <span class="Special"><-</span> subtract height,<span class="Constant"> 1</span> - at-bottom?:bool <span class="Special"><-</span> greater-or-equal row, max - <span class="muControl">break-if</span> at-bottom? - row <span class="Special"><-</span> add row,<span class="Constant"> 1</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, row - <span class="Delimiter">}</span> + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + move-cursor-down-on-display <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - move-cursor-down-on-display + <span class="Comment"># fake screen</span> + height:num <span class="Special"><-</span> get *screen, <span class="Constant">num-rows:offset</span> + row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> + max:num <span class="Special"><-</span> subtract height,<span class="Constant"> 1</span> + at-bottom?:bool <span class="Special"><-</span> greater-or-equal row, max + <span class="muControl">return-if</span> at-bottom? + row <span class="Special"><-</span> add row,<span class="Constant"> 1</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, row ] <span class="muRecipe">def</span> cursor-up screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="Delimiter">{</span> - <span class="Comment"># decrement row unless it's already all the way up</span> - row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> - at-top?:bool <span class="Special"><-</span> lesser-or-equal row,<span class="Constant"> 0</span> - <span class="muControl">break-if</span> at-top? - row <span class="Special"><-</span> subtract row,<span class="Constant"> 1</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, row - <span class="Delimiter">}</span> + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + move-cursor-up-on-display <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - move-cursor-up-on-display + <span class="Comment"># fake screen</span> + row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> + at-top?:bool <span class="Special"><-</span> lesser-or-equal row,<span class="Constant"> 0</span> + <span class="muControl">return-if</span> at-top? + row <span class="Special"><-</span> subtract row,<span class="Constant"> 1</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-row:offset</span>, row ] <span class="muRecipe">def</span> cursor-right screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="Delimiter">{</span> - <span class="Comment"># increment column unless it's already all the way to the right</span> - width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> - column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> - max:num <span class="Special"><-</span> subtract width,<span class="Constant"> 1</span> - at-bottom?:bool <span class="Special"><-</span> greater-or-equal column, max - <span class="muControl">break-if</span> at-bottom? - column <span class="Special"><-</span> add column,<span class="Constant"> 1</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column - <span class="Delimiter">}</span> + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + move-cursor-right-on-display <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - move-cursor-right-on-display + <span class="Comment"># fake screen</span> + width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> + column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> + max:num <span class="Special"><-</span> subtract width,<span class="Constant"> 1</span> + at-bottom?:bool <span class="Special"><-</span> greater-or-equal column, max + <span class="muControl">return-if</span> at-bottom? + column <span class="Special"><-</span> add column,<span class="Constant"> 1</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column ] <span class="muRecipe">def</span> cursor-left screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="Delimiter">{</span> - <span class="Comment"># decrement column unless it's already all the way to the left</span> - column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> - at-top?:bool <span class="Special"><-</span> lesser-or-equal column,<span class="Constant"> 0</span> - <span class="muControl">break-if</span> at-top? - column <span class="Special"><-</span> subtract column,<span class="Constant"> 1</span> - *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column - <span class="Delimiter">}</span> + <span class="muControl">break-if</span> screen + <span class="Comment"># real screen</span> + move-cursor-left-on-display <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> - move-cursor-left-on-display + <span class="Comment"># fake screen</span> + column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> + at-top?:bool <span class="Special"><-</span> lesser-or-equal column,<span class="Constant"> 0</span> + <span class="muControl">return-if</span> at-top? + column <span class="Special"><-</span> subtract column,<span class="Constant"> 1</span> + *screen <span class="Special"><-</span> put *screen, <span class="Constant">cursor-column:offset</span>, column ] <span class="muRecipe">def</span> cursor-to-start-of-line screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ @@ -610,76 +595,58 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> screen-width screen:&:screen<span class="muRecipe"> -> </span>width:num [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen + <span class="Comment"># fake screen</span> width <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> + <span class="Comment"># real screen</span> width <span class="Special"><-</span> display-width ] <span class="muRecipe">def</span> screen-height screen:&:screen<span class="muRecipe"> -> </span>height:num [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists, move cursor in fake screen</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> screen + <span class="Comment"># fake screen</span> height <span class="Special"><-</span> get *screen, <span class="Constant">num-rows:offset</span> <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> + <span class="Comment"># real screen</span> height <span class="Special"><-</span> display-height ] <span class="muRecipe">def</span> hide-cursor screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists (not real display), do nothing</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> + <span class="muControl">reply-if</span> screen <span class="Comment"># fake screen; do nothing</span> + <span class="Comment"># real screen</span> hide-cursor-on-display ] <span class="muRecipe">def</span> show-cursor screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists (not real display), do nothing</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> + <span class="muControl">reply-if</span> screen <span class="Comment"># fake screen; do nothing</span> + <span class="Comment"># real screen</span> show-cursor-on-display ] <span class="muRecipe">def</span> hide-screen screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists (not real display), do nothing</span> - <span class="Comment"># todo: help test this</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> + <span class="muControl">reply-if</span> screen <span class="Comment"># fake screen; do nothing</span> + <span class="Comment"># real screen</span> hide-display ] <span class="muRecipe">def</span> show-screen screen:&:screen<span class="muRecipe"> -> </span>screen:&:screen [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Comment"># if x exists (not real display), do nothing</span> - <span class="Comment"># todo: help test this</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> screen - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># otherwise, real screen</span> + <span class="muControl">reply-if</span> screen <span class="Comment"># fake screen; do nothing</span> + <span class="Comment"># real screen</span> show-display ] diff --git a/html/084console.mu.html b/html/084console.mu.html index 9271231a..5cb819de 100644 --- a/html/084console.mu.html +++ b/html/084console.mu.html @@ -123,7 +123,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> _, found?:bool <span class="Special"><-</span> read-event console - <span class="muControl">loop-unless</span> found? + <span class="muControl">break-if</span> found? + switch + <span class="muControl">loop</span> <span class="Delimiter">}</span> ] @@ -131,11 +133,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">def</span> has-more-events? console:&:console<span class="muRecipe"> -> </span>result:bool [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> console - <span class="Comment"># fake consoles should be plenty fast; never skip</span> - <span class="muControl">return</span> <span class="Constant">0/false</span> - <span class="Delimiter">}</span> + <span class="muControl">return-if</span> console, <span class="Constant">0/false</span> <span class="Comment"># fake consoles should be plenty fast; never skip</span> result <span class="Special"><-</span> interactions-left? ] </pre> diff --git a/html/088file.mu.html b/html/088file.mu.html index e6ef6e98..26fa0c7c 100644 --- a/html/088file.mu.html +++ b/html/088file.mu.html @@ -47,15 +47,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> - <span class="muControl">break-if</span> resources - <span class="Comment"># real file system</span> - file:num <span class="Special"><-</span> $open-file-for-reading filename - assert file, <span class="Constant">[file not found]</span> - contents:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 30</span> - start-running receive-from-file file, sink + <span class="muControl">break-unless</span> resources + <span class="Comment"># fake file system</span> + contents <span class="Special"><-</span> start-reading-from-fake-resources resources, filename <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># fake file system</span> + <span class="Comment"># real file system</span> + file:num <span class="Special"><-</span> $open-file-for-reading filename + assert file, <span class="Constant">[file not found]</span> + contents:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 30</span> + start-running receive-from-file file, sink +] + +<span class="muRecipe">def</span> start-reading-from-fake-resources resources:&:resources, resource:text<span class="muRecipe"> -> </span>contents:&:source:char [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> data:&:@:resource <span class="Special"><-</span> get *resources, <span class="Constant">data:offset</span> len:num <span class="Special"><-</span> length *data @@ -64,8 +70,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-if</span> done? tmp:resource <span class="Special"><-</span> index *data, i i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> - curr-filename:text <span class="Special"><-</span> get tmp, <span class="Constant">name:offset</span> - found?:bool <span class="Special"><-</span> equal filename, curr-filename + curr-resource:text <span class="Special"><-</span> get tmp, <span class="Constant">name:offset</span> + found?:bool <span class="Special"><-</span> equal resource, curr-resource <span class="muControl">loop-unless</span> found? contents:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 30</span> curr-contents:text <span class="Special"><-</span> get tmp, <span class="Constant">contents:offset</span> @@ -109,16 +115,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">load-ingredients</span> source:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 30</span> <span class="Delimiter">{</span> - <span class="muControl">break-if</span> resources - <span class="Comment"># real file system</span> - file:num <span class="Special"><-</span> $open-file-for-writing filename - assert file, <span class="Constant">[no such file]</span> - routine-id <span class="Special"><-</span> start-running transmit-to-file file, source + <span class="muControl">break-unless</span> resources + <span class="Comment"># fake file system</span> + <span class="Comment"># beware: doesn't support multiple concurrent writes yet</span> + routine-id <span class="Special"><-</span> start-running transmit-to-fake-file resources, filename, source <span class="muControl">reply</span> <span class="Delimiter">}</span> - <span class="Comment"># fake file system</span> - <span class="Comment"># beware: doesn't support multiple concurrent writes yet</span> - routine-id <span class="Special"><-</span> start-running transmit-to-fake-file resources, filename, source + <span class="Comment"># real file system</span> + file:num <span class="Special"><-</span> $open-file-for-writing filename + assert file, <span class="Constant">[no such file]</span> + routine-id <span class="Special"><-</span> start-running transmit-to-file file, source ] <span class="muRecipe">def</span> transmit-to-file file:num, source:&:source:char<span class="muRecipe"> -> </span>source:&:source:char [ diff --git a/html/091socket.cc.html b/html/091socket.cc.html index 67f11eb1..e205508f 100644 --- a/html/091socket.cc.html +++ b/html/091socket.cc.html @@ -235,22 +235,32 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of '$read-from-socket' should be a number, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$read-from-socket' requires exactly two products, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Normal">int</span> nprod = SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>nprod == <span class="Constant">0</span> || nprod > <span class="Constant">4</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$read-from-socket' requires 1-4 products, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_text<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first product of '$read-from-socket' should be a text (address array character), but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_boolean<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second product of '$read-from-socket' should be a boolean (eof?), but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>nprod > <span class="Constant">1</span> && !is_mu_boolean<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second product of '$read-from-socket' should be a boolean (data received?), but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>nprod > <span class="Constant">2</span> && !is_mu_boolean<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"third product of '$read-from-socket' should be a boolean (eof?), but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>nprod > <span class="Constant">3</span> && !is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"fourth product of '$read-from-socket' should be a number (error code), but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> _READ_FROM_SOCKET: <span class="Delimiter">{</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">4</span><span class="Delimiter">);</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> socket_t* socket = <span class="Normal">reinterpret_cast</span><socket_t*><span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Comment">// 1. we'd like to simply read() from the socket</span> @@ -260,26 +270,37 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">// 3. but poll() will block on EOF, so only use poll() on the very first</span> <span class="Comment">// $read-from-socket on a socket</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!socket<span class="Delimiter">-></span>polled<span class="Delimiter">)</span> <span class="Delimiter">{</span> - socket<span class="Delimiter">-></span>polled = <span class="Constant">true</span><span class="Delimiter">;</span> pollfd p<span class="Delimiter">;</span> bzero<span class="Delimiter">(</span>&p<span class="Delimiter">,</span> <span class="Normal">sizeof</span><span class="Delimiter">(</span>p<span class="Delimiter">));</span> p<span class="Delimiter">.</span>fd = socket<span class="Delimiter">-></span>fd<span class="Delimiter">;</span> p<span class="Delimiter">.</span>events = POLLIN | POLLHUP<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>poll<span class="Delimiter">(</span>&p<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">num pollfds</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">no timeout</span><span class="Comment">*/</span>-<span class="Constant">1</span><span class="Delimiter">)</span> <= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">int</span> status = poll<span class="Delimiter">(</span>&p<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">num pollfds</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">timeout</span><span class="Comment">*/</span><span class="Constant">100</span><span class="Comment">/*</span><span class="Comment">ms</span><span class="Comment">*/</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>status == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">no data</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">found</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">eof</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">error</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>status < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">int</span> error_code = errno<span class="Delimiter">;</span> raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"error in $read-from-socket</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">false</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">no data</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">found</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">eof</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>error_code<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + socket<span class="Delimiter">-></span>polled = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">int</span> bytes = <span class="Normal">static_cast</span><<span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Normal">char</span>* contents = <span class="Normal">new</span> <span class="Normal">char</span>[bytes]<span class="Delimiter">;</span> bzero<span class="Delimiter">(</span>contents<span class="Delimiter">,</span> bytes<span class="Delimiter">);</span> <span class="Normal">int</span> bytes_read = recv<span class="Delimiter">(</span>socket<span class="Delimiter">-></span>fd<span class="Delimiter">,</span> contents<span class="Delimiter">,</span> bytes-<span class="Comment">/*</span><span class="Comment">terminal null</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> MSG_DONTWAIT<span class="Delimiter">);</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>new_mu_text<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>bytes_read <= <span class="Constant">0</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">found</span><span class="Comment">*/</span><span class="Constant">true</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">eof</span><span class="Comment">*/</span>bytes_read <= <span class="Constant">0</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">error</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Normal">delete</span> contents<span class="Delimiter">;</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/092socket.mu.html b/html/092socket.mu.html index 3b18e2cd..78321183 100644 --- a/html/092socket.mu.html +++ b/html/092socket.mu.html @@ -19,7 +19,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .Special { color: #c00000; } -.CommentedCode { color: #6c6c6c; } .muRecipe { color: #ff8700; } .muScenario { color: #00af00; } --> @@ -33,98 +32,95 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color </head> <body> <pre id='vimCodeElement'> -<span class="Comment"># Wrappers around socket primitives that take a 'local-network' object and are</span> -<span class="Comment"># thus easier to test.</span> -<span class="Comment">#</span> -<span class="Comment"># The current semantics of fake port-connections don't match UNIX socket ones,</span> -<span class="Comment"># but we'll improve them as we learn more.</span> +<span class="Comment"># Wrappers around socket primitives that are easier to test.</span> -<span class="muData">container</span> local-network [ - data:&:@:port-connection -] - -<span class="Comment"># Port connections represent connections to ports on localhost.</span> -<span class="Comment"># Before passing a local-network object to network functions</span> -<span class="Comment"># `start-reading-socket` and `start-writing-socket`, add port-connections to</span> -<span class="Comment"># the local-network.</span> -<span class="Comment">#</span> -<span class="Comment"># For reading, `receive-from-socket` will check for a</span> -<span class="Comment"># port-connection on the port parameter that's been passed in. If there's</span> -<span class="Comment"># no port-connection for that port, it will return nothing and log an error.</span> -<span class="Comment"># If there is a port-connection for that port, it will transmit the contents</span> -<span class="Comment"># to the provided sink.</span> -<span class="Comment">#</span> -<span class="Comment"># For writing, `start-writing-socket` returns a sink connecting the</span> -<span class="Comment"># caller to the socket on the passed-in port.</span> -<span class="muData">container</span> port-connection [ - port:num - contents:text -] - -<span class="muRecipe">def</span> new-port-connection port:num, contents:text<span class="muRecipe"> -> </span>p:&:port-connection [ +<span class="Comment"># To test server operations, just run a real client against localhost.</span> +<span class="muScenario">scenario</span> example-server-test [ <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - p:&:port-connection <span class="Special"><-</span> new <span class="Constant">port-connection:type</span> - *p <span class="Special"><-</span> merge port, contents + <span class="Comment"># test server without a fake on a random (real) port</span> + <span class="Comment"># that way repeatedly running the test will give ports time to timeout and</span> + <span class="Comment"># close before reusing them</span> + make-random-nondeterministic + port:num <span class="Special"><-</span> random-in-range <span class="Constant">0/real-random-numbers</span>,<span class="Constant"> 8000</span>,<span class="Constant"> 8100</span> + run [ + socket:num <span class="Special"><-</span> $open-server-socket port + assert socket, <span class="Constant">[ </span> +<span class="Constant">F - example-server-test: $open-server-socket failed]</span> + handler-routine:number <span class="Special"><-</span> start-running serve-one-request socket, example-handler + ] + source:&:source:char <span class="Special"><-</span> start-reading-from-network <span class="Constant">0/real-resources</span>, <span class="Constant">[localhost/]</span>, port + response:text <span class="Special"><-</span> drain source + 10:@:char/<span class="Special">raw</span> <span class="Special"><-</span> copy *response + memory-should-contain [ + 10:array:character <span class="Special"><-</span> <span class="Constant">[abc]</span> + ] ] - -<span class="muRecipe">def</span> new-fake-network<span class="muRecipe"> -> </span>n:&:local-network [ +<span class="Comment"># helper just for this scenario</span> +<span class="muRecipe">def</span> example-handler query:text<span class="muRecipe"> -> </span>response:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - n:&:local-network <span class="Special"><-</span> new <span class="Constant">local-network:type</span> - local-network-ports:&:@:port-connection <span class="Special"><-</span> new <span class="Constant">port-connection:type</span>,<span class="Constant"> 0</span> - *n <span class="Special"><-</span> put *n, <span class="Constant">data:offset</span>, local-network-ports + <span class="muControl">reply</span> <span class="Constant">[abc]</span> ] -<span class="muScenario">scenario</span> write-to-fake-socket [ +<span class="Comment"># To test client operations, use `assume-resources` with a filename that</span> +<span class="Comment"># begins with a hostname. (Filenames starting with '/' are assumed to be</span> +<span class="Comment"># local.)</span> +<span class="muScenario">scenario</span> example-client-test [ <span class="Constant">local-scope</span> - single-port-network:&:local-network <span class="Special"><-</span> new-fake-network - sink:&:sink:char, writer:num/routine <span class="Special"><-</span> start-writing-socket single-port-network,<span class="Constant"> 8080</span> - sink <span class="Special"><-</span> write sink, <span class="Constant">120/x</span> - close sink - wait-for-routine writer - tested-port-connections:&:@:port-connection <span class="Special"><-</span> get *single-port-network, <span class="Constant">data:offset</span> - tested-port-connection:port-connection <span class="Special"><-</span> index *tested-port-connections,<span class="Constant"> 0</span> - contents:text <span class="Special"><-</span> get tested-port-connection, <span class="Constant">contents:offset</span> + assume-resources [ + <span class="Constant">[example.com/]</span> <span class="Special"><-</span> [ +<span class="Constant"> |abc|</span> + ] + ] + run [ + source:&:source:char <span class="Special"><-</span> start-reading-from-network resources, <span class="Constant">[example.com/]</span> + ] + contents:text <span class="Special"><-</span> drain source 10:@:char/<span class="Special">raw</span> <span class="Special"><-</span> copy *contents memory-should-contain [ - 10:array:character <span class="Special"><-</span> <span class="Constant">[x]</span> + 10:array:character <span class="Special"><-</span> <span class="Constant">[abc</span> +<span class="Constant">]</span> ] ] +<span class="muData">type</span> request-handler = (recipe text<span class="muRecipe"> -> </span>text) + +<span class="muRecipe">def</span> serve-one-request socket:num, request-handler:request-handler [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + session:num <span class="Special"><-</span> $accept socket + assert session, <span class="Constant">[ </span> +<span class="Constant">F - example-server-test: $accept failed]</span> + contents:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 30</span> + sink <span class="Special"><-</span> start-running receive-from-socket session, sink + query:text <span class="Special"><-</span> drain contents + response:text <span class="Special"><-</span> call request-handler, query + write-to-socket session, response + $close-socket session +] + <span class="muRecipe">def</span> start-reading-from-network resources:&:resources, uri:text<span class="muRecipe"> -> </span>contents:&:source:char [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> - <span class="muControl">break-if</span> resources - <span class="Comment"># real network</span> - host:text, path:text <span class="Special"><-</span> split-at uri, <span class="Constant">47/slash</span> - socket:num <span class="Special"><-</span> $open-client-socket host, <span class="Constant">80/http-port</span> - assert socket, <span class="Constant">[contents]</span> - req:text <span class="Special"><-</span> interpolate <span class="Constant">[GET _ HTTP/1.1]</span>, path - request-socket socket, req - contents:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 10000</span> - start-running receive-from-socket socket, sink + port:num, port-found?:boolean <span class="Special"><-</span> <span class="Constant">next-ingredient</span> + <span class="muControl">break-if</span> port-found? + port <span class="Special"><-</span> copy <span class="Constant">80/http-port</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> resources + <span class="Comment"># fake network</span> + contents <span class="Special"><-</span> start-reading-from-fake-resources resources, uri <span class="muControl">return</span> <span class="Delimiter">}</span> - <span class="Comment"># fake network</span> -<span class="CommentedCode">#? i:num <- copy 0</span> -<span class="CommentedCode">#? data:&:@:resource <- get *fs, data:offset</span> -<span class="CommentedCode">#? len:num <- length *data</span> -<span class="CommentedCode">#? {</span> -<span class="CommentedCode">#? done?:bool <- greater-or-equal i, len</span> -<span class="CommentedCode">#? break-if done?</span> -<span class="CommentedCode">#? tmp:resource <- index *data, i</span> -<span class="CommentedCode">#? i <- add i, 1</span> -<span class="CommentedCode">#? curr-filename:text <- get tmp, name:offset</span> -<span class="CommentedCode">#? found?:bool <- equal filename, curr-filename</span> -<span class="CommentedCode">#? loop-unless found?</span> -<span class="CommentedCode">#? contents:&:source:char, sink:&:sink:char <- new-channel 30</span> -<span class="CommentedCode">#? curr-contents:text <- get tmp, contents:offset</span> -<span class="CommentedCode">#? start-running transmit-from-text curr-contents, sink</span> -<span class="CommentedCode">#? return</span> -<span class="CommentedCode">#? }</span> - <span class="muControl">return</span> <span class="Constant">0/not-found</span> + <span class="Comment"># real network</span> + host:text, path:text <span class="Special"><-</span> split-at uri, <span class="Constant">47/slash</span> + socket:num <span class="Special"><-</span> $open-client-socket host, port + assert socket, <span class="Constant">[contents]</span> + req:text <span class="Special"><-</span> interpolate <span class="Constant">[GET _ HTTP/1.1]</span>, path + request-socket socket, req + contents:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 10000</span> + start-running receive-from-socket socket, sink ] <span class="muRecipe">def</span> request-socket socket:num, s:text<span class="muRecipe"> -> </span>socket:num [ @@ -138,70 +134,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color $write-to-socket socket, <span class="Constant">10/lf</span> ] -<span class="muRecipe">def</span> start-writing-socket network:&:local-network, port:num<span class="muRecipe"> -> </span>sink:&:sink:char, routine-id:num [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - source:&:source:char, sink:&:sink:char <span class="Special"><-</span> new-channel<span class="Constant"> 30</span> - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> network - socket:num <span class="Special"><-</span> $open-server-socket port - session:num <span class="Special"><-</span> $accept socket - <span class="Comment"># TODO Create channel implementation of write-to-socket.</span> - <span class="muControl">return</span> sink, <span class="Constant">0/routine-id</span> - <span class="Delimiter">}</span> - <span class="Comment"># fake network</span> - routine-id <span class="Special"><-</span> start-running transmit-to-fake-socket network, port, source -] - -<span class="muRecipe">def</span> transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char<span class="muRecipe"> -> </span>network:&:local-network, source:&:source:char [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - <span class="Comment"># compute new port connection contents</span> - buf:&:buffer <span class="Special"><-</span> new-buffer<span class="Constant"> 30</span> - <span class="Delimiter">{</span> - c:char, done?:bool, source <span class="Special"><-</span> read source - <span class="muControl">break-unless</span> c - buf <span class="Special"><-</span> append buf, c - <span class="muControl">break-if</span> done? - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - contents:text <span class="Special"><-</span> buffer-to-array buf - new-port-connection:&:port-connection <span class="Special"><-</span> new-port-connection port, contents - <span class="Comment"># Got the contents of the channel, time to write to fake port.</span> - i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> - port-connections:&:@:port-connection <span class="Special"><-</span> get *network, <span class="Constant">data:offset</span> - len:num <span class="Special"><-</span> length *port-connections - <span class="Delimiter">{</span> - done?:bool <span class="Special"><-</span> greater-or-equal i, len - <span class="muControl">break-if</span> done? - current:port-connection <span class="Special"><-</span> index *port-connections, i - current-port:num <span class="Special"><-</span> get current, <span class="Constant">port:offset</span> - ports-match?:bool <span class="Special"><-</span> equal current-port, port - i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> - <span class="muControl">loop-unless</span> ports-match? - <span class="Comment"># Found an existing connection on this port, overwrite.</span> - put-index *port-connections, i, *new-port-connection - <span class="muControl">reply</span> - <span class="Delimiter">}</span> - <span class="Comment"># Couldn't find an existing connection on this port, initialize a new one.</span> - new-len:num <span class="Special"><-</span> add len,<span class="Constant"> 1</span> - new-port-connections:&:@:port-connection <span class="Special"><-</span> new <span class="Constant">port-connection:type</span>, new-len - put *network, <span class="Constant">data:offset</span>, new-port-connections - i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> - <span class="Delimiter">{</span> - done?:bool <span class="Special"><-</span> greater-or-equal i, len - <span class="muControl">break-if</span> done? - tmp:port-connection <span class="Special"><-</span> index *port-connections, i - put-index *new-port-connections, i, tmp - <span class="Delimiter">}</span> - put-index *new-port-connections, len, *new-port-connection -] - <span class="muRecipe">def</span> receive-from-socket socket:num, sink:&:sink:char<span class="muRecipe"> -> </span>sink:&:sink:char [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> - req:text, eof?:bool <span class="Special"><-</span> $read-from-socket socket, <span class="Constant">4096/bytes</span> +<span class="Constant"> +next-attempt</span> + req:text, found?:bool, eof?:bool, error:num <span class="Special"><-</span> $read-from-socket socket, <span class="Constant">4096/bytes</span> + <span class="muControl">break-if</span> error + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> found? + switch + <span class="muControl">loop</span> <span class="Constant">+next-attempt</span> + <span class="Delimiter">}</span> bytes-read:num <span class="Special"><-</span> length *req i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> <span class="Delimiter">{</span> |