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)
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)
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))
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)