Ejemplo n.º 1
0
    def do_prepare(self):
        argspec = inspect.getargspec(self.expr_fn)

        check_multiple([
            (len(argspec.args)
             in (1, 2), 'Invalid collection iteration lambda: only one '
             'or two parameters expected'),
            (not argspec.varargs and not argspec.keywords,
             'Invalid collection iteration lambda: no *args or **kwargs'),
            (not argspec.defaults,
             'Invalid collection iteration lambda: No default values allowed '
             'for arguments')
        ])

        self.requires_index = len(argspec.args) == 2
        self.element_var = AbstractVariable(
            names.Name("Item_{}".format(next(CollectionExpression._counter))),
            source_name=names.Name.from_lower(argspec.args[0]))
        if self.requires_index:
            self.index_var = AbstractVariable(
                names.Name('I'),
                type=LongType,
                create_local=True,
                source_name=names.Name.from_lower(argspec.args[1]))
            expr = self.expr_fn(self.index_var, self.element_var)
        else:
            expr = self.expr_fn(self.element_var)
        self.expr = unsugar(expr)
Ejemplo n.º 2
0
    def do_prepare(self):
        # When this expression does not come from our Python DSL (see the
        # initialize method above), the sub-expression is ready to use: do not
        # try to expand the function.
        if self.expr is not None:
            return

        argspec = inspect.getargspec(self.expr_fn)

        check_multiple([
            (len(argspec.args) in (1, 2),
             'Invalid collection iteration lambda: only one '
             'or two parameters expected'),
            (not argspec.varargs and not argspec.keywords,
             'Invalid collection iteration lambda: no *args or **kwargs'),
            (not argspec.defaults,
             'Invalid collection iteration lambda: No default values allowed '
             'for arguments')
        ])

        if len(argspec.args) == 2:
            self.requires_index = True
            index_var_pos = 0
            item_var_pos = 1
        else:
            self.requires_index = False
            index_var_pos = None
            item_var_pos = 0

        # Get the name of the loop variable from the DSL. But don't when we
        # have a "default" one, such as for using the ".filter" combinator. In
        # this case, it's up to ".filter"'s special implementation to get the
        # name from the filter function.
        source_name = (None if self.expr_fn == collection_expr_identity else
                       names.Name.from_lower(argspec.args[item_var_pos]))

        self.element_var = AbstractVariable(
            names.Name("Item_{}".format(next(CollectionExpression._counter))),
            source_name=source_name
        )
        if self.requires_index:
            self.index_var = AbstractVariable(
                names.Name('I'), type=T.Int,
                source_name=names.Name.from_lower(argspec.args[index_var_pos])
            )
            expr = self.expr_fn(self.index_var, self.element_var)
        else:
            expr = self.expr_fn(self.element_var)
        self.expr = unsugar(expr)
Ejemplo n.º 3
0
    def do_prepare(self):
        # If this Then was created using create_from exprs, there is no lambda
        # expansion to do.
        if self.then_expr:
            return

        argspec = inspect.getargspec(self.then_fn)
        check_source_language(
            len(argspec.args) == 1 and not argspec.varargs
            and not argspec.keywords and not argspec.defaults,
            'Invalid lambda for Then expression: exactly one parameter is'
            ' required, without a default value')

        self.var_expr = AbstractVariable(names.Name("Var_Expr"),
                                         create_local=True,
                                         source_name=names.Name(
                                             argspec.args[0]))
        self.then_expr = unsugar(self.then_fn(self.var_expr))
Ejemplo n.º 4
0
    def prepare_iter_function(
        self,
        what: str,
        expr_fn: Union[Callable[[AbstractExpression], AbstractExpression],
                       Callable[[AbstractExpression, AbstractExpression],
                                AbstractExpression]]
    ) -> AbstractExpression:
        """
        Validate an iteration function, whether it only takes the iteration
        element or also the iteration index.

        Return the abstract expression to evaluate for each iteration.

        :param what: Purpose of this function. Used for diagnostics.
        :param expr_fn: Function to prepare.
        """
        check_type(
            expr_fn,
            types.FunctionType,
            "{what} passed to a collection expression must be a lambda or a"
            " function"
        )

        argspec = inspect.getargspec(expr_fn)

        check_multiple([
            (len(argspec.args) in (1, 2),
             'Invalid collection iteration lambda: only one'
             ' or two parameters expected'),
            (not argspec.varargs and not argspec.keywords,
             'Invalid collection iteration lambda: no *args or **kwargs'),
            (not argspec.defaults,
             'Invalid collection iteration lambda: No default values allowed'
             ' for arguments')
        ])

        # Get source names for the iteration variables
        index_required = False
        index_varname: Optional[str] = None
        element_varname: Optional[str] = None
        if len(argspec.args) == 2:
            index_required = True
            self.requires_index = True
            index_varname = argspec.args[0]
            element_varname = argspec.args[1]
        else:
            element_varname = argspec.args[0]

        # We are interested in names from user sources: disregard names from
        # the default functions function we define here.
        if expr_fn in builtin_collection_functions:
            index_varname = None
            element_varname = None

        # Make sure we have an iteration element variable
        self.element_var = self.create_iteration_var(
            self.element_var, "Item", element_varname
        )

        # Expand the function. If the index is required, make sure we have an
        # iteration variable for it.
        if index_required:
            self.index_var = self.create_iteration_var(
                self.index_var, "Index", index_varname, T.Int
            )
            expr = expr_fn(self.index_var, self.element_var)  # type: ignore
        else:
            expr = expr_fn(self.element_var)  # type: ignore

        return unsugar(expr)