def try_decide_less_weak(lhs, rhs): """Weak decision procedure returning True, False, or None.""" assert is_code(lhs), lhs assert is_code(rhs), rhs # Try simple cases. if lhs is BOT or lhs is rhs or rhs is TOP: return True if lhs is TOP and rhs is BOT: return False # Destructure JOIN. if is_join(lhs): return trool_all(try_decide_less_weak(i, rhs) for i in iter_join(lhs)) if is_join(rhs): # This requires we give up at unreduced terms. return trool_any(try_decide_less_weak(lhs, i) for i in iter_join(rhs)) # Destructure ABS. while is_abs(lhs) or is_abs(rhs): lhs = unabstract(lhs) rhs = unabstract(rhs) assert lhs is not rhs, lhs # Destructure APP. lhs_head, lhs_args = unapply(lhs) rhs_head, rhs_args = unapply(rhs) # Give up at unreduced terms. if is_abs(lhs_head) or is_abs(rhs_head): if len(lhs_args) == len(rhs_args): if try_decide_less_weak(lhs_head, rhs_head) is True: if all(try_decide_less_weak(i, j) is True for i, j in zip(lhs_args, rhs_args)): return True return None if lhs_args and not is_var(lhs_head): return None if rhs_args and not is_var(rhs_head): return None # Distinguish solvable terms. if is_var(lhs_head) and is_var(rhs_head): if lhs_head is not rhs_head or len(lhs_args) != len(rhs_args): return False return trool_all( try_decide_less_weak(i, j) for i, j in zip(lhs_args, rhs_args) ) # Distinguish quoted terms. if is_quote(lhs_head) and is_quote(rhs_head): return try_decide_equal(lhs_head[1], rhs_head[1]) # Anything else is incomparable. return False
def approximate_var(code, direction, rank): """Locally approximate wrt one variable.""" assert is_code(code), code assert direction is TOP or direction is BOT, direction assert isinstance(rank, int) and rank >= 0, rank result = set() if not occurs(code, rank): result.add(code) elif is_ivar(code): assert code[1] == rank, code result.add(code) result.add(direction) elif is_app(code): for lhs in approximate_var(code[1], direction, rank): for rhs in approximate_var(code[2], direction, rank): result.add(app(lhs, rhs)) elif is_abs(code): for body in approximate_var(code[1], direction, rank + 1): result.add(abstract(body)) elif is_join(code): for lhs in approximate_var(code[1], direction, rank): for rhs in approximate_var(code[2], direction, rank): result.add(join(lhs, rhs)) else: raise ValueError(code) return tuple(sorted(result, key=complexity))
def test_try_compute_step_runs(code): for step in xrange(5): with xfail_if_not_implemented(): result = try_compute_step(code) if is_normal(code): assert result is None return else: assert is_code(result)
def is_linear(code): """Return whether code never copies a bound IVAR.""" assert is_code(code), code return _is_linear(code) is not None