-
-
Save kragen/256555 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
typedef int bool; | |
enum { true = 1, false = 0 }; | |
/* dummy definitions to make it compile */ | |
enum symbol { SYM_DONTCARE, SYM_ANY, SYM_OTHER }; | |
enum kind { KIND_DONTCARE, KIND_NODE, KIND_OTHER }; | |
struct thing { enum symbol type; enum kind kind; }; | |
int is_kind(enum symbol type, enum kind kind) { | |
return true; | |
} | |
#define DEBUGMSG(x) printf x | |
/* end of dummy definitions */ | |
#ifndef DEBUGMSG | |
#define DEBUGMSG(x) 0 | |
#endif | |
struct Case { | |
enum symbol s1_type; | |
enum kind s1_kind; | |
enum symbol s2_type; | |
enum kind s2_kind; | |
bool kinds_equal; | |
bool types_equal; | |
bool s1_type_is_s2_kind; | |
bool s2_type_is_s1_kind; | |
} table[] = { | |
/* This is a straightforward transliteration of Gian's code from <http://gist.github.com/255934>. */ | |
/* It contains redundant tests. */ | |
{ .s1_type = SYM_ANY, .s1_kind = KIND_NODE, .s2_type = SYM_ANY, .s2_kind = KIND_NODE }, /* 1 */ | |
{ .s1_type = SYM_ANY, .s1_kind = KIND_NODE, .s2_type = SYM_ANY, .s2_kind = KIND_OTHER, .kinds_equal = true }, /* this is a bug; it is in the original code */ | |
{ .s1_type = SYM_ANY, .s1_kind = KIND_NODE, .s2_type = SYM_OTHER }, | |
{ .s1_type = SYM_ANY, .s1_kind = KIND_OTHER, .s2_type = SYM_ANY, .kinds_equal = true }, | |
{ .s1_type = SYM_ANY, .s1_kind = KIND_OTHER, .s2_type = SYM_OTHER, .s2_type_is_s1_kind = true }, | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_NODE, .s2_type = SYM_ANY, .s2_kind = KIND_NODE }, /* 6 */ | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_NODE, .s2_type = SYM_ANY, .s2_kind = KIND_OTHER, .s1_type_is_s2_kind = true }, | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_NODE, .s2_type = SYM_OTHER, .s2_kind = KIND_NODE, .types_equal = true }, | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_NODE, .s2_type = SYM_OTHER, .s2_kind = KIND_OTHER, .types_equal = true, .s1_type_is_s2_kind = true }, | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_OTHER, .s2_type = SYM_ANY, .s2_kind = KIND_NODE }, | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_OTHER, .s2_type = SYM_ANY, .s1_type_is_s2_kind = true }, /* 11 */ | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_OTHER, .s2_type = SYM_OTHER, .s2_kind = KIND_NODE, .types_equal = true, .s2_type_is_s1_kind = true }, | |
{ .s1_type = SYM_OTHER, .s1_kind = KIND_OTHER, .s2_type = SYM_OTHER, .s2_kind = KIND_OTHER, .types_equal = true, .s1_type_is_s2_kind = true, .s2_type_is_s1_kind = true }, /* 13 */ | |
}; | |
/* The SYM_ANY in the first case is redundant, and I suspect that a | |
lot of the SYM_OTHER and KIND_OTHER items are redundant too --- in | |
the sense that in no case they cover would changing a type from | |
something to SYM_ANY, or changing a kind from something to | |
KIND_NODE, would cause the code to return FALSE where it had | |
previously returned TRUE. I suspect that removing the redundancy | |
would make the table considerably more compact and readable. | |
*/ | |
int matches(struct Case *c, struct thing s1, struct thing s2) { | |
DEBUGMSG(("%d %d %d %d %d %d %d %d\n", | |
c->s1_type, | |
c->s1_kind, | |
c->s2_type, | |
c->s2_kind, | |
c->kinds_equal, | |
c->types_equal, | |
c->s1_type_is_s2_kind, | |
c->s2_type_is_s1_kind)); | |
if ((c->s1_type == SYM_ANY ) && (s1.type != SYM_ANY)) return false; | |
if ((c->s1_type == SYM_OTHER) && (s1.type == SYM_ANY)) return false; | |
if ((c->s1_kind == KIND_NODE ) && (s1.kind != KIND_NODE)) return false; | |
if ((c->s1_kind == KIND_OTHER) && (s1.kind == KIND_NODE)) return false; | |
if ((c->s2_type == SYM_ANY ) && (s2.type != SYM_ANY)) return false; | |
if ((c->s2_type == SYM_OTHER) && (s2.type == SYM_ANY)) return false; | |
if ((c->s2_kind == KIND_NODE ) && (s2.kind != KIND_NODE)) return false; | |
if ((c->s2_kind == KIND_OTHER) && (s2.kind == KIND_NODE)) return false; | |
if (c->kinds_equal && (s1.kind != s2.kind)) return false; | |
if (c->types_equal && (s1.type != s2.type)) return false; | |
if (c->s1_type_is_s2_kind && !is_kind(s1.type, s2.kind)) return false; | |
if (c->s2_type_is_s1_kind && !is_kind(s2.type, s1.kind)) return false; | |
return true; | |
} | |
int determine(struct thing s1, struct thing s2) { | |
for (int ii = 0; ii < sizeof(table)/sizeof(table[0]); ii++) { | |
if (matches(&table[ii], s1, s2)) return true; | |
} | |
return false; | |
} | |
int main() { | |
struct thing x; | |
return determine(x, x); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment