diff options
author | Marvin Borner | 2023-06-01 23:08:07 +0200 |
---|---|---|
committer | Marvin Borner | 2023-06-01 23:08:07 +0200 |
commit | c9b0537a1f04c8a28e1f9aa9a6112a1e59653eea (patch) | |
tree | ec403ce89057acf409ac8ccb21c0538d207f5a47 | |
parent | c062eaeea09592cbdf7e5d732e992d0cdd8eedc5 (diff) |
Some work on derefs
-rw-r--r-- | src/reduce.c | 21 | ||||
-rw-r--r-- | src/schedule.c | 2 | ||||
-rw-r--r-- | src/term.c | 48 |
3 files changed, 53 insertions, 18 deletions
diff --git a/src/reduce.c b/src/reduce.c index 9e7520d..38baf06 100644 --- a/src/reduce.c +++ b/src/reduce.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <term.h> +#include <map.h> #include <reduce.h> #include <log.h> #include <assert.h> @@ -13,26 +14,28 @@ static struct term *substitute(struct term *term, struct term *substitution, { if (term->type == VAR) { if (term->u.var.index == level) { - // TODO: deref index + term_deref_head(term); return substitution; } else { return term; } } else if (term->type == ABS) { + hash_t previous = term->u.abs.term->hash; struct term *new = substitute(term->u.abs.term, substitution, level + 1); - if (term->u.abs.term->hash == new->hash) + if (previous == new->hash) return term; // nothing changed struct term *rehashed = term_rehash_abs(term, new); term_rehash_parents(rehashed); 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 = substitute(term->u.app.lhs, substitution, level); struct term *rhs = substitute(term->u.app.rhs, substitution, level); - if (term->u.app.lhs->hash == lhs->hash && - term->u.app.rhs->hash == rhs->hash) + 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); @@ -45,8 +48,12 @@ static struct term *substitute(struct term *term, struct term *substitution, // ([X] Y) -> X/Y struct term *reduce(struct term *term) { - assert(term->type == APP); - assert(term->u.app.lhs->type == ABS); + if (term->type != APP || term->u.app.lhs->type != ABS) + fatal("can't reduce non-beta-redex %d\n", term->type); - return substitute(term->u.app.lhs, term->u.app.rhs, -1); + map_delete(term->u.app.lhs->parents, term); + map_delete(term->u.app.rhs->parents, term); + struct term *reduced = substitute(term->u.app.lhs, term->u.app.rhs, -1); + term_deref_head(term); + return reduced; } diff --git a/src/schedule.c b/src/schedule.c index 93cd700..1362b1e 100644 --- a/src/schedule.c +++ b/src/schedule.c @@ -69,6 +69,8 @@ void schedule_add(struct term *term) void schedule(void) { while (pqueue_size(queue) > 0) { + map_dump(map_all_terms()); + // TODO: check finished programs size_t position = choose_position(); struct term *term = pqueue_pop_at(queue, position); @@ -9,6 +9,22 @@ #include <term.h> #include <map.h> +// doesn't care about ref count +static void term_destroy_head(struct term *term) +{ + term_print(term); + fprintf(stderr, "\n"); + map_delete(map_all_terms(), term); + map_destroy(term->parents); + free(term); +} + +static void term_destroy_parent(void *item) +{ + struct term *term = *(struct term **)item; + term_destroy_head(term); +} + struct term *term_new(term_type_t type, hash_t hash, size_t depth) { struct term *term = malloc(sizeof(*term)); @@ -18,7 +34,8 @@ struct term *term_new(term_type_t type, hash_t hash, size_t depth) term->refs = 1; term->hash = hash; term->depth = depth; - term->parents = hashmap_new(sizeof(struct term *), 0, 0); + term->parents = + hashmap_new(sizeof(struct term *), 0, term_destroy_parent); return term; } @@ -55,12 +72,15 @@ struct term *term_rehash_abs(struct term *head, struct term *term) struct term *match = map_get(map_all_terms(), res); if (match) { // already exists + term_refer_head(match, head->depth); + term_deref_head(head); return match; } else { // create new struct term *new = term_new(ABS, res, head->depth); new->u.abs.term = term; map_set(map_all_terms(), new); map_set(term->parents, new); + term_deref_head(head); return new; } } @@ -77,6 +97,8 @@ struct term *term_rehash_app(struct term *head, struct term *lhs, struct term *match = map_get(map_all_terms(), res); if (match) { // already exists + term_refer_head(match, head->depth); + term_deref(head); return match; } else { // create new struct term *new = term_new(APP, res, head->depth); @@ -85,6 +107,7 @@ struct term *term_rehash_app(struct term *head, struct term *lhs, map_set(map_all_terms(), new); map_set(lhs->parents, new); map_set(rhs->parents, new); + term_deref_head(head); return new; } } @@ -98,25 +121,30 @@ struct term *term_rehash_var(struct term *head, size_t index) struct term *match = map_get(map_all_terms(), res); if (match) { // already exists + term_refer_head(match, head->depth); + term_deref(head); return match; } else { // create new struct term *new = term_new(APP, res, head->depth); new->u.var.index = index; map_set(map_all_terms(), new); + term_deref_head(head); return new; } } struct term *term_rehash(struct term *term) { - if (term->type == ABS) { + if (term->type == ABS) return term_rehash_abs(term, term->u.abs.term); - } else if (term->type == APP) { + + if (term->type == APP) return term_rehash_app(term, term->u.app.lhs, term->u.app.rhs); - } else if (term->type == VAR) { + + if (term->type == VAR) return term_rehash_var(term, term->u.var.index); - } - return term; + + fatal("invalid type %d\n", term->type); } // returns the direct parent @@ -186,12 +214,10 @@ void term_refer(struct term *term, size_t depth) void term_deref_head(struct term *term) { + assert(term->refs); term->refs--; - if (term->refs == 0) { - map_delete(map_all_terms(), term); - map_destroy(term->parents); - free(term); - } + if (!term->refs) + term_destroy_head(term); } void term_deref(struct term *term) |