c82d6080f48c6d83f7ae9fbf54cbaaff2daaa0c5 — Jasper den Ouden 9 months ago 61fb121
`SimpleInbuildFunction` can now inspect functions to get the arguments, rather than(incorrectly) doing that upstream
M type_stack_calc/base/component.py => type_stack_calc/base/component.py +1 -1
@@ 117,7 117,7 @@ NOTE: it doesn't access `.set`, `.glob` from the value because the methods for t
        """Ask for global variable."""
        assert False, f"Only local variables can ask to become globals. {self} ({type(self)})"

    param_glob = SimpleInbuildFunction(1, _param_glob, with_vars=True,
    param_glob = SimpleInbuildFunction(_param_glob, with_vars=True,

    def get_comp(self, key):

M type_stack_calc/base/with_params.py => type_stack_calc/base/with_params.py +1 -4
@@ 5,8 5,6 @@
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

from inspect import signature

from type_stack_calc.ib.plain_component import PlainComponent
from type_stack_calc.ib.simple_ib_fun import SimpleInbuildFunction

@@ 26,8 24,7 @@ class WithParams:
        param = self._get_param(key, prep)

        if callable(param):  # Assume it's an plain inbuilt function.
            args = list(signature(param).parameters)
            return self.callable_cls(args, param, key)  # InbuildFunction
            return self.callable_cls(param, key)  # (SimpleInbuildFunction)
        elif param is not None:
            return param

M type_stack_calc/ib/ib_fun.py => type_stack_calc/ib/ib_fun.py +7 -7
@@ 10,20 10,20 @@ from type_stack_calc.base.variant_able_function import VariantAbleFunction

class InbuildFunction(SimpleInbuildFunction, VariantAbleFunction):

    def __init__(self, args, fun, name=None, infix=False, with_vars=False,
    def __init__(self, fun, name=None, args=None, infix=False, with_vars=False,
                 destructive=False, definitional=False, extract_n=None,
                 tp='method', code_type=False):
        BaseFunction.__init__(self, name, args, infix, with_vars,
                              destructive, definitional, tp)
        self.extract_n = self.n if extract_n is None else extract_n
            self, fun, name, args, infix, with_vars,
            destructive, definitional, extract_n, tp)

        self.type, self.code_type = fun, code_type
        self.code_type = code_type
        VariantAbleFunction.__init__(self, ('type',))
        assert self.type or (self.code_type is not False)
        assert self.fun or (self.code_type is not False)

    def _tp(self, inp):
        if self.code_type is not False:  # The zero indicates it's not a real call.
            return self.ensure_variant('type', inp, 0).ret_stack
            ret = self.type(*inp) if callable(self.type) else self.type
            ret = self.fun(*inp) if callable(self.fun) else self.fun
            return ret if type(ret) == list else [ret]

M type_stack_calc/ib/simple_ib_fun.py => type_stack_calc/ib/simple_ib_fun.py +7 -3
@@ 49,19 49,23 @@ from type_stack_calc.util.stack_check import assert_acceptable_vals
# For infixing a bunch of names automatically.
from type_stack_calc.util.fun_info import infixed_set

from inspect import signature

# NOTE: with "more advanced" type compilation, i noticed might want to note
#  some of the results on the object instead of re-calculating.
# (that included number ranges, pretty complicated..)
class SimpleInbuildFunction(BaseFunction):
    """Relatively simple inbuild function."""

    def __init__(self, args, fun, name=None, infix=None, with_vars=False,
    def __init__(self, fun, name=None, args=None, 
                 infix=None, with_vars=False,
                 destructive=False, definitional=False, extract_n=None,
        infix = (infix is None and name in infixed_set) or infix or False 

        BaseFunction.__init__(self, name, args, infix, with_vars,
                              destructive, definitional, tp)
            self, name, signature(fun).parameters if args is None else args,
            infix, with_vars, destructive, definitional, tp)
        self.fun = fun
        if fun == 'id': self.fun = lambda x:x

M type_stack_calc/intro/logic.py => type_stack_calc/intro/logic.py +3 -2
@@ 8,8 8,9 @@ def _type_smoosh_pair(a, b):
    return a.smoosh(b)

intro = {
    'or'  : InbuildFunction(2, _type_smoosh_pair, tp='plain'),
    'and' : InbuildFunction(2, _type_smoosh_pair, tp='plain'),  # TODO Not quite..
# TODO not entirely true, it may just definitely be the first one..
    'or'  : InbuildFunction(_type_smoosh_pair, tp='plain'),
    'and' : InbuildFunction(_type_smoosh_pair, tp='plain'),
    # TODO not

    'true' : ConstBool(True), 'false' : ConstBool(False),

M type_stack_calc/sets/float.py => type_stack_calc/sets/float.py +0 -3
@@ 53,15 53,12 @@ class SetFloat(tuple):
    def c_name(self): return f"f{self[0]}"

from type_stack_calc.ib.simple_ib_fun import SimpleInbuildFunction
from type_stack_calc.util.fun_info import fun_info

for k, fun in fun_info.items():
    use = SetFloat.bool_op if getattr(fun, 'bool', None) else \
            (SetFloat.num_op_1 if fun.n == 1 else SetFloat.num_op_2)

#    use = SimpleInbuildFunction(fun.args or fun.n, use,
#            name=k, infix=infix)
    setattr(SetFloat, 'iparam_' + k, use)
    # NOTE: totally forgot that it used reverse cases to implement the unknown to-range/stepping combinations..
    setattr(SetFloat, 'rev_iparam_' + k, use)

M type_stack_calc/sets/intersection.py => type_stack_calc/sets/intersection.py +16 -22
@@ 90,25 90,21 @@ def _do_op_2(x, opkey, y, touch):
def _untouched(touched, x):
    return (ex for i, ex in enumerate(x) if i not in touched)

def _m1(key):
    """Generates function to calculate the new type based on all applicable methods, for one argument."""
    opkey = f"iparam_{key}"
    def ret(self):
        return type(self)(*_do_op_1(self, opkey))
    return ret

def _m2(key):
    """Generates function to calculate new type, for two arguments.
Will try `rev_param`, with the arguments flipped, too."""
def _m(n, key):
    """Generates function to calculate the new type based on all applicable methods, for one or two arguments. If two arguments it will try iparam and rev_iparam."""
    opkey, rev_opkey  = f"iparam_{key}", f"rev_iparam_{key}"
    def ret(y, x):
        #return type(self)
        touch_x, touch_y = set(), set()
        ret = (*_do_op_2(x, opkey, y, (touch_x, touch_y)),
               *_do_op_2(y, rev_opkey, x, (touch_y, touch_x)))
        return type(x)(*ret,
                       *_untouched(touch_x, x),
                       *_untouched(touch_y, y))
    if n == 1:
        def ret(self):
            return type(self)(*_do_op_1(self, opkey))
    elif n == 2:
        def ret(y, x):
            touch_x, touch_y = set(), set()
            ret = (*_do_op_2(x, opkey, y, (touch_x, touch_y)),
                   *_do_op_2(y, rev_opkey, x, (touch_y, touch_x)))
            return type(x)(*ret, *_untouched(touch_x, x),
                           *_untouched(touch_y, y))
        assert False, n
    return ret

from inspect import signature

@@ 177,10 173,8 @@ Otherwise makes an intersection of the results."""

        if n_args == 'value':
            return type(self)(*vals)  # Will intersect them further itself.
        elif n_args == 1:
            return SimpleInbuildFunction(1, _m1(name), name)
        elif n_args == 2:
            return SimpleInbuildFunction(2, _m2(name), name)
        elif isinstance(n_args, int):
            return SimpleInbuildFunction(_m(n, name), name, n)
        elif n_args is None:
            assert False, f"Unsupported arg count for {name}? {n_args} {self}"

M type_stack_calc/tp/num.py => type_stack_calc/tp/num.py +2 -2
@@ 19,8 19,8 @@ class _TpHelp(BaseType):
    def get_param_final(self, _name): return None  # (just abstain)

    # TODO just do the infix detection at the end?
    def callable_cls(self, args, param, key):
         return SimpleInbuildFunction(args, param, key,
    def callable_cls(self, fun, args, key):
         return SimpleInbuildFunction(fun, args, key,
                                      infix=key in infixed_set)

    def settable(self, other):