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.
    """
    assert isinstance(target_type, basestring)
    assert isinstance(prop_set, property_set.PropertySet)
    # Select generators that can create the required target type.
    viable_generators = []
    initial_generators = []

    from . 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
Example #2
0
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.
    """
    assert isinstance(target_type, basestring)
    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
Example #3
0
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.
    """
    assert isinstance(target_type, basestring)
    assert isinstance(prop_set, property_set.PropertySet)
    # Select generators that can create the required target type.
    viable_generators = []
    initial_generators = []

    from . 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
Example #4
0
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.
    """
    assert isinstance(target_type, basestring)
    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