def _match(pattern, term, defs, rank): if is_nvar(pattern): for _ in xrange(rank): if IVAR_0 in free_vars(term): raise NoMatch term = decrement_rank(term) if defs.setdefault(pattern, term) is not term: raise NoMatch elif is_atom(pattern) or is_ivar(pattern): if pattern is not term: raise NoMatch elif is_abs(pattern): if not is_abs(term): raise NoMatch _match(pattern[1], term[1], defs, rank + 1) elif is_app(pattern): if not is_app(term): raise NoMatch _match(pattern[1], term[1], defs, rank) _match(pattern[2], term[2], defs, rank) elif is_join(pattern): if not is_join(term): raise NoMatch _match(pattern[1], term[1], defs, rank) _match(pattern[2], term[2], defs, rank) elif is_quote(pattern): if not is_quote(term): raise NoMatch _match(pattern[1], term[1], defs, rank) else: raise ValueError(pattern)
def de_bruijn_abstract(body): """APP,JOIN,TOP,BOT,I,K,B,C,S,eta-abstraction algorithm.""" result = _try_abstract(body) if result is not None: return result elif body in (TOP, BOT): return body # Rules TOP, BOT else: return APP(K, decrement_rank(body)) # Rule K
def _try_abstract(body): """Returns abstraction if IVAR(0) occurs in body, else None.""" if body is IVAR_0: return I # Rule I elif is_app(body): lhs = body[1] rhs = body[2] lhs_abs = _try_abstract(lhs) rhs_abs = _try_abstract(rhs) if lhs_abs is None: if rhs_abs is None: return None # Rule K elif rhs_abs is I: return decrement_rank(lhs) # Rule eta else: return APP(APP(B, decrement_rank(lhs)), rhs_abs) # Rule B else: if rhs_abs is None: return APP(APP(C, lhs_abs), decrement_rank(rhs)) # Rule C else: return APP(APP(S, lhs_abs), rhs_abs) # Rule S elif is_join(body): lhs = body[1] rhs = body[2] lhs_abs = _try_abstract(lhs) rhs_abs = _try_abstract(rhs) if lhs_abs is None: if rhs_abs is None: return None # Rule K else: # Rule JOIN-K return JOIN(APP(K, decrement_rank(lhs)), rhs_abs) else: if rhs_abs is None: # Rule JOIN-K return JOIN(lhs_abs, APP(K, decrement_rank(rhs))) else: return JOIN(lhs_abs, rhs_abs) # Rule JOIN else: return None # Rule K
def test_decrement_increment_rank(term): assert bohm.decrement_rank(bohm.increment_rank(term)) is term
def test_decrement_rank(term, expected): assert bohm.decrement_rank(term) is expected
def test_abstract_eta(code): hypothesis.assume(is_const(code)) assert abstract(app(code, IVAR(0))) is decrement_rank(code)
def test_decrement_increment_rank(code): assert decrement_rank(increment_rank(code, 0)) is code
def test_decrement_rank(code, expected): assert decrement_rank(code) is expected