M => +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))) +
list(filter_none(list_flatten(ilist))))
# 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)
- else:
- 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)
else:
yield el