aboutsummaryrefslogtreecommitdiff
path: root/types.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-12 13:05:08 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-12 13:05:08 -0400
commit56a4d13975f443fc9e81f0acbb1a896122aa5857 (patch)
tree09ea8a4d14ff7e3d849f9ed3cb3b76b81094fff9 /types.c
parent43f4f3610e5258afbfb9e313c989e1e52f477c38 (diff)
Automatic promotion to single-argument enum tags with a unique type
Diffstat (limited to 'types.c')
-rw-r--r--types.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/types.c b/types.c
index d7b517d3..d70346a2 100644
--- a/types.c
+++ b/types.c
@@ -276,6 +276,25 @@ PUREFUNC bool has_stack_memory(type_t *t)
}
}
+PUREFUNC const char *enum_single_value_tag(type_t *enum_type, type_t *t)
+{
+ const char *found = NULL;
+ for (tag_t *tag = Match(enum_type, EnumType)->tags; tag; tag = tag->next) {
+ if (tag->type->tag != StructType) continue;
+ auto s = Match(tag->type, StructType);
+ if (!s->fields || s->fields->next || !s->fields->type)
+ continue;
+
+ if (can_promote(t, s->fields->type)) {
+ if (found) // Ambiguous case, multiple matches
+ return NULL;
+ found = tag->name;
+ // Continue searching to check for ambiguous cases
+ }
+ }
+ return found;
+}
+
PUREFUNC bool can_promote(type_t *actual, type_t *needed)
{
// No promotion necessary:
@@ -296,6 +315,9 @@ PUREFUNC bool can_promote(type_t *actual, type_t *needed)
return cmp == NUM_PRECISION_EQUAL || cmp == NUM_PRECISION_LESS;
}
+ if (needed->tag == EnumType)
+ return (enum_single_value_tag(needed, actual) != NULL);
+
// Text to C String
if (actual->tag == TextType && !Match(actual, TextType)->lang && needed->tag == CStringType)
return true;