Example #1
0
    def __call__(self, *args, **kwargs):
        """ Returns a new _LambdaExpression performing '<r>.__call__(*args, **kwargs)' on the result <r> of this expression's evaluation """
        # return self.add_bound_method_to_stack('__call__', *args, **kwargs)
        root_var, _ = _get_root_var(self, *args, **kwargs)

        def ___call__(input):
            # first evaluate the inner function
            r = self.evaluate(input)
            # then call the method
            return r.__call__(
                *[evaluate(other, input) for other in args], **{
                    arg_name: evaluate(other, input)
                    for arg_name, other in kwargs.items()
                })

        # return a new LambdaExpression of the same type than self, with the new function as inner function
        # Note: we use precedence=None for coma-separated items inside the parenthesis
        string_expr = get_repr(self, _PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF) \
                      + '(' + ', '.join([get_repr(arg, None) for arg in args]) \
                      + (', ' if (len(args) > 0 and len(kwargs) > 0) else '')\
                      + ', '.join([arg_name + '=' + get_repr(arg, None) for arg_name, arg in kwargs.items()]) + ')'
        return type(self)(
            fun=___call__,
            precedence_level=_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF,
            str_expr=string_expr,
            root_var=root_var)
Example #2
0
    def __or__(self, other):
        """
        A logical OR between this _LambdaExpression and something else. The other part can either be
        * a scalar
        * a callable
        * a _LambdaExpression

        A special operation can be performed by doing '| _'. This will 'close' the expression and return a callable
        view of it

        :param other:
        :return:
        """
        # Abandoned - operator | does not have precedence over comparison operators (<, >, ...)
        # if other is _:
        #     # special character: close and return
        #     return self.as_function()

        if not callable(other):
            # then the other part has already been evaluated, since this operator is not a short-circuit like the 'or'
            # keyword. This is probably an error from the developer ? Warn him/her
            warn(
                "One of the sides of an '|' operator is not a _LambdaExpression and therefore will always have the same"
                " value, whatever the input. This is most probably a mistake in the expression."
            )
            if other:
                # the other part is True, there will never be a need to evaluate.
                return True
            else:
                # the other part is False, return a boolean expression of self (The Bool function is created later)
                return getattr(this_module, 'Bool')(self)
        else:
            # check that both work on the same variable
            root_var, _ = _get_root_var(self, other)

            # create a new _LambdaExpression able to evaluate both sides with short-circuit capability
            def evaluate_both_inner_functions_and_combine(input):
                # first evaluate self
                left = self.evaluate(input)
                if left:
                    # short-circuit: the left part is True, no need to evaluate the right part
                    return True
                else:
                    # evaluate the right part
                    return bool(evaluate(other, input))

            string_expr = get_repr(self,
                                   _PRECEDENCE_BITWISE_OR) + ' | ' + get_repr(
                                       other, _PRECEDENCE_BITWISE_OR)
            return _LambdaExpression(
                fun=evaluate_both_inner_functions_and_combine,
                precedence_level=_PRECEDENCE_BITWISE_OR,
                str_expr=string_expr,
                root_var=root_var)
Example #3
0
    def __rpow__(self, other):
        """ Returns a new _LambdaExpression performing 'other ** <r>' on the result <r> of this expression's evaluation """
        root_var, _ = _get_root_var(self, other)

        def ___rpow__(input):
            # first evaluate the inner function
            r = self.evaluate(input)
            # then call the method
            return evaluate(other, input)**r

        # return a new LambdaExpression of the same type than self, with the new function as inner function
        string_expr = get_repr(other, _PRECEDENCE_EXPONENTIATION) + ' ** ' \
                      + get_repr(self, _PRECEDENCE_POS_NEG_BITWISE_NOT)
        return type(self)(fun=___rpow__,
                          precedence_level=13,
                          str_expr=string_expr,
                          root_var=root_var)
Example #4
0
    def __and__(self, other):
        """
        A logical AND between this _LambdaExpression and something else. The other part can either be
        * a scalar
        * a callable
        * a _LambdaExpression

        :param other:
        :return:
        """
        if not callable(other):
            # then the other part has already been evaluated, since this operator is not a short-circuit like the 'and'
            # keyword. This is probably an error from the developer ? Warn him/her
            warn(
                "One of the sides of an '&' operator is not a _LambdaExpression and therefore will always have the "
                "same value, whatever the input. This is most probably a mistake in the expression."
            )
            if not other:
                # the other part is False, there will never be a need to evaluate.
                return False
            else:
                # the other part is True, return a boolean expression of self. (The Bool function is created later)
                return getattr(this_module, 'Bool')(self)
        else:
            # check that both work on the same variable
            root_var, _ = _get_root_var(self, other)

            # create a new _LambdaExpression able to evaluate both sides with short-circuit capability
            def evaluate_both_inner_functions_and_combine(input):
                # first evaluate self
                left = self.evaluate(input)
                if not left:
                    # short-circuit: the left part is False, no need to evaluate the right part
                    return False
                else:
                    # evaluate the right part
                    return bool(evaluate(other, input))

            string_expr = get_repr(self,
                                   _PRECEDENCE_BITWISE_AND) + ' & ' + get_repr(
                                       other, _PRECEDENCE_BITWISE_AND)
            return _LambdaExpression(
                fun=evaluate_both_inner_functions_and_combine,
                precedence_level=_PRECEDENCE_BITWISE_AND,
                str_expr=string_expr,
                root_var=root_var)
Example #5
0
    def __xor__(self, other):
        """
        A logical XOR between this _LambdaExpression and something else. The other part can either be
        * a scalar
        * a callable
        * a _LambdaExpression

        :param other:
        :return:
        """
        if not callable(other):
            # then the other part has already been evaluated, since this operator is not a short-circuit like the 'or'
            # keyword. This is probably an error from the developer ? Warn him/her
            warn(
                "One of the sides of an '^' operator is not a _LambdaExpression and therefore will always have the "
                "same value, whatever the input. This is most probably a mistake in the expression."
            )
            if other:
                # the other part is True, so this becomes a Not expression of self (The Not function is created later)
                return self.not_()
            else:
                # the other part is False, return a boolean expression of self (The Bool function is created later)
                return getattr(this_module, 'Bool')(self)
        else:
            # check that both work on the same variable
            root_var, _ = _get_root_var(self, other)

            # create a new _LambdaExpression able to evaluate both sides
            def evaluate_both_inner_functions_and_combine(input):
                # first evaluate self
                left = self.evaluate(input)

                # evaluate the right part
                right = evaluate(other, input)

                return (left and not right) or (not left and right)

            string_expr = get_repr(self,
                                   _PRECEDENCE_BITWISE_XOR) + ' ^ ' + get_repr(
                                       other, _PRECEDENCE_BITWISE_XOR)
            return _LambdaExpression(
                fun=evaluate_both_inner_functions_and_combine,
                precedence_level=_PRECEDENCE_BITWISE_XOR,
                str_expr=string_expr,
                root_var=root_var)
Example #6
0
    def __getattr__(self, name):
        """ Returns a new _LambdaExpression performing 'getattr(<r>, *args)' on the result <r> of this expression's evaluation """
        root_var, _ = _get_root_var(self, name)

        def ___getattr__(input):
            # first evaluate the inner function
            r = self.evaluate(input)
            # then call the method
            return getattr(r, evaluate(name, input))

        # return a new LambdaExpression of the same type than self, with the new function as inner function
        string_expr = get_repr(
            self, _PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF) + '.' + name
        return type(self)(
            fun=___getattr__,
            precedence_level=_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF,
            str_expr=string_expr,
            root_var=root_var)
Example #7
0
    def __rdivmod__(self, other):
        """ Returns a new _LambdaExpression performing '<r>.__rdivmod__(*args)' on the result <r> of this expression's evaluation """
        # return self.add_bound_method_to_stack('__rdivmod__', *args)
        root_var, _ = _get_root_var(self, other)

        def ___rdivmod__(input):
            # first evaluate the inner function
            r = self.evaluate(input)
            # then call the method
            return divmod(evaluate(other, input), r)

        # return a new LambdaExpression of the same type than self, with the new function as inner function
        # Note: we use precedence=None for coma-separated items inside the parenthesis
        string_expr = 'divmod(' + get_repr(other, None) + ', ' + get_repr(
            self, None) + ')'
        return type(self)(
            fun=___rdivmod__,
            precedence_level=_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF,
            str_expr=string_expr,
            root_var=root_var)