Используя recursive
, я могу генерировать простые AST, например,
from hypothesis import *
from hypothesis.strategies import *
def trees():
base = integers(min_value=1, max_value=10).map(lambda n: 'x' + str(n))
@composite
def extend(draw, children):
op = draw(sampled_from(['+', '-', '*', '/']))
return (op, draw(children), draw(children))
return recursive(base, draw)
Теперь я хочу изменить его, чтобы я мог генерировать логические операции в дополнение к арифметическим.Моя первоначальная идея - добавить параметр в trees
:
def trees(tpe):
base = integers(min_value=1, max_value=10).map(lambda n: 'x' + str(n) + ': ' + tpe)
@composite
def extend(draw, children):
if tpe == 'bool':
op = draw(sampled_from(['&&', '||']))
return (op, draw(children), draw(children))
elif tpe == 'num':
op = draw(sampled_from(['+', '-', '*', '/']))
return (op, draw(children), draw(children))
return recursive(base, draw)
Хорошо, пока.Но как мне их смешать?То есть мне также нужны операторы сравнения и троичный оператор, которые потребовали бы, так сказать, «вызова children
с другим параметром».
Деревья должны быть хорошо типизированы: если операция выполняется'||'
или '&&'
, оба аргумента должны быть логическими, аргументы '+'
или '<'
должны быть числами и т. Д. Если бы у меня было только два типа, я мог бы просто использовать filter
(учитывая type_of
function):
if op in ('&&', '||'):
bool_trees = children.filter(lambda x: type_of(x) == 'bool')
return (op, draw(bool_trees), draw(bool_trees))
но в реальном случае это было бы неприемлемо.
Поддерживает ли recursive
это?Или есть другой способ?Очевидно, я могу напрямую определить trees
рекурсивно, но это сталкивается с стандартными проблемами .