Skip to content

Commit

Permalink
Merge pull request #497 from katef/sv/move-codegen-callback-metadata-…
Browse files Browse the repository at this point in the history
…args-into-struct

print API: Box end_ids and end_id_count in a struct for callbacks.
  • Loading branch information
katef authored Sep 27, 2024
2 parents 2474c51 + 1295005 commit 0961848
Show file tree
Hide file tree
Showing 27 changed files with 291 additions and 201 deletions.
11 changes: 8 additions & 3 deletions include/fsm/print.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ enum fsm_print_lang {
FSM_PRINT_VMOPS_MAIN
};

struct fsm_state_metadata {
const fsm_end_id_t *end_ids;
size_t end_id_count;
};

/*
* Hooks to override generated code. These give an oportunity to
* emit application-specific constructs, especially based on ids
Expand All @@ -66,19 +71,19 @@ struct fsm_hooks {
void *lang_opaque, void *hook_opaque);

int (*accept)(FILE *, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
void *lang_opaque, void *hook_opaque);

int (*reject)(FILE *, const struct fsm_options *opt,
void *lang_opaque, void *hook_opaque);

int (*comment)(FILE *, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
void *hook_opaque);

/* only called for AMBIG_ERROR; see opt.ambig */
int (*conflict)(FILE *, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
const char *example,
void *hook_opaque);

Expand Down
28 changes: 16 additions & 12 deletions src/libfsm/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ int
print_hook_accept(FILE *f,
const struct fsm_options *opt,
const struct fsm_hooks *hooks,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
int (*default_accept)(FILE *f, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
void *lang_opaque, void *hook_opaque),
void *lang_opaque)
{
Expand All @@ -64,18 +64,18 @@ print_hook_accept(FILE *f,
assert(hooks != NULL);

if (opt->ambig == AMBIG_ERROR) {
assert(count <= 1);
assert(state_metadata->end_id_count <= 1);
}

if (default_accept == NULL) {
assert(lang_opaque == NULL);
}

if (hooks->accept != NULL) {
return hooks->accept(f, opt, ids, count,
return hooks->accept(f, opt, state_metadata,
lang_opaque, hooks->hook_opaque);
} else if (default_accept != NULL) {
return default_accept(f, opt, ids, count,
return default_accept(f, opt, state_metadata,
lang_opaque, hooks->hook_opaque);
}

Expand All @@ -86,21 +86,21 @@ int
print_hook_comment(FILE *f,
const struct fsm_options *opt,
const struct fsm_hooks *hooks,
const fsm_end_id_t *ids, size_t count)
const struct fsm_state_metadata *state_metadata)
{
assert(f != NULL);
assert(opt != NULL);
assert(hooks != NULL);

if (opt->ambig == AMBIG_ERROR) {
assert(count <= 1);
assert(state_metadata->end_id_count <= 1);
}

if (opt->comments && hooks->comment != NULL) {
/* this space is a polyglot */
fprintf(f, " ");

return hooks->comment(f, opt, ids, count,
return hooks->comment(f, opt, state_metadata,
hooks->hook_opaque);
}

Expand Down Expand Up @@ -138,7 +138,7 @@ int
print_hook_conflict(FILE *f,
const struct fsm_options *opt,
const struct fsm_hooks *hooks,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
const char *example)
{
assert(opt != NULL);
Expand All @@ -147,7 +147,7 @@ print_hook_conflict(FILE *f,
/* f may be NULL for FSM_PRINT_NONE */

if (hooks->conflict != NULL) {
return hooks->conflict(f, opt, ids, count,
return hooks->conflict(f, opt, state_metadata,
example,
hooks->hook_opaque);
}
Expand Down Expand Up @@ -211,8 +211,12 @@ print_conflicts(FILE *f, const struct fsm *fsm,
* The conflict hook is called here (rather in the caller),
* because it can be called multiple times, for different states.
*/
struct fsm_state_metadata state_metadata = {
.end_ids = ids,
.end_id_count = count,
};
if (-1 == print_hook_conflict(f, opt, hooks,
ids, count,
&state_metadata,
example))
{
goto error;
Expand Down Expand Up @@ -354,7 +358,7 @@ fsm_print(FILE *f, const struct fsm *fsm,
continue;
}

assert(ir->states[i].count <= 1);
assert(ir->states[i].endids.count <= 1);
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/libfsm/print.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct ir;
struct dfavm_op_ir;
struct ret_list;

#include <fsm/print.h>

int
print_hook_args(FILE *f,
const struct fsm_options *opt,
Expand All @@ -26,17 +28,17 @@ int
print_hook_accept(FILE *f,
const struct fsm_options *opt,
const struct fsm_hooks *hooks,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
int (*default_accept)(FILE *f, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
void *lang_opaque, void *hook_opaque),
void *lang_opaque);

int
print_hook_comment(FILE *f,
const struct fsm_options *opt,
const struct fsm_hooks *hooks,
const fsm_end_id_t *ids, size_t count);
const struct fsm_state_metadata *state_metadata);

int
print_hook_reject(FILE *f,
Expand All @@ -50,7 +52,7 @@ int
print_hook_conflict(FILE *f,
const struct fsm_options *opt,
const struct fsm_hooks *hooks,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
const char *example);

typedef int fsm_print_f(FILE *f,
Expand Down
32 changes: 18 additions & 14 deletions src/libfsm/print/awk.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ cmp_operator(int cmp)

static int
default_accept(FILE *f, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
void *lang_opaque, void *hook_opaque)
{
assert(f != NULL);
Expand All @@ -69,37 +69,37 @@ default_accept(FILE *f, const struct fsm_options *opt,

case AMBIG_ERROR:
// TODO: decide if we deal with this ahead of the call to print or not
if (count > 1) {
if (state_metadata->end_id_count > 1) {
errno = EINVAL;
return -1;
}
fprintf(f, "return %u;", ids[0]);

fprintf(f, "return %u;", state_metadata->end_ids[0]);
break;

case AMBIG_EARLIEST:
/*
* The libfsm api guarentees these ids are unique,
* and only appear once each, and are sorted.
*/
fprintf(f, "return %u;", ids[0]);
fprintf(f, "return %u;", state_metadata->end_ids[0]);
break;

case AMBIG_MULTIPLE:
/* awk can't return an array */
fprintf(f, "return \"");

for (size_t i = 0; i < count; i++) {
fprintf(f, "%u", ids[i]);
for (size_t i = 0; i < state_metadata->end_id_count; i++) {
fprintf(f, "%u", state_metadata->end_ids[i]);

if (i < count - 1) {
if (i < state_metadata->end_id_count - 1) {
fprintf(f, ",");
}
}

fprintf(f, "\"");
break;

default:
assert(!"unreached");
abort();
Expand Down Expand Up @@ -156,17 +156,21 @@ print_end(FILE *f, const struct dfavm_op_ir *op,
case VM_END_FAIL:
return print_hook_reject(f, opt, hooks, default_reject, NULL);

case VM_END_SUCC:
case VM_END_SUCC:;
struct fsm_state_metadata state_metadata = {
.end_ids = op->ret->ids,
.end_id_count = op->ret->count,
};
if (-1 == print_hook_accept(f, opt, hooks,
op->ret->ids, op->ret->count,
&state_metadata,
default_accept,
NULL))
{
return -1;
}

if (-1 == print_hook_comment(f, opt, hooks,
op->ret->ids, op->ret->count))
&state_metadata))
{
return -1;
}
Expand Down
29 changes: 17 additions & 12 deletions src/libfsm/print/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ ir_hasend(const struct ir *ir)
// TODO: centralise vmc/c
static int
print_ids(FILE *f,
enum fsm_ambig ambig, const fsm_end_id_t *ids, size_t count)
enum fsm_ambig ambig, const struct fsm_state_metadata *state_metadata)
{
switch (ambig) {
case AMBIG_NONE:
// TODO: for C99 we'd return bool
fprintf(f, "return 1;");
fprintf(f, "return 1;");
break;

case AMBIG_ERROR:
// TODO: decide if we deal with this ahead of the call to print or not
if (count > 1) {
if (state_metadata->end_id_count > 1) {
errno = EINVAL;
return -1;
}
Expand All @@ -79,7 +79,7 @@ print_ids(FILE *f,
* and only appear once each, and are sorted.
*/
fprintf(f, "{\n");
fprintf(f, "\t\t*id = %u;\n", ids[0]);
fprintf(f, "\t\t*id = %u;\n", state_metadata->end_ids[0]);
fprintf(f, "\t\treturn 1;\n");
fprintf(f, "\t}");
break;
Expand All @@ -94,15 +94,15 @@ print_ids(FILE *f,

fprintf(f, "{\n");
fprintf(f, "\t\tstatic const unsigned a[] = { ");
for (fsm_end_id_t i = 0; i < count; i++) {
fprintf(f, "%u", ids[i]);
if (i + 1 < count) {
for (fsm_end_id_t i = 0; i < state_metadata->end_id_count; i++) {
fprintf(f, "%u", state_metadata->end_ids[i]);
if (i + 1 < state_metadata->end_id_count) {
fprintf(f, ", ");
}
}
fprintf(f, " };\n");
fprintf(f, "\t\t*ids = a;\n");
fprintf(f, "\t\t*count = %zu;\n", count);
fprintf(f, "\t\t*count = %zu;\n", state_metadata->end_id_count);
fprintf(f, "\t\treturn 1;\n");
fprintf(f, "\t}");
break;
Expand All @@ -117,7 +117,7 @@ print_ids(FILE *f,

static int
default_accept(FILE *f, const struct fsm_options *opt,
const fsm_end_id_t *ids, size_t count,
const struct fsm_state_metadata *state_metadata,
void *lang_opaque, void *hook_opaque)
{
assert(f != NULL);
Expand All @@ -127,7 +127,7 @@ default_accept(FILE *f, const struct fsm_options *opt,
(void) lang_opaque;
(void) hook_opaque;

if (-1 == print_ids(f, opt->ambig, ids, count)) {
if (-1 == print_ids(f, opt->ambig, state_metadata)) {
return -1;
}

Expand Down Expand Up @@ -374,16 +374,21 @@ print_endstates(FILE *f,

fprintf(f, "\tcase S%u: ", i);

const struct fsm_state_metadata state_metadata = {
.end_ids = ir->states[i].endids.ids,
.end_id_count = ir->states[i].endids.count,
};

if (-1 == print_hook_accept(f, opt, hooks,
ir->states[i].ids, ir->states[i].count,
&state_metadata,
default_accept,
NULL))
{
return -1;
}

if (-1 == print_hook_comment(f, opt, hooks,
ir->states[i].ids, ir->states[i].count))
&state_metadata))
{
return -1;
}
Expand Down
Loading

0 comments on commit 0961848

Please sign in to comment.