def add_all_data_to_delta_list( self,delta_to_add_to,current_internal_val,action_event,for_map): ''' Run through entire list. Create an add action for each element. @param {bool} for_map --- True if performing operations for map. false if performing for list. ''' if for_map: to_iter_over = current_internal_val.keys() else: to_iter_over = range(0,len(current_internal_val)) for key in to_iter_over: if for_map: action = delta_to_add_to.map_actions.add() else: action = delta_to_add_to.list_actions.add() action.container_action = VarStoreDeltas.ContainerAction.ADD_KEY add_action = action.added_key add_action.parent_type = VarStoreDeltas.CONTAINER_ADDED if isinstance(key,numbers.Number): add_action.added_key_num = key elif util.is_string(key): add_action.added_key_text = key else: add_action.added_key_tf = key # now actually add the value to the map list_val = current_internal_val[key] if isinstance(list_val,numbers.Number): add_action.added_what_num = list_val elif util.is_string(list_val): add_action.added_what_text = list_val elif isinstance(list_val,bool): add_action.added_what_tf = list_val elif isinstance(list_val,WaldoLockedObj): list_val.serializable_var_tuple_for_network( add_action,'',action_event,True) #### DEBUG else: util.logger_assert( 'Unkonw type to serialize')
def ensure_locked_obj(new_val,host_uuid,single_threaded): ''' @param {Anything} new_val --- If new_val is a non-Waldo object, convert it to a Waldo object. Otherwise, return it unchanged. This method is used to ensure that each individual entry in a map/list is also protected. @param {bool} single_threaded --- True if the variable should be single threaded. ''' # FIXME: Need to include function object check in ensure locked # obj if isinstance(new_val, WaldoLockedObj): return new_val if single_threaded: if isinstance(new_val, bool): return SingleThreadedLockedTrueFalseVariable(host_uuid,False,new_val) elif isinstance(new_val, numbers.Number): return SingleThreadedLockedNumberVariable(host_uuid,False,new_val) elif util.is_string(new_val): return SingleThreadedLockedTextVariable(host_uuid,False,new_val) elif isinstance(new_val,list): return SingleThreadedLockedListVariable(host_uuid,False,new_val) elif isinstance(new_val,dict): return SingleThreadedLockedMapVariable(host_uuid,False,new_val) elif isinstance(new_val,EndpointBase): return SingleThreadedLockedEndpointVariable(host_uuid,False,new_val) else: util.logger_assert('Unknown object type.') else: if isinstance(new_val, bool): return LockedTrueFalseVariable(host_uuid,False,new_val) elif isinstance(new_val, numbers.Number): return LockedNumberVariable(host_uuid,False,new_val) elif util.is_string(new_val): return LockedTextVariable(host_uuid,False,new_val) elif isinstance(new_val,list): return LockedListVariable(host_uuid,False,new_val) elif isinstance(new_val,dict): return LockedMapVariable(host_uuid,False,new_val) elif isinstance(new_val,EndpointBase): return LockedEndpointVariable(host_uuid,False,new_val) else: util.logger_assert('Unknown object type.')
def handle_in_check(self,lhs,rhs,active_event): ''' Call has form: lhs in rhs rhs can have three basic types: it can be a list, a map, or a string. That means that it can either be a WaldoMapVariable, a WaldoListVariable, a WaldoStringVariable, or a Python string. Instead of using static type inference at compile time to determine, for sake of development, just doing dynamic check to determine which type it is and do the in processing here. FIXME: it is faster to do the static checks with type inference, etc. at compile time rather than at run time. ''' lhs_val = self.get_val_if_waldo(lhs,active_event) # handles Python string case if util.is_string(rhs): return lhs_val in rhs elif is_non_ext_text_var(rhs): return lhs_val in rhs.get_val(active_event) elif is_non_ext_map_var(rhs): return rhs.get_val(active_event).contains_key_called(active_event,lhs_val) elif is_non_ext_list_var(rhs): return rhs.get_val(active_event).contains_val_called(active_event,lhs_val) util.logger_assert( 'Error when calling in: unknown right hand side of expression')
def __init__(self,host_uuid,peered=False,init_val=None): if init_val is None: init_val = '' if util.is_string(init_val): init_val = LockedTextVariable(host_uuid,False,init_val) # FIXME: Have no single threaded external variables. self.SINGLE_THREADED_CONSTRUCTOR = LockedTextVariable self.MULTI_THREADED_CONSTRUCTOR = LockedTextVariable super(WaldoExternalTextVariable,self).__init__(host_uuid,False,init_val)
def get_for_iter(self,to_iter_over,active_event): ''' When call for loop on Waldo variables, need to get item to iterate over ''' if (isinstance(to_iter_over,dict) or isinstance(to_iter_over,list) or util.is_string(to_iter_over)): return iter(to_iter_over) if is_non_ext_text_var(to_iter_over): return iter(to_iter_over.get_val(active_event)) if is_non_ext_map_var(to_iter_over): return iter(to_iter_over.get_val(active_event).get_keys(active_event)) if is_non_ext_list_var(to_iter_over): # FIXME: This is an inefficient way of reading all values # over list. to_return = [] internal_val = to_iter_over.get_val(active_event) for i in range(0, internal_val.get_len(active_event)): to_append = internal_val.get_val_on_key(active_event,i) # The reason that we do this here is that in a for # loop, the operation we perform in the compiled code # immediately following the actual for header is # assign to another Waldo variable the variable being # held by to_append. (We do this through a set_val # call. set_val must take in InternalMaps or # InternalLists. Therefore, get_val on the # WaldoList/WaldoMap first. Note this is unnecessary # for all other for iterations because none of the # others possibly return a WaldoObject to iterate over. if (is_non_ext_list_var(to_append) or is_non_ext_map_var(to_append)): to_append = to_append.get_val(active_event) to_return.append(to_append) return iter(to_return) util.logger_assert( 'Calling get_for_iter on an object that does not support iteration')
def handle_len(self,what_calling_len_on, active_event): ''' Can support python lists, dicts, strings, or waldo lists, waldo maps, waldo texts. @returns {int} ''' if (isinstance(what_calling_len_on, dict) or isinstance(what_calling_len_on, list) or util.is_string(what_calling_len_on)): return len(what_calling_len_on) if is_non_ext_text_var(what_calling_len_on): return len(what_calling_len_on.get_val(active_event)) if (is_non_ext_list_var(what_calling_len_on) or is_non_ext_map_var(what_calling_len_on)): return what_calling_len_on.get_val(active_event).get_len(active_event) util.logger_assert( 'Calling len on an object that does not support the function')
def turn_into_waldo_var( self,val,force_copy,active_event, host_uuid,new_peered, new_multi_threaded): ''' @param {Anything} val @param {bool} force_copy @param {_ActiveEvent object} active_event @param {uuid} host_uuid @param {bool} new_peered --- True if in the case that we have to copy a value, the copy should be peered. Used for loading arguments into sequence local data when message send is called. @see convert_for_seq_local. @returns {WaldoVariable} Used when copying arguments in to function. Compiler's caller can pass in Python literals or WaldoReference objects when it emits a function call. However, the emitted function definition requires all arguments to be WaldoVariables. Therefore, at the beginning of each emitted function, copy all arguments in to WaldoVariables if they are not already. If val is not a WaldoReference, then based on its type, assign it as the initial value of a Waldo Variable and return. If val is a WaldoReference, then check force_copy. force_copy represents whether or not we want to make a copy of the WaldoReference object. (It would be True for instance if we were passed in a WaldoNumber because numbers are passed by value; it would be false if the arg was external or if we were passed in a reference type.) If it is false, then just return val. Otherwise, make copy. ''' # FIXME: Start using some of the single threaded constructors # as well. if isinstance(val,WaldoLockedObj): if force_copy: # means that it was a WaldoVariable: just call its copy # method return val.copy(active_event,new_peered,new_multi_threaded) # otherwise, just return val return val # means that val was not a reference object.... turn it into one. constructor = None if new_multi_threaded: if util.is_string(val): # not using isinstance here because python 3 and python # 2.7 have different ways of testing for string. constructor = LockedTextVariable elif isinstance(val,numbers.Number): constructor = LockedNumberVariable elif isinstance(val,bool): constructor = LockedTrueFalseVariable elif isinstance(val,dict): constructor = LockedMapVariable elif isinstance(val,list): constructor = LockedListVariable elif isinstance(val,EndpointBase): constructor = LockedEndpointVariable #### DEBUG elif hasattr(val,'__call__'): # checks if is function util.logger_assert( 'Should use special call func_turn_into_waldo_var for function objects') else: util.logger_assert( 'Unknown object type to call turn_into_waldo_var on') #### END DEBUG else: if util.is_string(val): # not using isinstance here because python 3 and python # 2.7 have different ways of testing for string. constructor = SingleThreadedLockedTextVariable elif isinstance(val,numbers.Number): constructor = SingleThreadedLockedNumberVariable elif isinstance(val,bool): constructor = SingleThreadedLockedTrueFalseVariable elif isinstance(val,dict): constructor = SingleThreadedLockedMapVariable elif isinstance(val,list): constructor = SingleThreadedLockedListVariable elif isinstance(val,EndpointBase): constructor = SingleThreadedLockedEndpointVariable #### DEBUG elif hasattr(val,'__call__'): # checks if is function util.logger_assert( 'Should use special call func_turn_into_waldo_var for function objects') else: util.logger_assert( 'Unknown object type to call turn_into_waldo_var on') #### END DEBUG return constructor( host_uuid, new_peered, # not peered val # used as initial value )
def add_to_delta_list( self,delta_to_add_to,current_internal_val,action_event, for_map): ''' @param {varStoreDeltas.SingleListDelta} delta_to_add_to --- @param {list} current_internal_val --- The internal val of the action event. @param {_InvalidationListener} action_event @param {bool} for_map --- True if performing operations for map. false if performing for list. @returns {bool} --- Returns true if have any changes to add false otherwise. ''' modified_indices = {} changes_made = False # FIXME: only need to keep track of change log for peered # variables. May be expensive to otherwise. for partner_change in self.partner_change_log: changes_made = True # FIXME: no need to transmit overwrites. but am doing # that currently. if for_map: action = delta_to_add_to.map_actions.add() else: action = delta_to_add_to.list_actions.add() if is_delete_key_tuple(partner_change): action.container_action = VarStoreDeltas.ContainerAction.DELETE_KEY delete_action = action.deleted_key key = partner_change[1] modified_indices[key] = True if isinstance(key,numbers.Number): delete_action.deleted_key_num = key elif util.is_string(key): delete_action.deleted_key_text = key elif isinstance(key,bool): delete_action.deleted_key_tf = key #### DEBUG else: util.logger_assert('Unknown map key type when serializing') #### END DEBUG elif is_add_key_tuple(partner_change): key = partner_change[1] modified_indices[key] = True key_in_internal = key < len(current_internal_val) if for_map: key_in_internal = (key in current_internal_val) if key_in_internal: # note, key may not be in internal val, for # instance if we had deleted it after adding. # in this case, can ignore the add here. action.container_action = VarStoreDeltas.ContainerAction.ADD_KEY add_action = action.added_key add_action.parent_type = VarStoreDeltas.CONTAINER_ADDED if isinstance(key,numbers.Number): add_action.added_key_num = key elif util.is_string(key): add_action.added_key_text = key elif isinstance(key,bool): add_action.added_key_tf = key #### DEBUG else: util.logger_assert('Unknown map key type when serializing') #### END DEBUG # now actually add the value to the map list_val = current_internal_val[key] if isinstance(list_val,numbers.Number): add_action.added_what_num = list_val elif util.is_string(list_val): add_action.added_what_text = list_val elif isinstance(list_val,bool): add_action.added_what_tf = list_val elif isinstance(list_val,WaldoLockedObj): list_val.serializable_var_tuple_for_network( add_action,'',action_event, # true here because if anything is written # or added, then we must force the entire # copy of it. True) #### DEBUG else: util.logger_assert( 'Unkonw type to serialize') #### END DEBUG elif is_write_key_tuple(partner_change): key = partner_change[1] modified_indices[key] = True key_in_internal = key < len(current_internal_val) if for_map: key_in_internal = (key in current_internal_val) if key_in_internal: action.container_action = VarStoreDeltas.ContainerAction.WRITE_VALUE write_action = action.write_key write_action.parent_type = VarStoreDeltas.CONTAINER_WRITTEN if isinstance(key,numbers.Number): write_action.write_key_num = key elif util.is_string(key): write_action.write_key_text = key elif isinstance(key,bool): write_action.write_key_tf = key #### DEBUG else: util.logger_assert('Unknown map key type when serializing') #### END DEBUG list_val = current_internal_val[key] if isinstance(list_val,numbers.Number): write_action.what_written_num = list_val elif util.is_string(list_val): write_action.what_written_text = list_val elif isinstance(list_val,bool): write_action.what_written_tf = list_val else: list_val.serializable_var_tuple_for_network( write_action,'',action_event, # true here because if anything is written # or added, then we must force the entire # copy of it. True) #### DEBUG else: util.logger_assert('Unknown container operation') #### END DEBUG if for_map: to_iter_over = current_internal_val.keys() else: to_iter_over = range(0,len(current_internal_val)) for index in to_iter_over: list_val = current_internal_val[index] if not isinstance(list_val,WaldoLockedObj): break if index not in modified_indices: # create action sub_element_action = delta_to_add_to.sub_element_update_actions.add() sub_element_action.parent_type = VarStoreDeltas.SUB_ELEMENT_ACTION if isinstance(index,numbers.Number): sub_element_action.key_num = index elif util.is_string(index): sub_element_action.key_text = index else: sub_element_action.key_tf = index if list_val.serializable_var_tuple_for_network(sub_element_action,'',action_event,False): changes_made = True else: # no change made to subtree: go ahead and delete added subaction del delta_to_add_to.sub_element_update_actions[-1] # clean out change log: do not need to re-send updates for # these changes to partner, so can just reset after sending # once. self.partner_change_log = [] return changes_made
def value_variable_py_val_serialize(value_variable,parent,var_data,var_name): ''' @param {} parent --- Either a ContainerAction a VarStoreDeltas. FIXME: unclear if actually need var_name for all elements py_serialize-ing, or just py variables that are in the top-level. @returns {bool} --- True if var_data was a python value type and we put it into parent. False otherwise. If is python value type, then adds a delta message to parent. Otherwise, does nothing. ''' is_value_type = False delta = None if isinstance(var_data, numbers.Number): # can only add a pure number to var store a holder or to # an added key if parent.parent_type == VarStoreDeltas.VAR_STORE_DELTA: delta = parent.num_deltas.add() elif parent.parent_type == VarStoreDeltas.CONTAINER_ADDED: parent.added_what_num = var_data elif parent.parent_type == VarStoreDeltas.CONTAINER_WRITTEN: parent.what_written_num = var_data #### DEBUG else: util.logger_assert('Unexpected parent type in py_serialize') #### END DEBUG is_value_type = True elif util.is_string(var_data): if parent.parent_type == VarStoreDeltas.VAR_STORE_DELTA: delta = parent.text_deltas.add() elif parent.parent_type == VarStoreDeltas.CONTAINER_ADDED: parent.added_what_text = var_data elif parent.parent_type == VarStoreDeltas.CONTAINER_WRITTEN: parent.what_written_text = var_data #### DEBUG else: util.logger_assert('Unexpected parent type in py_serialize') #### END DEBUG is_value_type = True elif isinstance(var_data,bool): if parent.parent_type == VarStoreDeltas.VAR_STORE_DELTA: delta = parent.true_false_deltas.add() elif parent.parent_type == VarStoreDeltas.CONTAINER_ADDED: parent.added_what_tf = var_data elif parent.parent_type == VarStoreDeltas.CONTAINER_WRITTEN: parent.what_written_tf = var_data #### DEBUG else: util.logger_assert('Unexpected parent type in py_serialize') #### END DEBUG is_value_type = True if delta != None: # all value types have same format delta.var_name = var_name delta.var_data = var_data return is_value_type