def eval_expro(expr, env, value, depth=0, maxdepth=3): # logger.debug("Evaluating expr {} to {} with env {}".format(expr, value, env)) uuid = str(uuid4())[:4] if isinstance(expr, ast.AST): logger.info("Found AST for expr -> {}".format( ast_dump_if_possible(expr))) if isinstance(value, ast.AST): logger.info("Found AST for value -> {}".format( ast_dump_if_possible(value))) if depth >= maxdepth: return fail # fmt: off return conde( (eq(expr, ast.Name(id=var('name_' + uuid), ctx=ast.Load())), lookupo(var('name_' + uuid), env, value)), # (lany( # typeo(value, int), # typeo(value, str), # ), # eq(expr, ast.Constant(value=value)),), (eq(expr, ast.Str(s=var('str_e_' + uuid))), typeo( value, str), eq(var('str_e_' + uuid), value)), (eq(expr, ast.Num(n=value)), membero(value, [_ for _ in range(5)])), (eq( expr, ast.BinOp(left=var('e1_' + uuid), op=var('op_e_' + uuid), right=var('e2_' + uuid))), typeo(var('v1_' + uuid), int), typeo(var('v2_' + uuid), int), eval_expro(var('e1_' + uuid), env, var('v1_' + uuid), depth + 1, maxdepth), eval_expro(var('e2_' + uuid), env, var('v2_' + uuid), depth + 1, maxdepth), eval_opo(var('op_e_' + uuid), var('op_v_' + uuid), var('v1_' + uuid), var('v2_' + uuid), value), binopo(var('v1_' + uuid), var('v2_' + uuid), value, op=var('op_v_' + uuid))), # Lists (eq(expr, ast.List(elts=var("list_elements_" + uuid), ctx=ast.Load())), eval_expr_listo(var("list_elements_" + uuid), env, value, depth, maxdepth)), # Functions (eq(expr, ast.Lambda(body=var('body_' + uuid), args=[])), typeo(value, FunctionType), eval_expro(var('body_' + uuid), env, var('body_v_' + uuid), depth + 1, maxdepth), eq(lambda: var('body_v_' + uuid), value)), (eq(expr, ast.Call(func=var('func_' + uuid), args=[], keywords=[])), typeo(var('func_v_' + uuid), FunctionType), eval_expro(var('func_' + uuid), env, var('func_v_' + uuid), depth + 1, maxdepth), applyo(var('func_v_' + uuid), [], value)), )
def test_applyo(): x = var() assert run(0, x, applyo("add", (1, 2, 3), x)) == (("add", 1, 2, 3), ) assert run(0, x, applyo(x, (1, 2, 3), ("add", 1, 2, 3))) == ("add", ) assert run(0, x, applyo("add", x, ("add", 1, 2, 3))) == ((1, 2, 3), ) a_lv, b_lv, c_lv = var(), var(), var() from operator import add assert run(0, c_lv, applyo(add, (1, 2), c_lv)) == (3, ) assert run(0, c_lv, applyo(add, etuple(1, 2), c_lv)) == (3, ) assert run(0, c_lv, applyo(add, a_lv, c_lv)) == (cons(add, a_lv), ) for obj in ( (1, 2, 3), (add, 1, 2), [1, 2, 3], [add, 1, 2], etuple(1, 2, 3), etuple(add, 1, 2), ): o_rator, o_rands = operator(obj), arguments(obj) assert run(0, a_lv, applyo(o_rator, o_rands, a_lv)) == (term(o_rator, o_rands), ) # Just acts like `conso` here assert run(0, a_lv, applyo(o_rator, a_lv, obj)) == (arguments(obj), ) assert run(0, a_lv, applyo(a_lv, o_rands, obj)) == (operator(obj), ) # Just acts like `conso` here, too assert run(0, c_lv, applyo(a_lv, b_lv, c_lv)) == (cons(a_lv, b_lv), ) # with pytest.raises(ConsError): assert run(0, a_lv, applyo(a_lv, b_lv, object())) == () assert run(0, a_lv, applyo(1, 2, a_lv)) == ()
def test_applyo_object(): x = var() assert run(0, x, applyo(Add, (1, 2, 3), x)) == (add(1, 2, 3), ) assert run(0, x, applyo(x, (1, 2, 3), add(1, 2, 3))) == (Add, ) assert run(0, x, applyo(Add, x, add(1, 2, 3))) == ((1, 2, 3), )
first = var(prefix="first") last = var(prefix="last") ident = var(prefix="ident") balance = var(prefix="balance") newbalance = var(prefix="newbalance") # Describe a couple of transformations on accounts source = Account(first, last, ident, balance) target = Account(first, last, ident, newbalance) theorists = ("Adam", "Carl") # Give $10 to theorists theorist_bonus = lall( membero(source, accounts), membero(first, theorists), applyo(add, (10, balance), newbalance), ) # Take $10 from anyone with more than $100 a = var(prefix="a") tax_the_rich = lall( membero(source, accounts), applyo(gt, (balance, 100), a), eq(a, True), applyo(sub, (balance, 10), newbalance), ) print("Take $10 from anyone with more than $100") print(run(0, target, tax_the_rich)) print("Give $10 to theorists")