summary refs log blame commit diff stats
path: root/doc/pydoc/ranger.container.keybuffer.html
blob: 07d9ad4f27f531f3e2b43510eea2db6bf07399e3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
 

                                                                    






                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                 












                                                                                                                                          







                                                                                                  
                                                                                          









                                                                                                   
                                                                                                                                                                                 











































                                                                                                                                                                                           
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module ranger.container.keybuffer</title>
</head><body bgcolor="#f0f0f8">

<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.<a href="ranger.container.html"><font color="#ffffff">container</font></a>.keybuffer</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/container/keybuffer.py">/home/hut/ranger/ranger/container/keybuffer.py</a></font></td></tr></table>
    <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2009,&nbsp;2010&nbsp;hut&nbsp;&lt;hut@lavabit.com&gt;<br>
#<br>
#&nbsp;Permission&nbsp;to&nbsp;use,&nbsp;copy,&nbsp;modify,&nbsp;and/or&nbsp;distribute&nbsp;this&nbsp;software&nbsp;for&nbsp;any<br>
#&nbsp;purpose&nbsp;with&nbsp;or&nbsp;without&nbsp;fee&nbsp;is&nbsp;hereby&nbsp;granted,&nbsp;provided&nbsp;that&nbsp;the&nbsp;above<br>
#&nbsp;copyright&nbsp;notice&nbsp;and&nbsp;this&nbsp;permission&nbsp;notice&nbsp;appear&nbsp;in&nbsp;all&nbsp;copies.<br>
#<br>
#&nbsp;THE&nbsp;SOFTWARE&nbsp;IS&nbsp;PROVIDED&nbsp;"AS&nbsp;IS"&nbsp;AND&nbsp;THE&nbsp;AUTHOR&nbsp;DISCLAIMS&nbsp;ALL&nbsp;WARRANTIES<br>
#&nbsp;WITH&nbsp;REGARD&nbsp;TO&nbsp;THIS&nbsp;SOFTWARE&nbsp;INCLUDING&nbsp;ALL&nbsp;IMPLIED&nbsp;WARRANTIES&nbsp;OF<br>
#&nbsp;MERCHANTABILITY&nbsp;AND&nbsp;FITNESS.&nbsp;IN&nbsp;NO&nbsp;EVENT&nbsp;SHALL&nbsp;THE&nbsp;AUTHOR&nbsp;BE&nbsp;LIABLE&nbsp;FOR<br>
#&nbsp;ANY&nbsp;SPECIAL,&nbsp;DIRECT,&nbsp;INDIRECT,&nbsp;OR&nbsp;CONSEQUENTIAL&nbsp;DAMAGES&nbsp;OR&nbsp;ANY&nbsp;DAMAGES<br>
#&nbsp;WHATSOEVER&nbsp;RESULTING&nbsp;FROM&nbsp;LOSS&nbsp;OF&nbsp;USE,&nbsp;DATA&nbsp;OR&nbsp;PROFITS,&nbsp;WHETHER&nbsp;IN&nbsp;AN<br>
#&nbsp;ACTION&nbsp;OF&nbsp;CONTRACT,&nbsp;NEGLIGENCE&nbsp;OR&nbsp;OTHER&nbsp;TORTIOUS&nbsp;ACTION,&nbsp;ARISING&nbsp;OUT&nbsp;OF<br>
#&nbsp;OR&nbsp;IN&nbsp;CONNECTION&nbsp;WITH&nbsp;THE&nbsp;USE&nbsp;OR&nbsp;PERFORMANCE&nbsp;OF&nbsp;THIS&nbsp;SOFTWARE.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
    
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.container.keybuffer.html#KeyBuffer">KeyBuffer</a>
</font></dt></dl>
</dd>
</dl>
 <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="KeyBuffer">class <strong>KeyBuffer</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
    
<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%">Methods defined here:<br>
<dl><dt><a name="KeyBuffer-__init__"><strong>__init__</strong></a>(self)</dt></dl>

<dl><dt><a name="KeyBuffer-__str__"><strong>__str__</strong></a>(self)</dt><dd><tt>returns&nbsp;a&nbsp;concatenation&nbsp;of&nbsp;all&nbsp;characters</tt></dd></dl>

<dl><dt><a name="KeyBuffer-append"><strong>append</strong></a>(self, key)</dt><dd><tt>Append&nbsp;a&nbsp;key&nbsp;to&nbsp;the&nbsp;keybuffer,&nbsp;or&nbsp;initial&nbsp;numbers&nbsp;to<br>
the&nbsp;number&nbsp;attribute.</tt></dd></dl>

<dl><dt><a name="KeyBuffer-clear"><strong>clear</strong></a>(self)</dt><dd><tt>Clear&nbsp;the&nbsp;keybuffer&nbsp;and&nbsp;restore&nbsp;the&nbsp;initial&nbsp;state</tt></dd></dl>

<dl><dt><a name="KeyBuffer-tuple_with_numbers"><strong>tuple_with_numbers</strong></a>(self)</dt><dd><tt>Get&nbsp;a&nbsp;tuple&nbsp;of&nbsp;ascii&nbsp;codes.</tt></dd></dl>

<dl><dt><a name="KeyBuffer-tuple_without_numbers"><strong>tuple_without_numbers</strong></a>(self)</dt><dd><tt>Get&nbsp;a&nbsp;tuple&nbsp;of&nbsp;ascii&nbsp;codes.<br>
If&nbsp;the&nbsp;keybuffer&nbsp;starts&nbsp;with&nbsp;numbers,&nbsp;those&nbsp;will<br>
be&nbsp;left&nbsp;out.&nbsp;To&nbsp;access&nbsp;them,&nbsp;use&nbsp;keybuffer.number</tt></dd></dl>

<hr>
Data descriptors defined here:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#eeaa77">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
    
<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt><a name="-to_string"><strong>to_string</strong></a>(i)</dt></dl>
</td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
    
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><strong>NINE</strong> = 57<br>
<strong>ZERO</strong> = 48</td></tr></table>
</body></html>
<< end(); } break; } :(before "End Primitive Recipe Implementations") case RETURN_CONTINUATION_UNTIL_MARK: { // I don't know how to think about next-ingredient in combination with // continuations, so seems cleaner to just kill it. Functions have to read // their inputs before ever returning a continuation. Current_routine->calls.front().ingredient_atoms.clear(); Current_routine->calls.front().next_ingredient_to_process = 0; // copy the current call stack until the most recent marked call call_stack::iterator find_base_of_continuation(call_stack&, int); // manual prototype containing '::' call_stack::iterator base = find_base_of_continuation(Current_routine->calls, /*mark tag*/current_instruction().ingredients.at(0).value); if (base == Current_routine->calls.end()) { raise << maybe(current_recipe_name()) << "couldn't find a 'call-with-continuation-mark' to return to with tag " << current_instruction().ingredients.at(0).original_string << '\n' << end(); raise << maybe(current_recipe_name()) << "call stack:\n" << end(); for (call_stack::iterator p = Current_routine->calls.begin(); p != Current_routine->calls.end(); ++p) raise << maybe(current_recipe_name()) << " " << get(Recipe, p->running_recipe).name << '\n' << end(); break; } trace(Callstack_depth+1, "run") << "creating continuation " << Next_delimited_continuation_id << end(); put(Delimited_continuation, Next_delimited_continuation_id, delimited_continuation(Current_routine->calls.begin(), base)); while (Current_routine->calls.begin() != base) { --Callstack_depth; assert(Callstack_depth >= 0); Current_routine->calls.pop_front(); } // return it as the result of the marked call products.resize(1); products.at(0).push_back(Next_delimited_continuation_id); // return any other ingredients passed in copy(/*skip mark tag*/++ingredients.begin(), ingredients.end(), inserter(products, products.end())); ++Next_delimited_continuation_id; break; // continue to process rest of marked call } :(code) call_stack::iterator find_base_of_continuation(call_stack& c, int mark_tag) { for (call_stack::iterator p = c.begin(); p != c.end(); ++p) if (p->continuation_mark_tag == mark_tag) return p; return c.end(); } //: overload 'call' for continuations :(after "Begin Call") if (is_mu_continuation(current_instruction().ingredients.at(0))) { // copy multiple calls on to current call stack assert(scalar(ingredients.at(0))); trace(Callstack_depth+1, "run") << "calling continuation " << ingredients.at(0).at(0) << end(); if (!contains_key(Delimited_continuation, ingredients.at(0).at(0))) raise << maybe(current_recipe_name()) << "no such delimited continuation " << current_instruction().ingredients.at(0).original_string << '\n' << end(); const call_stack& new_frames = get(Delimited_continuation, ingredients.at(0).at(0)).frames; for (call_stack::const_reverse_iterator p = new_frames.rbegin(); p != new_frames.rend(); ++p) Current_routine->calls.push_front(*p); trace(Callstack_depth+1, "trace") << "calling delimited continuation; growing callstack depth to " << Callstack_depth+SIZE(new_frames) << end(); Callstack_depth += SIZE(new_frames); assert(Callstack_depth < Max_depth); // no call housekeeping; continuations don't support next-ingredient copy(/*drop continuation*/++ingredients.begin(), ingredients.end(), inserter(products, products.begin())); break; // record results of resuming 'return-continuation-until-mark' instruction } :(code) void test_continuations_can_return_values() { run( "def main [\n" " local-scope\n" " k:continuation, 1:num/raw <- call-with-continuation-mark 233/mark, f\n" "]\n" "def f [\n" " local-scope\n" " g\n" "]\n" "def g [\n" " local-scope\n" " return-continuation-until-mark 233/mark, 34\n" " stash [continuation called]\n" "]\n" ); CHECK_TRACE_CONTENTS( "mem: storing 34 in location 1\n" ); } void test_continuations_continue_to_matching_mark() { run( "def main [\n" " local-scope\n" " k:continuation, 1:num/raw <- call-with-continuation-mark 233/mark, f\n" " add 1, 1\n" "]\n" "def f [\n" " local-scope\n" " k2:continuation <- call-with-continuation-mark 234/mark, g\n" " add 2, 2\n" "]\n" "def g [\n" " local-scope\n" " return-continuation-until-mark 233/mark, 34\n" " stash [continuation called]\n" "]\n" ); CHECK_TRACE_CONTENTS( "run: add {1: \"literal\"}, {1: \"literal\"}\n" ); CHECK_TRACE_DOESNT_CONTAIN("run: add {2: \"literal\"}, {2: \"literal\"}"); } //: Allow shape-shifting recipes to return continuations. void test_call_shape_shifting_recipe_with_continuation_mark() { run( "def main [\n" " 1:num <- call-with-continuation-mark 233/mark, f, 34\n" "]\n" "def f x:_elem -> y:_elem [\n" " local-scope\n" " load-ingredients\n" " y <- copy x\n" "]\n" ); CHECK_TRACE_CONTENTS( "mem: storing 34 in location 1\n" ); } :(before "End resolve_ambiguous_call(r, index, inst, caller_recipe) Special-cases") if (inst.name == "call-with-continuation-mark") { if (SIZE(inst.ingredients) > 1 && is_recipe_literal(inst.ingredients.at(/*skip mark*/1))) { resolve_indirect_continuation_call(r, index, inst, caller_recipe); return; } } :(code) void resolve_indirect_continuation_call(const recipe_ordinal r, int index, instruction& inst, const recipe& caller_recipe) { instruction inst2; inst2.name = inst.ingredients.at(/*skip mark*/1).name; for (int i = /*skip mark and recipe*/2; i < SIZE(inst.ingredients); ++i) inst2.ingredients.push_back(inst.ingredients.at(i)); for (int i = /*skip continuation*/1; i < SIZE(inst.products); ++i) inst2.products.push_back(inst.products.at(i)); resolve_ambiguous_call(r, index, inst2, caller_recipe); inst.ingredients.at(/*skip mark*/1).name = inst2.name; inst.ingredients.at(/*skip mark*/1).set_value(get(Recipe_ordinal, inst2.name)); } void test_call_shape_shifting_recipe_with_continuation_mark_and_no_outputs() { run( "def main [\n" " 1:continuation <- call-with-continuation-mark 233/mark, f, 34\n" "]\n" "def f x:_elem [\n" " local-scope\n" " load-ingredients\n" " return-continuation-until-mark 233/mark\n" "]\n" ); CHECK_TRACE_COUNT("error", 0); } void test_continuation1() { run( "def main [\n" " local-scope\n" " k:continuation <- call-with-continuation-mark 233/mark, create-yielder\n" " 10:num/raw <- call k\n" "]\n" "def create-yielder -> n:num [\n" " local-scope\n" " load-inputs\n" " return-continuation-until-mark 233/mark\n" " return 1\n" "]\n" ); CHECK_TRACE_CONTENTS( "mem: storing 1 in location 10\n" ); CHECK_TRACE_COUNT("error", 0); } :(code) bool is_mu_continuation(reagent/*copy*/ x) { canonize_type(x); return x.type && x.type->atom && x.type->value == get(Type_ordinal, "continuation"); } // helper for debugging void dump(const int continuation_id) { if (!contains_key(Delimited_continuation, continuation_id)) { raise << "missing delimited continuation: " << continuation_id << '\n' << end(); return; } delimited_continuation& curr = get(Delimited_continuation, continuation_id); dump(curr.frames); }