@@ 7,32 7,34 @@
"""Each combination of types on a user-defined function get's a `FunctionVariant`."""
+int_big = 1 << 60
+
+def goes_down_depth(tc_code, depth):
+ for c1 in tc_code:
+ depth = max(depth, getattr(c1, 'goes_down_depth', depth))
+ return depth
+
+def keep_arg(a):
+ """Whether the argument is needed in the C output. Both `TCVariant.extract` and `~.to_c` use it to determine that."""
+ return not (a.is_const) or getattr(a, 'destructive', None)
+
from type_stack_calc.tp_calc import StackCalc
from type_stack_calc.base.ided import Ided
from type_stack_calc.util.types_eq import types_eq, types_key
-
from type_stack_calc.tp.any import TpUnknown
from type_stack_calc.base.function import BaseFunctionVariant
-
-from type_stack_calc.to_c import ToC
+from type_stack_calc.base.component import ReturnStop
from type_stack_calc.extractor import Extractor
+from type_stack_calc.to_c import ToC
-int_big = 1 << 60
-
-def goes_down_depth(tc_code, depth):
- for c1 in tc_code:
- depth = max(depth, getattr(c1, 'goes_down_depth', depth))
- return depth
-
-def keep_arg(a):
- """Whether the argument is needed in the C output. Both `TCVariant.extract` and `~.to_c` use it to determine that."""
- return not (a.is_const) or getattr(a, 'destructive', None)
# TODO it gets angry ifi remove BaseFunctionVariant? What am i still using?
+from type_stack_calc.util.various import filter_none
+
class TCVariant(Ided, BaseFunctionVariant):
"""Instance of a code that can be type-calculated into different variants based on argument input types."""
@@ 81,14 83,11 @@ class TCVariant(Ided, BaseFunctionVariant):
def code(self):
return getattr(self.parent, f"code_{self.code_name}")
-# TODO in some cases no interest in tc_code, just the calculated type.
-
-# TODO make it actually correct.
# + If it received an `TpUnknown` or changes, it's unresolved-distance is 0
# + Otherwise it's the smallest distance of stuff it called, plus one. If none, the distance is infinite.
# + If the distance is greater than the deepest depth of call, then it is finished.
#
-# So need to track depth of call and these distances. Note that if there is no recursion the bottom will get "infinite" as value, causing the next layer.. etc.
+# Note that if there is no recursion the bottom will get "infinite" as value, causing the next layer.. etc.
def variant_tp_calc(self, real):
"""Calculates a type-compiled variant. (does hard work)"""
self.notify_real(real)
@@ 98,8 97,6 @@ class TCVariant(Ided, BaseFunctionVariant):
for arg in self.inp_stack: # Notify input it was used as argument.
if fun := getattr(arg, 'notify_arg', None): fun(self.id)
- # NOTE: it might be unclear what is being iterated, it is (should be) other functions that might call it itself back recurse with.
-
try_cnt, tp = 0, []
# Stuff it will reference too.
@@ 114,14 111,18 @@ class TCVariant(Ided, BaseFunctionVariant):
vs.get_comp('~r').set(ReturnCatchType(self_id))
# Type-calculate the code under these conditions & strip nonse.
- *tc_code, ret_stack = stack_calc.tp_calc(code, vs, [])
- tc_code = [c1 for c1 in tc_code if c1 is not None]
+ # NOTE: `stack` is only used to see if `~r .set` must be run to get it.
+ *tc_code, stack = stack_calc.tp_calc(code, vs, [])
+ tc_code = list(filter_none(tc_code))
+ # Already said return.
+ if len(stack) > 0 and stack[-1] == ReturnStop:
+ stack = []
# If stack left at the end, assume it is returned values.
- if len(ret_stack) > 0:
- *extra, _tp = stack_calc.tp_calc(['~r', '.set'], vs,
- ret_stack)
- tc_code = tc_code + [c1 for c1 in extra if c1 is not None]
+ elif len(stack) > 0:
+ *extra, _tp = stack_calc.tp_calc(['~r', '.set'], vs, stack)
+ tc_code = tc_code + list(filter_none(extra))
+
assert isinstance(vs['~r'].val, ReturnCatchType), vs['~r']
tp = vs['~r'].val.ret_stack() # Fill return type.
@@ 142,7 143,7 @@ class TCVariant(Ided, BaseFunctionVariant):
elif rdist is not None:
self.resolved_dist = min(rdist + 1, self.resolved_dist)
- self.ret_stack = tp # TODO that should be max depth?
+ self.ret_stack = tp
# If no longer changing and can finish now, it's good.
if self.resolved_dist > (self.goes_down_depth - self.depth):
self.unfinished = False
@@ 154,8 155,6 @@ class TCVariant(Ided, BaseFunctionVariant):
self.does = stack_calc.does # (for instance side-effects)
if not self.to_c: # Not going to use anyway.
self.tc_code = None
- # NOTE/TODO if produce C code(compiled result) here
- # won't need it in any case?
return
self.unfinished = tp
@@ 296,7 295,8 @@ Intention is to use this to identify when the output is identical."""
from type_stack_calc.tp.base import BaseType
class ReturnCatchType(BaseType):
- """Collects different return values with `smoosh_1` and makes the return value the unioned types."""
+ """Collects different return values with `smoosh_1` and makes the return value the unioned types.
+Note: could make this an typecalcable instead, but this uses variable logic more nicely."""
def __repr__(self): return "int:ReturnCatchType"
@@ 304,8 304,7 @@ class ReturnCatchType(BaseType):
def __init__(self, origin):
self.lst, self.origin = [], origin
- # TODO if type can be notified of escape, do it.
- def smoosh_1(self, other): # High tech, as they say.
+ def smoosh_1(self, other):
if fun := getattr(other, 'notify_return', None): fun(self.origin)
self.lst.append(other)
return self