Author here. The `<<` operator is being abused to mean "bind", so the right side is a normal expression (constructing a Foo and Bar) and the left side matches it to a particular "shape".
The purposes of pattern matching is to replace code that looks like this:
if (isinstance(tree, BinOp)
and type(tree.left) is Name
and type(tree.op) is Mod
and tree.left.id in module.expr_registry):
...
with code that looks like this
if BinOp(Name(id), Mod(), body) << tree
and id in module.expr_registry:
...
Which looks much nicer, and more clearly says what you want: that `tree` "looks like" a particular shape.
EDIT: Here's another example. Turning this:
if ((isinstance(tree, ClassDef) or isinstance(tree, FunctionDef))
and len(tree.decorator_list) == 1
and tree.decorator_list[0]
and type(tree.decorator_list[0]) is Name
and tree.decorator_list[0].id in module.decorator_registry):
...
into:
if ((isinstance(tree, ClassDef) or isinstance(tree, FunctionDef))
and [Name(id)] << tree.decorator_list
and id in module.decorator_registry):
...
The purposes of pattern matching is to replace code that looks like this:
with code that looks like this Which looks much nicer, and more clearly says what you want: that `tree` "looks like" a particular shape.EDIT: Here's another example. Turning this:
into: Doesn't quite work yet, but we're getting there