<jupyter_start><jupyter_text>The Plan: Step 1: Parse a lambda expression. Step 2: Given the lambda parameters and parse tree, build a closure that constructs the lambda's expression, substituting arguments for parameters. Step 3: Use the parametric substitution transformer from last time to apply the closure to the target code.  Step 1<jupyter_code>tree = ast.parse('lambda x: x ** 2 + x + 1', mode='eval')
print(ast.dump(tree, indent=2))
class LambdaVisitor(ast.NodeVisitor):
    def __init__(self, name, in_expr):
        self.name = name
        self.in_expr_tree = ast.parse(in_expr, mode='eval')
        assert isinstance(self.in_expr_tree.body, ast.Lambda), "Expected lambda expression as argument."
        self._lambda_args = None
        self._lambda_body = None
        self.visit(self.in_expr_tree.body)

    def visit_Lambda(self, node):
        if self._lambda_body is None:
            self._lambda_args = [arg.arg for arg in node.args.args]
            self._lambda_body = node.body

visitor = LambdaVisitor('f', 'lambda x: x ** 2 + x + 1')
print(ast.dump(visitor._lambda_body, indent=2))
visitor._lambda_args<jupyter_output><empty_output><jupyter_text>Step 2<jupyter_code>def build_closure(name, in_expr):
    visitor = LambdaVisitor(name, in_expr)
    def _sub_closure(*args, **kws):
        assert len(args) == len(visitor._lambda_args)
        result = copy.deepcopy(visitor._lambda_body)
        transformer = Episode10.NameSubstitutionTransformer(**{k: v for k, v in zip(visitor._lambda_args, args)})
        return ast.fix_missing_locations(transformer.visit(result))
    return _sub_closure

substitutor = build_closure('f', 'lambda x: x ** 2 + x + 1')
test0 = substitutor(ast.parse('42', mode='eval').body)
print(ast.dump(test0, indent=2))
test1 = substitutor(*[ast.parse(src, mode='eval').body for src in ('42', '99')])<jupyter_output><empty_output><jupyter_text>Step 3<jupyter_code>def inline_lambda(name, in_expr):
    substitutions = {name: build_closure(name, in_expr)}
    transformer = Episode10.ParametricSubstitutionTransformer(**substitutions)
    def inliner(source):
        target = ast.parse(source)
        #print(ast.dump(target, indent=2))
        return ast.fix_missing_locations(transformer.visit(target))
    return inliner

my_inliner = inline_lambda('f', 'lambda x: x ** 2 + x + 1')
test2 = my_inliner('''
def wonkify(x):
    return f(42) - f(x)
''')
print(ast.dump(test2, indent=2))
print(ast.unparse(test2))<jupyter_output>def wonkify(x):
    return 42 ** 2 + 42 + 1 - (x ** 2 + x + 1)<jupyter_text>(Step 4: Profit!)<jupyter_code># TBD...<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13139801375095492, 'fraction_numerical': 0.01757066462948816, 'mean_word_length': 4.411157024793388, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '295421', 'license': 'MIT', 'n_tokens_mistral': 922, 'n_tokens_neox': 869, 'n_words': 206, 'path': 'ohop/Episode11.ipynb', 'repo_name': 'gitter-badger/ohop', 'size': '2618'}