~jasper/type_stack_calc

0eb905b10fee6efa2fd452efe480d374ca7a2377 — Jasper den Ouden 1 year, 6 months ago a36ba41
Fix: if only one branch in if, it would put out the condition, which would get mistreated as another argument. Made `IfOneBranch` to deal with this. Also some utility functions in separate file
M type_stack_calc/call/if_call.py => type_stack_calc/call/if_call.py +2 -5
@@ 5,7 5,7 @@
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

from type_stack_calc.ib.if_block import IfBlock
from type_stack_calc.ib.if_block import IfBlock, IfOneBranch

from type_stack_calc.base.component import BaseComponent



@@ 43,13 43,10 @@ class IfCall:
            assert isinstance(cond_val, TpBool), cond_val
            c_case = cond_val.case

        # TODO ideally stack passed does not need to be empty.
        if isinstance(c_case, bool):  # Just one branch.
            # NOTE: conditions may have destructive statements in there.
            # And put in one of the bodies.
            *tc_body, stack = sc.tp_calc(then if c_case else otherwise,
                                         vs, [])
            return stack, *tc_cond, *tc_body
            return stack, IfOneBranch(tc_cond, c_case, tc_body)
        else:
            assert c_case is None, "Not definite True/False but not None?"
            *tc_t, if_t = sc.tp_calc(then,      vs, [])

M type_stack_calc/extractor.py => type_stack_calc/extractor.py +4 -0
@@ 48,6 48,10 @@ Derives from tuple; first is a function that puts it inside the function, and th
The extracted may be needed because it's destructive etc."""
        return Extractor((_ignore, self[1]))

    def extract(self, gen):
        for el in gen:
            if gen is not None: self._extract_1(gen, el)

    tmp_var = TmpVar

class ExtractorWVar(Extractor):

M type_stack_calc/ib/if_block.py => type_stack_calc/ib/if_block.py +23 -15
@@ 5,30 5,36 @@
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

from type_stack_calc.extractor import Extractor, StopMarker
from type_stack_calc.extractor import Extractor, extract, StopMarker

def list_flatten(gen):
    for el in gen:
        if type(el) == list:
            for r_el in list_flatten(el): yield r_el
        else:
            yield el
from type_stack_calc.pe.drop import PostExtractDrop

from type_stack_calc.util.various import list_flatten, filter_none

class IfOneBranch:
    """If block, but after concluding only one."""
    # TODO may only exist post-tc but pre-extract.

def filter_none(lst): return [el for el in lst if el is not None]
    def __init__(self, cond, which, body):
        assert isinstance(which, bool)
        self.cond, self.which, self.body = cond, which, body

    def extract(self, extractor, gen, _obj):
        # Entirely extract condition.
        extractor[1](extract(reversed(self.cond + [PostExtractDrop])))
        # Extract as normal the body.
        extractor.extract_1(reversed(self.body))

class IfBlock:
    """`if_block.py`: `{..if..} {..else..} (..cond..).if` provider."""
    def __init__(self, cond, yes, no, ret_stack):
        self.cond, self.yes, self.no = map(filter_none, [cond, yes, no])
        self.cond, self.yes, self.no = \
            map(list, map(filter_none, [cond, yes, no]))
        self.stack = ret_stack

    def extract_cond(self, extractor, gen):
        lst = []
        e_c = Extractor((lst.append, extractor[1]))
        gen = reversed(self.cond)
        for el in gen:
            if el is not None:
                e_c._extract_1(gen, el)
        lst = [] # Type-calced data needs reversing.
        Extractor((lst.append, extractor[1])).extract(reversed(self.cond))
        self.cond = list_flatten(lst)  # Remainder can stay.

    def extract(self, extractor, gen, _obj):


@@ 37,8 43,10 @@ class IfBlock:
        if len(self.stack) > 0:  # TODO permit multi-output stuff or not?
            assert len(self.stack) == 1
            tmp = extractor.tmp_var('if', self.stack[0])
            # Defining and set setting outside, and value inside.
            if deffer := getattr(tmp, 'deffer', None):
                extractor[1](deffer)

            if valuer := getattr(tmp, 'valuer', None):
                extractor[0](tmp if valuer == 'self' else valuer)
            else:  # Stops excessive stuff from being printed. (TODO right?)

A type_stack_calc/util/various.py => type_stack_calc/util/various.py +15 -0
@@ 0,0 1,15 @@

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

def filter_none(lst): return (el for el in lst if el is not None)

def list_flatten(gen):
    for el in gen:
        if type(el) == list:
            for r_el in list_flatten(el): yield r_el
        else:
            yield el