def __viable_source_types_real (target_type): """ Returns a list of source type which can possibly be converted to 'target_type' by some chain of generator invocation. More formally, takes all generators for 'target_type' and returns union of source types for those generators and result of calling itself recusrively on source types. """ generators = [] # 't0' is the initial list of target types we need to process to get a list # of their viable source target types. New target types will not be added to # this list. t0 = type.all_bases (target_type) # 't' is the list of target types which have not yet been processed to get a # list of their viable source target types. This list will get expanded as # we locate more target types to process. t = t0 result = [] while t: # Find all generators for current type. # Unlike 'find_viable_generators' we don't care about prop_set. generators = __type_to_generators.get (t [0], []) t = t[1:] for g in generators: if not g.source_types(): # Empty source types -- everything can be accepted result = "*" # This will terminate outer loop. t = None break for source_type in g.source_types (): if not source_type in result: # If generator accepts 'source_type' it # will happily accept any type derived from it all = type.all_derived (source_type) for n in all: if not n in result: # Here there is no point in adding target types to # the list of types to process in case they are or # have already been on that list. We optimize this # check by realizing that we only need to avoid the # original target type's base types. Other target # types that are or have been on the list of target # types to process have been added to the 'result' # list as well and have thus already been eliminated # by the previous if. if not n in t0: t.append (n) result.append (n) return result
def find_viable_generators_aux(target_type, prop_set): """ Returns generators which can be used to construct target of specified type with specified properties. Uses the following algorithm: - iterates over requested target_type and all it's bases (in the order returned bt type.all-bases. - for each type find all generators that generate that type and which requirements are satisfied by properties. - if the set of generators is not empty, returns that set. Note: this algorithm explicitly ignores generators for base classes if there's at least one generator for requested target_type. """ # Select generators that can create the required target type. viable_generators = [] initial_generators = [] import type # Try all-type generators first. Assume they have # quite specific requirements. all_bases = type.all_bases(target_type) for t in all_bases: initial_generators = __type_to_generators.get(t, []) if initial_generators: dout("there are generators for this type") if t != target_type: # We're here, when no generators for target-type are found, # but there are some generators for a base type. # We'll try to use them, but they will produce targets of # base type, not of 'target-type'. So, we clone the generators # and modify the list of target types. generators2 = [] for g in initial_generators[:]: # generators.register adds generator to the list of generators # for toolsets, which is a bit strange, but should work. # That list is only used when inheriting toolset, which # should have being done before generators are run. ng = g.clone_and_change_target_type(t, target_type) generators2.append(ng) register(ng) initial_generators = generators2 break for g in initial_generators: dout("trying generator " + g.id() + "(" + str(g.source_types()) + "->" + str(g.target_types()) + ")") m = g.match_rank(prop_set) if m: dout(" is viable") viable_generators.append(g) return viable_generators
def __viable_source_types_real(target_type): """ Returns a list of source type which can possibly be converted to 'target_type' by some chain of generator invocation. More formally, takes all generators for 'target_type' and returns union of source types for those generators and result of calling itself recusrively on source types. """ generators = [] # 't0' is the initial list of target types we need to process to get a list # of their viable source target types. New target types will not be added to # this list. t0 = type.all_bases(target_type) # 't' is the list of target types which have not yet been processed to get a # list of their viable source target types. This list will get expanded as # we locate more target types to process. t = t0 result = [] while t: # Find all generators for current type. # Unlike 'find_viable_generators' we don't care about prop_set. generators = __type_to_generators.get(t[0], []) t = t[1:] for g in generators: if not g.source_types(): # Empty source types -- everything can be accepted result = "*" # This will terminate outer loop. t = None break for source_type in g.source_types(): if not source_type in result: # If generator accepts 'source_type' it # will happily accept any type derived from it all = type.all_derived(source_type) for n in all: if not n in result: # Here there is no point in adding target types to # the list of types to process in case they are or # have already been on that list. We optimize this # check by realizing that we only need to avoid the # original target type's base types. Other target # types that are or have been on the list of target # types to process have been added to the 'result' # list as well and have thus already been eliminated # by the previous if. if not n in t0: t.append(n) result.append(n) return result
def find_viable_generators_aux (target_type, prop_set): """ Returns generators which can be used to construct target of specified type with specified properties. Uses the following algorithm: - iterates over requested target_type and all it's bases (in the order returned bt type.all-bases. - for each type find all generators that generate that type and which requirements are satisfied by properties. - if the set of generators is not empty, returns that set. Note: this algorithm explicitly ignores generators for base classes if there's at least one generator for requested target_type. """ # Select generators that can create the required target type. viable_generators = [] initial_generators = [] import type # Try all-type generators first. Assume they have # quite specific requirements. all_bases = type.all_bases(target_type) for t in all_bases: initial_generators = __type_to_generators.get(t, []) if initial_generators: dout("there are generators for this type") if t != target_type: # We're here, when no generators for target-type are found, # but there are some generators for a base type. # We'll try to use them, but they will produce targets of # base type, not of 'target-type'. So, we clone the generators # and modify the list of target types. generators2 = [] for g in initial_generators[:]: # generators.register adds generator to the list of generators # for toolsets, which is a bit strange, but should work. # That list is only used when inheriting toolset, which # should have being done before generators are run. ng = g.clone_and_change_target_type(t, target_type) generators2.append(ng) register(ng) initial_generators = generators2 break for g in initial_generators: dout("trying generator " + g.id() + "(" + str(g.source_types()) + "->" + str(g.target_types()) + ")") m = g.match_rank(prop_set) if m: dout(" is viable") viable_generators.append(g) return viable_generators
def __viable_source_types_real(target_type): """ Returns a list of source type which can possibly be converted to 'target_type' by some chain of generator invocation. More formally, takes all generators for 'target_type' and returns union of source types for those generators and result of calling itself recusrively on source types. """ generators = [] t = type.all_bases(target_type) result = [] # 't' is the list of types which are not yet processed while t: # Find all generators for current type. # Unlike 'find_viable_generators' we don't care about prop_set. generators = __type_to_generators.get(t[0], []) t = t[1:] for g in generators: if not g.source_types(): # Empty source types -- everything can be accepted result = "*" # This will terminate outer loop. t = None break for source_type in g.source_types(): if not source_type in result: # If generator accepts 'source_type' it # will happily accept any type derived from it all = type.all_derived(source_type) for n in all: if not n in result: t.append(n) result.append(n) result = unique(result) return result
def __viable_source_types_real (target_type): """ Returns a list of source type which can possibly be converted to 'target_type' by some chain of generator invocation. More formally, takes all generators for 'target_type' and returns union of source types for those generators and result of calling itself recusrively on source types. """ generators = [] t = type.all_bases (target_type) result = [] # 't' is the list of types which are not yet processed while t: # Find all generators for current type. # Unlike 'find_viable_generators' we don't care about prop_set. generators = __type_to_generators.get (t [0], []) t = t[1:] for g in generators: if not g.source_types(): # Empty source types -- everything can be accepted result = "*" # This will terminate outer loop. t = None break for source_type in g.source_types (): if not source_type in result: # If generator accepts 'source_type' it # will happily accept any type derived from it all = type.all_derived (source_type) for n in all: if not n in result: t.append (n) result.append (n) result = unique (result) return result