diff options
Diffstat (limited to 'src/reduce.c')
-rw-r--r-- | src/reduce.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/src/reduce.c b/src/reduce.c index 3fc7c48..07d1bfa 100644 --- a/src/reduce.c +++ b/src/reduce.c @@ -9,24 +9,63 @@ #include <log.h> #include <assert.h> -// only substitutes (and therefore rehashes) -> no explicit beta reduction +static struct term *shift(struct term *term, size_t level, size_t amount) +{ + debug("shifting %lx\n", term->hash & HASH_MASK); + if (term->type == VAR) { + if (level > term->u.var.index) + return term; + struct term *rehashed = + term_rehash_var(term, term->u.var.index + amount); + return rehashed; + } else if (term->type == ABS) { + struct term *previous = term->u.abs.term; + struct term *new = shift(term->u.abs.term, level + 1, amount); + if (previous->hash == new->hash) + return term; // nothing changed + struct term *rehashed = term_rehash_abs(term, new); + /* term_rehash_parents(rehashed); */ + /* if (rehashed->u.abs.term->hash == (*substitution)->hash) */ + /* term_deref_head(previous, 1); */ + return rehashed; + } else if (term->type == APP) { + hash_t previous_lhs = term->u.app.lhs->hash; + hash_t previous_rhs = term->u.app.rhs->hash; + struct term *lhs = shift(term->u.app.lhs, level, amount); + struct term *rhs = shift(term->u.app.rhs, level, amount); + if (previous_lhs == lhs->hash && previous_rhs == rhs->hash) + return term; // nothing changed + struct term *rehashed = term_rehash_app(term, lhs, rhs); + /* term_rehash_parents(rehashed); */ + return rehashed; + } + fatal("invalid type %d\n", term->type); +} + +// only substitutes (and therefore increments indices and rehashes) static struct term *substitute(struct term *term, struct term *substitution, size_t level) { - debug("substituting %lx with %lx\n", term->hash, substitution->hash); + debug("substituting %lx with %lx\n", term->hash & HASH_MASK, + substitution->hash & HASH_MASK); if (term->type == VAR) { if (term->u.var.index == level) { + substitution->refs += 1; // TODO: Kinda hacky + shift(substitution, 0, level); + substitution->refs -= 1; return substitution; - } else { + } else if (term->u.var.index < level) { term_deref(substitution, 1); return term; + } else { + fatal("implement\n"); } } else if (term->type == ABS) { struct term *previous = term->u.abs.term; struct term *new = substitute(term->u.abs.term, substitution, level + 1); if (previous->hash == new->hash) - return new; // nothing changed + return term; // nothing changed struct term *rehashed = term_rehash_abs(term, new); term_rehash_parents(rehashed); if (rehashed->u.abs.term->hash == substitution->hash) @@ -55,7 +94,7 @@ struct term *reduce(struct term *term) if (!term_is_beta_redex(term)) fatal("can't reduce non-beta-redex %d\n", term->type); - debug("reducing %lx\n", term->hash); + debug("reducing %lx\n", term->hash & HASH_MASK); struct term *reduced = substitute(term->u.app.lhs, term->u.app.rhs, -1); return reduced; |