Manipulating S-expressions¶
Transformation of s-expression is implemented with inject and extend functions.
inject is used to inject (or replace) children in an expression. It expects a function which is called with children of the expression in the first argument and returns new s-expression with the expression’s tag and body returned from the function:
sexp = ['and', ['lit', True], ['lit', False]]
apply_or = lambda left, right: ['or', left, right]
inject(sexp, apply_or)
# = ['and', ['or', ['lit', True], ['lit', False]]]
Similarly, extend is used to extend the expression (or replace its tag):
extend(['lit', True], lambda exp: ['not', not exp])
# = ['not', ['lit', False]]]
# `Sexpr` implements sequence type. Therefore, to replace expression's tag it's enough:
extend(['lit', True], lambda exp: ['literal', exp[1:])
# = ['literal', True]
If an expression has multiple children, argument function must expect and return multiple arguments. In case of anonymous lambda, this means than it must return a tuple:
inject(exp, lambda first, second: (not first, not second))
Otherwise, Python’s interpreter would take the second return value as an argument to inject.