73a3985bc98c8a533c0fa89eb5165f0c69bce13c — Jasper den Ouden 1 year, 6 months ago 0eb905b
More use of `type_stack_calc.util.various`, added start of selecting specific parts of types to be used in wideners.(itll take a while to actually do wideners.
M type_stack_calc/extractor.py => type_stack_calc/extractor.py +6 -16
@@ 9,12 9,12 @@ from type_stack_calc.pe.tmpvar import TmpVar

class StopMarker: pass

def _ignore(x): pass

def getattr_or_parent(obj, key):
    return getattr(getattr(obj, 'parent', None), key, None) \
        or getattr(obj, key, None)

from type_stack_calc.util.various import list_flatten, filter_none, ignore

class Extractor(tuple):
    """Extracts things in arguments of functions to the body the function is called from.

@@ 46,7 46,7 @@ Derives from tuple; first is a function that puts it inside the function, and th
    def sub_return_irrelevant(self):
        """Ignores the non-extracted, as the return value does not matter.
The extracted may be needed because it's destructive etc."""
        return Extractor((_ignore, self[1]))
        return Extractor((ignore, self[1]))

    def extract(self, gen):
        for el in gen:

@@ 63,14 63,6 @@ class ExtractorWVar(Extractor):
    def tmp_var(self, name, tp):
        return self[2]

def _flatten_into_cb(got, into_cb):
    """Enters entries into the callback.
Flattening part: if list, it will do the elements one by one."""
    if type(got) == list:  # Recurse. (exact, some derive from lists)
        for el in got: _flatten_into_cb(el, into_cb)
    elif got is not None:
        into_cb(got)  # Use the callback.

def figure_destructive(val, been=None):
    """Figures out if a value is destructive. Memoizes."""
    cur = getattr(val, 'destructive', None)  # See if it says so.

@@ 104,11 96,9 @@ def extract(gen):
        # Extract, NOTE: also moves generator forward.
        ext._extract_1(gen, obj, 'extract_top')

        ret = []
        for el in extlist:  # The externalized bit goes first.
            _flatten_into_cb(el, ret.append)  # Also flatten so underlying code doesn't have to.
        for el in ilist:  # Non-externalized portion next.
            _flatten_into_cb(el, ret.append)
        # Externalized first, then argument partion.
        ret = (list(filter_none(list_flatten(extlist))) +
        # Drop:
        # * If any definitional parts => assumed comes back as variants.
        # * If entirely `is_const`, which does not do anything.

M type_stack_calc/sets/intersection.py => type_stack_calc/sets/intersection.py +1 -6
@@ 43,12 43,7 @@ def merge_1(into, add, meth_name):
            yield from gen
    yield add  # And finally the potentially merged remains.

def list_flatten(gen):
    for el in gen:
        if type(el) == list:
            yield from list_flatten(el)
            yield el
from type_stack_calc.util.various import list_flatten

def merge(gen, meth_name):
    """Merges the sets and simplifies."""

M type_stack_calc/tp/intersection.py => type_stack_calc/tp/intersection.py +13 -6
@@ 55,17 55,13 @@ class TpIntersection(_BaseTpIntersection):

    def get_comp(self, name):
        """Inside it uses components instead of params, and don't want them double-wrapped.
NOTE/TODO: it's a little off the `param` stuff should really be about values, not components."""
NOTE/TODO: it's a little off, the `param` stuff should really be about values, not components."""
        val = self.get_param(name)
        if notify := getattr(val, 'notify_name', None): notify(name)
        return (val if isinstance(val, (PlainComponent, BaseComponent))
                else PlainComponent(name, val))

def first_or_none(gen, alt=None):
    gen = (el for el in gen if el is not None)
    ret = next(gen, alt)
    assert next(gen, None) is None
    return ret
from type_stack_calc.util.various import first_or_none

class TypeTpIntersection(_BaseTpIntersection):

@@ 106,3 102,14 @@ class TypeTpIntersection(_BaseTpIntersection):
        """Gets the type param if _only one_ of the intersection provides it."""
        return first_or_none(getattr(type(el), f"tp_param_{name}", None)
                             for el in self)

    def param_extract(self): return TypeExtractor(self)

from type_stack_calc.tp.stepping import TpStepping
from type_stack_calc.tp.float import TpFloat
from type_stack_calc.tp.bool import the_none

class TypeExtractor(_BaseTpIntersection):
    """Get individual types from the intersection."""
    def get_param_final(self, name):
        return next((tp for tp in self if tp.name == 'name'), the_none)

M type_stack_calc/util/various.py => type_stack_calc/util/various.py +8 -2
@@ 1,15 1,21 @@

def ignore(_x): pass

def first_or_none(gen, alt=None):
    """Get the first not-`None` value or get `alt` if none available."""
    gen = (el for el in gen if el is not None)
    ret = next(gen, alt)
    assert next(gen, None) is None
    return ret

def filter_none(lst): return (el for el in lst if el is not None)
def filter_none(lst):
    """Filter all the `None` values."""
    return (el for el in lst if el is not None)

def list_flatten(gen):
    """If an item in `gen` is a list yield it flatly, and continue so recursively."""
    for el in gen:
        if type(el) == list:
            for r_el in list_flatten(el): yield r_el
            yield from list_flatten(el)
            yield el