Skip to content

Commit

Permalink
Remove fsm_{get,set,setend,carry}opaque from the API.
Browse files Browse the repository at this point in the history
get and set have been no-ops for several commits, the others are
all unused now. Everything that previously used them has been
switched over to use the end ID API instead, which is more
strongly typed and manages carrying them internally, but still
leaves the meaning of end states being associated with particular
end IDs to the caller.
  • Loading branch information
silentbicycle committed Mar 1, 2021
1 parent f5e5a1f commit 3d532ee
Show file tree
Hide file tree
Showing 14 changed files with 3 additions and 362 deletions.
18 changes: 0 additions & 18 deletions include/fsm/fsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,24 +191,6 @@ fsm_findmode(const struct fsm *fsm, fsm_state_t state, unsigned int *freq);
void
fsm_setend(struct fsm *fsm, fsm_state_t state, int end);

/*
* Set data associated with all end states.
*/
void
fsm_setendopaque(struct fsm *fsm, void *opaque);

/*
* Set data associated with an end state.
*/
void
fsm_setopaque(struct fsm *fsm, fsm_state_t state, void *opaque);

/*
* Get data associated with an end state.
*/
void *
fsm_getopaque(const struct fsm *fsm, fsm_state_t state);

/* Associate a numeric ID with the end states in an fsm.
* This can be used to track which of the original fsms matched
* input when multiple fsms are combined.
Expand Down
4 changes: 0 additions & 4 deletions include/fsm/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ struct fsm_options {
const void *endleaf_opaque);
void *endleaf_opaque;

/* TODO: explain */
void (*carryopaque)(const struct fsm *src_fsm, const fsm_state_t *src_set, size_t n,
struct fsm *dst_fsm, fsm_state_t dst_state);

/* custom allocation functions */
const struct fsm_alloc *alloc;
};
Expand Down
31 changes: 0 additions & 31 deletions src/libfsm/consolidate.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,37 +133,6 @@ fsm_consolidate(struct fsm *src,
if (fsm_isend(src, src_i)) {
fsm_setend(dst, dst_i, 1);
}
} else {
const int is_end = fsm_isend(dst, dst_i);
fsm_state_t prev_i;
fsm_state_t prev_src_id = src->statecount; /* NONE */
fsm_state_t src_set[2];

if (!is_end) {
continue;
}
assert(fsm_isend(src, src_i));

/* Find the previous state that also maps to this
* state, to carry the opaque from it. This could
* become expensive when there are a very high number
* of states, so it may be worth keeping a temporary
* second mapping for just the end states. */
for (prev_i = 0; prev_i < mapping_count; prev_i++) {
if (mapping[prev_i] == dst_i) {
prev_src_id = prev_i;
break;
}
}
assert(prev_src_id < src->statecount);

src_set[0] = prev_src_id;
src_set[1] = src_i;

/* call carryopaque pairwise */
fsm_carryopaque_array(src,
src_set, 2,
dst, dst_i);
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/libfsm/determinise.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,12 @@ fsm_determinise(struct fsm *nfa)
fsm_setend(dfa, m->dfastate, 1);

/*
* Carry through opaque values, if present. This isn't anything to do
* Carry through end IDs, if present. This isn't anything to do
* with the DFA conversion; it's meaningful only to the caller.
*
* The closure may contain non-end states, but at least one state is
* known to have been an end state.
*/
fsm_carryopaque(nfa, ss, dfa, m->dfastate);

if (!fsm_endid_carry(nfa, ss, dfa, m->dfastate)) {
goto cleanup;
}
Expand Down
39 changes: 0 additions & 39 deletions src/libfsm/end.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,42 +40,3 @@ fsm_setend(struct fsm *fsm, fsm_state_t state, int end)
break;
}
}

void
fsm_setendopaque(struct fsm *fsm, void *opaque)
{
fsm_state_t i;

assert(fsm != NULL);

for (i = 0; i < fsm->statecount; i++) {
if (fsm_isend(fsm, i)) {
fsm_setopaque(fsm, i, opaque);
}
}
}

void
fsm_setopaque(struct fsm *fsm, fsm_state_t state, void *opaque)
{
(void) fsm;

assert(fsm != NULL);
assert(state < fsm->statecount);

assert(fsm->states[state].end);
}

void *
fsm_getopaque(const struct fsm *fsm, fsm_state_t state)
{
(void) fsm;

assert(fsm != NULL);
assert(state < fsm->statecount);

assert(fsm->states[state].end);

return NULL;
}

87 changes: 0 additions & 87 deletions src/libfsm/fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,93 +137,6 @@ fsm_move(struct fsm *dst, struct fsm *src)
f_free(src->opt->alloc, src);
}

void
fsm_carryopaque_array(const struct fsm *src_fsm, const fsm_state_t *src_set, size_t n,
struct fsm *dst_fsm, fsm_state_t dst_state)
{
assert(src_fsm != NULL);
assert(src_set != NULL);
assert(n > 0);
assert(dst_fsm != NULL);
assert(dst_state < dst_fsm->statecount);
assert(fsm_isend(dst_fsm, dst_state));
assert(src_fsm->opt == dst_fsm->opt);

/*
* Some states in src_set may be not end states (for example
* from an epsilon closure over a mix of end and non-end states).
* However at least one element is known to be an end state,
* so we assert on that here.
*
* I would filter out the non-end states if there were a convenient
* way to do that without allocating for it. As it is, the caller
* must unfortunately be exposed to a mix.
*/
#ifndef NDEBUG
{
int has_end;
size_t i;

has_end = 0;

for (i = 0; i < n; i++) {
if (fsm_isend(src_fsm, src_set[i])) {
has_end = 1;
break;
}
}

assert(has_end);
}
#endif

if (src_fsm->opt == NULL || src_fsm->opt->carryopaque == NULL) {
return;
}

src_fsm->opt->carryopaque(src_fsm, src_set, n,
dst_fsm, dst_state);
}

void
fsm_carryopaque(const struct fsm *src_fsm, const struct state_set *src_set,
struct fsm *dst_fsm, fsm_state_t dst_state)
{
fsm_state_t src_state;
const fsm_state_t *p;
size_t n;

assert(src_fsm != NULL);
assert(dst_fsm != NULL);
assert(dst_state < dst_fsm->statecount);
assert(fsm_isend(dst_fsm, dst_state));
assert(src_fsm->opt == dst_fsm->opt);

/* TODO: right? */
if (state_set_empty(src_set)) {
return;
}

n = state_set_count(src_set);

if (n == 1) {
/*
* Workaround for singleton sets having a special encoding.
*/
src_state = state_set_only(src_set);
p = &src_state;
} else {
/*
* Our state set is implemented as an array of fsm_state_t.
* Here we're presenting the underlying array directly,
* because the user-facing API doesn't expose the state set ADT.
*/
p = state_set_array(src_set);
}

fsm_carryopaque_array(src_fsm, p, n, dst_fsm, dst_state);
}

unsigned int
fsm_countstates(const struct fsm *fsm)
{
Expand Down
10 changes: 1 addition & 9 deletions src/libfsm/glushkovise.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,24 +158,16 @@ fsm_glushkovise(struct fsm *nfa)
}

/*
* Carry through opaque values, if present. This isn't anything to do
* Carry through end IDs, if present. This isn't anything to do
* with the NFA conversion; it's meaningful only to the caller.
*
* The closure may contain non-end states, but at least one state is
* known to have been an end state.
*/
fsm_carryopaque(nfa, eclosures[s], nfa, s);

if (!carry_endids(nfa, eclosures[s], s)) {
free_closure_sets(sclosures);
goto error;
}

#if 0
if (!fsm_endid_carry(nfa, eclosures[s], nfa, s)) {
goto error;
}
#endif
}

if (!remap_capture_actions(nfa, eclosures)) {
Expand Down
5 changes: 0 additions & 5 deletions src/libfsm/libfsm.syms
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ fsm_subgraph_duplicate
fsm_setstart
fsm_getstart
fsm_setend
fsm_setendopaque
fsm_setopaque
fsm_getopaque

fsm_getendidcount
fsm_getendids
Expand All @@ -96,8 +93,6 @@ fsm_minimise
fsm_concat
fsm_subtract

fsm_carryopaque

fsm_empty
fsm_equal
fsm_shortest
Expand Down
2 changes: 0 additions & 2 deletions src/libfsm/reverse.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ fsm_reverse(struct fsm *fsm)
fsm_setend(fsm, end, 1);

/* TODO: if we keep a fsm-wide endset, we can use it verbatim here */
fsm_carryopaque(fsm, endset, fsm, end);
}

for (state_set_reset(endset, &it); state_set_next(&it, &s); ) {
Expand All @@ -261,7 +260,6 @@ fsm_reverse(struct fsm *fsm)
if (state_set_count(endset) > 1 && !hasepsilons && state_set_has(fsm, endset, fsm_isend)) {
assert(!fsm_isend(fsm, start));
fsm_setend(fsm, start, 1);
fsm_carryopaque(fsm, endset, fsm, start);
}

{
Expand Down
31 changes: 1 addition & 30 deletions src/libfsm/walk2.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ walk2_comb_state(struct fsm *dst_fsm, int is_end,
fsm_state_t state_ids[2];
size_t count;
unsigned endcount;
struct fsm tmp;

assert(dst_fsm != NULL);
assert(comb != NULL);
Expand All @@ -212,7 +211,7 @@ walk2_comb_state(struct fsm *dst_fsm, int is_end,

fsm_setend(dst_fsm, *comb, 1);

if (dst_fsm->opt == NULL || dst_fsm->opt->carryopaque == NULL) {
if (dst_fsm->opt == NULL) {
return 1;
}

Expand All @@ -233,34 +232,6 @@ walk2_comb_state(struct fsm *dst_fsm, int is_end,
endcount += fsm_isend(fsm_b, b);
}

if (count == 0) {
return 1;
}

/*
* Using an array here is slightly cheesed, but it avoids
* constructing a set just to pass these two states to
* the .carryopaque callback.
*
* Unrelated to that, the .carryopaque callback needs a
* src_fsm to pass for calls on those states. But because
* our two states may come from different FSMs, there's no
* single correct src_fsm to pass. So we workaround that
* by constructing a temporary FSM just to hold them.
*
* This is done entirely in automatic storage, because
* it's only needed briefly and is limited to two states.
*/

tmp.states = states;
tmp.statealloc = count;
tmp.statecount = count;
tmp.endcount = endcount;
tmp.hasstart = 0;
tmp.opt = dst_fsm->opt;

fsm_carryopaque_array(&tmp, state_ids, count, dst_fsm, *comb);

return 1;
}

Expand Down

0 comments on commit 3d532ee

Please sign in to comment.