~jasper/type_stack_calc

6b65086a7cf40a6c03d719d3a91bbd6c8719dfc2 — Jasper den Ouden 2 years ago 6df9e1e
TCVariant should also check if returned is a `ReturnStop`
1 files changed, 30 insertions(+), 31 deletions(-)

M type_stack_calc/ib/tc_variant.py
M type_stack_calc/ib/tc_variant.py => type_stack_calc/ib/tc_variant.py +30 -31
@@ 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