<s> from pycket import config <EOL> from pycket import values , values_string <EOL> from pycket . base import SingletonMeta , UnhashableType <EOL> from pycket . hash . base import W_HashTable , get_dict_item , w_missing <EOL> from pycket . error import SchemeException <EOL> from pycket . cont import continuation , loop_label <EOL> from rpython . rlib import rerased <EOL> from rpython . rlib . objectmodel import compute_hash , import_from_mixin , r_dict , specialize <EOL> @ loop_label <EOL> def equal_hash_ref_loop ( data , idx , key , env , cont ) : <EOL> from pycket . interpreter import return_value <EOL> from pycket . prims . equal import equal_func , EqualInfo <EOL> if idx >= len ( data ) : <EOL> return return_value ( w_missing , env , cont ) <EOL> k , v = data [ idx ] <EOL> info = EqualInfo . BASIC_SINGLETON <EOL> return equal_func ( k , key , info , env , <EOL> catch_ref_is_equal_cont ( data , idx , key , v , env , cont ) ) <EOL> @ continuation <EOL> def catch_ref_is_equal_cont ( data , idx , key , v , env , cont , _vals ) : <EOL> from pycket . interpreter import check_one_val , return_value <EOL> val = check_one_val ( _vals ) <EOL> if val is not values . w_false : <EOL> return return_value ( v , env , cont ) <EOL> return equal_hash_ref_loop ( data , idx + <NUM_LIT:1> , key , env , cont ) <EOL> def equal_hash_set_loop ( data , idx , key , val , env , cont ) : <EOL> from pycket . interpreter import check_one_val , return_value <EOL> from pycket . prims . equal import equal_func , EqualInfo <EOL> if idx >= len ( data ) : <EOL> data . append ( ( key , val ) ) <EOL> return return_value ( values . w_void , env , cont ) <EOL> k , _ = data [ idx ] <EOL> info = EqualInfo . BASIC_SINGLETON <EOL> return equal_func ( k , key , info , env , <EOL> catch_set_is_equal_cont ( data , idx , key , val , env , cont ) ) <EOL> @ continuation <EOL> def catch_set_is_equal_cont ( data , idx , key , val , env , cont , _vals ) : <EOL> from pycket . interpreter import check_one_val , return_value <EOL> cmp = check_one_val ( _vals ) <EOL> if cmp is not values . w_false : <EOL> data [ idx ] = ( key , val ) <EOL> return return_value ( values . w_void , env , cont ) <EOL> return equal_hash_set_loop ( data , idx + <NUM_LIT:1> , key , val , env , cont ) <EOL> class HashmapStrategy ( object ) : <EOL> __metaclass__ = SingletonMeta <EOL> def get ( self , w_dict , w_key , env , cont ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def set ( self , w_dict , w_key , w_val , env , cont ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def items ( self , w_dict ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def get_item ( self , w_dict , i ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def length ( self , w_dict ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def create_storage ( self , keys , vals ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> def _find_strategy_class ( keys ) : <EOL> if not config . strategies : <EOL> return ObjectHashmapStrategy . singleton <EOL> if len ( keys ) == <NUM_LIT:0> : <EOL> return EmptyHashmapStrategy . singleton <EOL> single_class = type ( keys [ <NUM_LIT:0> ] ) <EOL> for elem in keys : <EOL> if not isinstance ( elem , single_class ) : <EOL> return ObjectHashmapStrategy . singleton <EOL> if single_class is values . W_Fixnum : <EOL> return FixnumHashmapStrategy . singleton <EOL> if single_class is values . W_Symbol : <EOL> return SymbolHashmapStrategy . singleton <EOL> if single_class is values_string . W_String : <EOL> return StringHashmapStrategy . singleton <EOL> if single_class is values . W_Bytes : <EOL> return ByteHashmapStrategy . singleton <EOL> return ObjectHashmapStrategy . singleton <EOL> class UnwrappedHashmapStrategyMixin ( object ) : <EOL> def get ( self , w_dict , w_key , env , cont ) : <EOL> from pycket . interpreter import return_value <EOL> if self . is_correct_type ( w_key ) : <EOL> w_res = self . unerase ( w_dict . hstorage ) . get ( self . unwrap ( w_key ) , w_missing ) <EOL> return return_value ( w_res , env , cont ) <EOL> self . switch_to_object_strategy ( w_dict ) <EOL> return w_dict . hash_ref ( w_key , env , cont ) <EOL> def set ( self , w_dict , w_key , w_val , env , cont ) : <EOL> from pycket . interpreter import return_value <EOL> if self . is_correct_type ( w_key ) : <EOL> self . unerase ( w_dict . hstorage ) [ self . unwrap ( w_key ) ] = w_val <EOL> return return_value ( values . w_void , env , cont ) <EOL> self . switch_to_object_strategy ( w_dict ) <EOL> return w_dict . hash_set ( w_key , w_val , env , cont ) <EOL> def items ( self , w_dict ) : <EOL> return [ ( self . wrap ( key ) , w_val ) for key , w_val in self . unerase ( w_dict . hstorage ) . iteritems ( ) ] <EOL> def get_item ( self , w_dict , i ) : <EOL> key , w_val = get_dict_item ( self . unerase ( w_dict . hstorage ) , i ) <EOL> return self . wrap ( key ) , w_val <EOL> def length ( self , w_dict ) : <EOL> return len ( self . unerase ( w_dict . hstorage ) ) <EOL> def create_storage ( self , keys , vals ) : <EOL> d = self . _create_empty_dict ( ) <EOL> if not keys : <EOL> return self . erase ( d ) <EOL> for i , w_key in enumerate ( keys ) : <EOL> d [ self . unwrap ( w_key ) ] = vals [ i ] <EOL> return self . erase ( d ) <EOL> def _create_empty_dict ( self ) : <EOL> return { } <EOL> def switch_to_object_strategy ( self , w_dict ) : <EOL> d = self . unerase ( w_dict . hstorage ) <EOL> keys = [ self . wrap ( key ) for key in d . keys ( ) ] <EOL> values = d . values ( ) <EOL> strategy = ObjectHashmapStrategy . singleton <EOL> storage = strategy . create_storage ( keys , values ) <EOL> w_dict . strategy = strategy <EOL> w_dict . hstorage = storage <EOL> class EmptyHashmapStrategy ( HashmapStrategy ) : <EOL> erase , unerase = rerased . new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def get ( self , w_dict , w_key , env , cont ) : <EOL> from pycket . interpreter import return_value <EOL> return return_value ( w_missing , env , cont ) <EOL> def set ( self , w_dict , w_key , w_val , env , cont ) : <EOL> self . switch_to_correct_strategy ( w_dict , w_key ) <EOL> return w_dict . hash_set ( w_key , w_val , env , cont ) <EOL> def items ( self , w_dict ) : <EOL> return [ ] <EOL> def get_item ( self , w_dict , i ) : <EOL> raise IndexError <EOL> def length ( self , w_dict ) : <EOL> return <NUM_LIT:0> <EOL> def create_storage ( self , keys , vals ) : <EOL> assert not keys <EOL> assert not vals <EOL> return self . erase ( None ) <EOL> def switch_to_correct_strategy ( self , w_dict , w_key ) : <EOL> if type ( w_key ) is values . W_Fixnum : <EOL> strategy = FixnumHashmapStrategy . singleton <EOL> elif type ( w_key ) is values . W_Symbol : <EOL> strategy = SymbolHashmapStrategy . singleton <EOL> elif isinstance ( w_key , values_string . W_String ) : <EOL> strategy = StringHashmapStrategy . singleton <EOL> elif isinstance ( w_key , values . W_Bytes ) : <EOL> strategy = ByteHashmapStrategy . singleton <EOL> else : <EOL> strategy = ObjectHashmapStrategy . singleton <EOL> storage = strategy . create_storage ( [ ] , [ ] ) <EOL> w_dict . strategy = strategy <EOL> w_dict . hstorage = storage <EOL> class Bucket ( object ) : <EOL> _attrs_ = _immutable_fields_ = [ "<STR_LIT>" ] <EOL> def __init__ ( self ) : <EOL> self . entries = [ ] <EOL> def add_entry ( self , key , val ) : <EOL> self . entries . append ( ( key , val ) ) <EOL> def size ( self ) : <EOL> return len ( self . entries ) <EOL> UNHASHABLE_TAG = <NUM_LIT> <EOL> def tagged_hash ( w_object ) : <EOL> try : <EOL> return w_object . hash_equal ( ) << <NUM_LIT:1> <EOL> except UnhashableType : <EOL> return UNHASHABLE_TAG <EOL> class ObjectHashmapStrategy ( HashmapStrategy ) : <EOL> erase , unerase = rerased . new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def get_bucket ( self , w_dict , w_key , nonull = False ) : <EOL> hash = tagged_hash ( w_key ) <EOL> storage = self . unerase ( w_dict . hstorage ) <EOL> bucket = storage . get ( hash , None ) <EOL> if nonull and bucket is None : <EOL> storage [ hash ] = bucket = Bucket ( ) <EOL> return bucket <EOL> def get ( self , w_dict , w_key , env , cont ) : <EOL> from pycket . interpreter import return_value <EOL> bucket = self . get_bucket ( w_dict , w_key ) <EOL> if bucket is None : <EOL> return return_value ( w_missing , env , cont ) <EOL> entries = bucket . entries <EOL> return equal_hash_ref_loop ( entries , <NUM_LIT:0> , w_key , env , cont ) <EOL> def set ( self , w_dict , w_key , w_val , env , cont ) : <EOL> bucket = self . get_bucket ( w_dict , w_key , nonull = True ) <EOL> return equal_hash_set_loop ( bucket . entries , <NUM_LIT:0> , w_key , w_val , env , cont ) <EOL> def items ( self , w_dict ) : <EOL> items = [ ] <EOL> storage = self . unerase ( w_dict . hstorage ) <EOL> for bucket in storage . itervalues ( ) : <EOL> for item in bucket . entries : <EOL> items . append ( item ) <EOL> return items <EOL> def get_item ( self , w_dict , i ) : <EOL> storage = self . unerase ( w_dict . hstorage ) <EOL> for bucket in storage . itervalues ( ) : <EOL> size = bucket . size ( ) <EOL> if size > i : <EOL> return bucket . entries [ i ] <EOL> i -= size <EOL> raise IndexError <EOL> def length ( self , w_dict ) : <EOL> storage = self . unerase ( w_dict . hstorage ) <EOL> size = <NUM_LIT:0> <EOL> for bucket in storage . itervalues ( ) : <EOL> size += bucket . size ( ) <EOL> return size <EOL> def create_storage ( self , keys , vals ) : <EOL> storage = { } <EOL> for i , key in enumerate ( keys ) : <EOL> val = vals [ i ] <EOL> hash = tagged_hash ( key ) <EOL> bucket = storage . get ( hash , None ) <EOL> if bucket is None : <EOL> storage [ hash ] = bucket = Bucket ( ) <EOL> bucket . add_entry ( key , val ) <EOL> return self . erase ( storage ) <EOL> class FixnumHashmapStrategy ( HashmapStrategy ) : <EOL> import_from_mixin ( UnwrappedHashmapStrategyMixin ) <EOL> erase , unerase = rerased . new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def is_correct_type ( self , w_obj ) : <EOL> return isinstance ( w_obj , values . W_Fixnum ) <EOL> def wrap ( self , val ) : <EOL> assert isinstance ( val , int ) <EOL> return values . W_Fixnum ( val ) <EOL> def unwrap ( self , w_val ) : <EOL> assert isinstance ( w_val , values . W_Fixnum ) <EOL> return w_val . value <EOL> class SymbolHashmapStrategy ( HashmapStrategy ) : <EOL> import_from_mixin ( UnwrappedHashmapStrategyMixin ) <EOL> erase , unerase = rerased . new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def is_correct_type ( self , w_obj ) : <EOL> return isinstance ( w_obj , values . W_Symbol ) <EOL> def wrap ( self , val ) : <EOL> assert isinstance ( val , values . W_Symbol ) <EOL> return val <EOL> def unwrap ( self , w_val ) : <EOL> assert isinstance ( w_val , values . W_Symbol ) <EOL> return w_val <EOL> def hash_strings ( w_b ) : <EOL> assert isinstance ( w_b , values_string . W_String ) <EOL> return w_b . hash_equal ( ) <EOL> def cmp_strings ( w_a , w_b ) : <EOL> assert isinstance ( w_a , values_string . W_String ) <EOL> assert isinstance ( w_b , values_string . W_String ) <EOL> return w_a . equal ( w_b ) <EOL> class StringHashmapStrategy ( HashmapStrategy ) : <EOL> import_from_mixin ( UnwrappedHashmapStrategyMixin ) <EOL> erase , unerase = rerased . new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def is_correct_type ( self , w_obj ) : <EOL> return isinstance ( w_obj , values_string . W_String ) <EOL> def wrap ( self , w_val ) : <EOL> return w_val <EOL> def unwrap ( self , w_val ) : <EOL> return w_val <EOL> def _create_empty_dict ( self ) : <EOL> return r_dict ( cmp_strings , hash_strings ) <EOL> def hash_bytes ( w_b ) : <EOL> assert isinstance ( w_b , values . W_Bytes ) <EOL> return w_b . hash_equal ( ) <EOL> def cmp_bytes ( w_a , w_b ) : <EOL> assert isinstance ( w_a , values . W_Bytes ) <EOL> assert isinstance ( w_b , values . W_Bytes ) <EOL> return w_a . value == w_b . value <EOL> class ByteHashmapStrategy ( HashmapStrategy ) : <EOL> import_from_mixin ( UnwrappedHashmapStrategyMixin ) <EOL> erase , unerase = rerased . new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def is_correct_type ( self , w_obj ) : <EOL> return isinstance ( w_obj , values . W_Bytes ) <EOL> def wrap ( self , val ) : <EOL> return val <EOL> def unwrap ( self , w_val ) : <EOL> assert isinstance ( w_val , values . W_Bytes ) <EOL> return w_val <EOL> def _create_empty_dict ( self ) : <EOL> return r_dict ( cmp_bytes , hash_bytes ) <EOL> class W_EqualHashTable ( W_HashTable ) : <EOL> _attrs_ = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> _immutable_fields_ = [ '<STR_LIT>' ] <EOL> def __init__ ( self , keys , vals , immutable = False ) : <EOL> self . is_immutable = immutable <EOL> self . strategy = _find_strategy_class ( keys ) <EOL> self . hstorage = self . strategy . create_storage ( keys , vals ) <EOL> def immutable ( self ) : <EOL> return self . is_immutable <EOL> def hash_items ( self ) : <EOL> return self . strategy . items ( self ) <EOL> def hash_set ( self , key , val , env , cont ) : <EOL> return self . strategy . set ( self , key , val , env , cont ) <EOL> def hash_ref ( self , key , env , cont ) : <EOL> return self . strategy . get ( self , key , env , cont ) <EOL> def get_item ( self , i ) : <EOL> return self . strategy . get_item ( self , i ) <EOL> def length ( self ) : <EOL> return self . strategy . length ( self ) <EOL> def make_empty ( self ) : <EOL> return W_EqualHashTable ( [ ] , [ ] , immutable = self . is_immutable ) <EOL> def tostring ( self ) : <EOL> lst = [ values . W_Cons . make ( k , v ) . tostring ( ) for k , v in self . hash_items ( ) ] <EOL> return "<STR_LIT>" % "<STR_LIT:U+0020>" . join ( lst ) </s>
