def visit_SelectMany_of_SelectMany(self, parent: ast.Call, selection: ast.Lambda): ''' Transformation #1: seq.SelectMany(x: f(x)).SelectMany(y: f(y)) => SelectMany(SelectMany(seq, x: f(x)), y: f(y)) is turned into: seq.SelectMany(x: f(x).SelectMany(y: f(y))) => SelectMany(seq, x: SelectMany(f(x), y: f(y))) ''' _, args = unpack_Call(parent) assert (args is not None) and len(args) == 2 seq = args[0] func_f = args[1] assert isinstance(func_f, ast.Lambda) func_g = selection captured_arg = func_f.args.args[0].arg captured_body = func_f.body new_select = function_call( 'SelectMany', [cast(ast.AST, captured_body), cast(ast.AST, func_g)]) new_select_lambda = lambda_build(captured_arg, new_select) new_selectmany = function_call( 'SelectMany', [seq, cast(ast.AST, new_select_lambda)]) return new_selectmany
def visit_Select_of_SelectMany(self, parent, selection): r''' seq.SelectMany(x: f(x)).Select(y: g(y)) => Select(SelectMany(seq, x: f(x)), y: g(y)) is turned into seq.SelectMany(x: f(x).Select(y: g(y))) => SelectMany(seq, x: Select(f(x), y: g(y))) ''' (_, args) = unpack_Call(parent) source = args[0] func_f = args[1] assert isinstance(func_f, ast.Lambda) func_g = selection lambda_select = \ lambda_body_replace(func_f, make_Select(lambda_body(func_f), func_g)) # type: ast.AST return self.visit(function_call('SelectMany', [source, lambda_select]))
def visit_Where_of_SelectMany(self, parent, filter): ''' seq.SelectMany(x: f(x)).Where(y: g(y)) => Where(SelectMany(seq, x: f(x)), y: g(y)) Is turned into: seq.SelectMany(x: f(x).Where(y: g(y))) => SelectMany(seq, x: Where(f(x), g(y))) ''' _, args = unpack_Call(parent) seq = args[0] func_f = args[1] assert isinstance(func_f, ast.Lambda) func_g = filter lambda_where = lambda_body_replace( func_f, function_call("Where", [lambda_body(func_f), func_g])) return self.visit(function_call('SelectMany', [seq, lambda_where]))
def visit_SelectMany_of_Select(self, parent_select: ast.Call, selection: ast.Lambda): ''' seq.Select(x: f(x)).SelectMany(y: g(y)) => SelectMany(Select(seq, x: f(x)), y:g(y)) is turned into seq.SelectMany(x: f(x).Select(y: g(y))) => SelectMany(seq, x: Select(f(x), y: g(y))) ''' _, select_args = unpack_Call(parent_select) assert (select_args is not None) and len(select_args) == 2 seq = select_args[0] func_f = select_args[1] assert isinstance(func_f, ast.Lambda) func_g = selection w = function_call('SelectMany', [seq, self.visit(convolute(func_g, func_f))]) return w
def visit_Select_of_Select(self, parent: ast.Call, selection: ast.Lambda): r''' seq.Select(x: f(x)).Select(y: g(y)) => Select(Select(seq, x: f(x)), y: g(y)) is turned into seq.Select(x: g(f(x))) => Select(seq, x: g(f(x))) ''' _, args = unpack_Call(parent) source = args[0] func_f = args[1] assert isinstance(func_f, ast.Lambda) func_g = selection # Convolute the two functions new_selection = self.visit(convolute(func_g, func_f)) # And return the parent select with the new selection function return make_Select(source, new_selection)
def visit_Where_of_Select(self, parent, filter): ''' seq.Select(x: f(x)).Where(y: g(y)) => Where(Select(seq, x: f(x)), y: g(y)) Is turned into: seq.Where(x: g(f(x))).Select(x: f(x)) => Select(Where(seq, x: g(f(x)), f(x)) ''' _, args = unpack_Call(parent) source = args[0] func_f = args[1] assert isinstance(func_f, ast.Lambda) func_g = filter w = function_call( 'Where', [source, self.visit(convolute(func_g, func_f))]) s = make_Select(w, func_f) # Recursively visit this mess to see if the Where needs to move further up. return self.visit(s)
def visit_Where_of_Where(self, parent: ast.Call, filter: ast.Lambda): ''' seq.Where(x: f(x)).Where(x: g(x)) => Where(Where(seq, x: f(x)), y: g(y)) is turned into seq.Where(x: f(x) and g(y)) => Where(seq, x: f(x) and g(y)) ''' # Unpack arguments and f and g functions _, args = unpack_Call(parent) source = args[0] func_f = args[1] assert isinstance(func_f, ast.Lambda) func_g = filter arg = arg_name() convolution = lambda_build( arg, ast.BoolOp(ast.And(), [lambda_call(arg, func_f), lambda_call(arg, func_g)])) # type: ast.AST return self.visit(function_call('Where', [source, convolution]))