diff --git a/examples/type_metadata/type_metadata.c b/examples/type_metadata/type_metadata.c index 554806f..948758f 100644 --- a/examples/type_metadata/type_metadata.c +++ b/examples/type_metadata/type_metadata.c @@ -31,10 +31,16 @@ struct TypeInfo TypeKind kind; MD_Node *node; - // struct member list + // member list struct TypeMember *first_member; struct TypeMember *last_member; int member_count; + + // enumerant list + struct TypeEnumerant *first_enumerant; + struct TypeEnumerant *last_enumerant; + int enumerant_count; + }; typedef struct TypeMember TypeMember; @@ -45,6 +51,14 @@ struct TypeMember TypeInfo *type; }; +typedef struct TypeEnumerant TypeEnumerant; +struct TypeEnumerant +{ + TypeEnumerant *next; + MD_Node *node; + int value; +}; + typedef struct MapInfo MapInfo; struct MapInfo { @@ -161,13 +175,14 @@ main(int argc, char **argv) } } - // build struct member lists + // build member lists for (TypeInfo *type = first_type; type != 0; type = type->next) { if (type->kind == TypeKind_Struct) { + // build the list MD_b32 got_list = 1; TypeMember *first_member = 0; TypeMember *last_member = 0; @@ -207,6 +222,8 @@ main(int argc, char **argv) { TypeInfo *type_info = (TypeInfo*)type_info_slot->val; + // TODO(allen): handle the array tag + TypeMember *member = MD_PushArray(arena, TypeMember, 1); member->node = member_node; member->type = type_info; @@ -217,6 +234,7 @@ main(int argc, char **argv) skip_member:; } + // save the list if (got_list) { type->first_member = first_member; @@ -226,6 +244,71 @@ main(int argc, char **argv) } } + // build enumerant lists + for (TypeInfo *type = first_type; + type != 0; + type = type->next) + { + if (type->kind == TypeKind_Enum) + { + // build the list + MD_b32 got_list = 1; + TypeEnumerant *first_enumerant = 0; + TypeEnumerant *last_enumerant = 0; + int enumerant_count = 0; + + int next_implicit_value = 0; + + MD_Node *type_root_node = type->node; + for (MD_EachNode(enumerant_node, type_root_node->first_child)) + { + MD_Node *value_node = enumerant_node->first_child; + int value = 0; + + // missing value node? + if (MD_NodeIsNil(value_node)) + { + value = next_implicit_value; + next_implicit_value += 1; + } + + // has value node + else + { + MD_String8 value_string = value_node->string; + if (!MD_StringIsCStyleInt(value_string)) + { + got_list = 0; + goto skip_enumerant; + } + value = (int)MD_CStyleIntFromString(value_string); + } + + // set next implicit value + next_implicit_value = value + 1; + + // save enumerant + if (got_list) + { + TypeEnumerant *enumerant = MD_PushArray(arena, TypeEnumerant, 1); + enumerant->node = enumerant_node; + enumerant->value = value; + MD_QueuePush(first_enumerant, last_enumerant, enumerant); + enumerant_count += 1; + } + + skip_enumerant:; + } + + // save the list + if (got_list) + { + type->first_enumerant = first_enumerant; + type->last_enumerant = last_enumerant; + type->enumerant_count = enumerant_count; + } + } + } // TODO check types & build member lists // TODO check maps & build case lists @@ -257,6 +340,15 @@ main(int argc, char **argv) MD_S8VArg(member->node->string), MD_S8VArg(member->type->node->string)); } + + // print enumerant lists + for (TypeEnumerant *enumerant = type->first_enumerant; + enumerant != 0; + enumerant = enumerant->next){ + printf(" %.*s: %d\n", + MD_S8VArg(enumerant->node->string), + enumerant->value); + } } for (MapInfo *map = first_map; diff --git a/examples/type_metadata/types.mdesk b/examples/type_metadata/types.mdesk index 5d3aff6..7e42765 100644 --- a/examples/type_metadata/types.mdesk +++ b/examples/type_metadata/types.mdesk @@ -32,9 +32,9 @@ RoundedPolygon: @type(enum: U32) Shape: { - Circle: 1, - Segment: 2, - Polygon: 3, + Circle: 1, + Segment, + Polygon, } @map(Shape -> `$Type`; complete) diff --git a/source/md.c b/source/md.c index 78efe81..c881154 100644 --- a/source/md.c +++ b/source/md.c @@ -1500,21 +1500,99 @@ MD_S8ChopWhitespace(MD_String8 string) //~ Numeric Strings +MD_GLOBAL MD_u8 md_char_to_value[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +}; + +MD_GLOBAL MD_u8 md_char_is_integer[] = { + 0,0,0,0,0,0,1,1, + 1,0,0,0,1,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, +}; + +MD_FUNCTION MD_b32 +MD_StringIsU64(MD_String8 string, MD_u32 radix) +{ + MD_b32 result = 0; + if (string.size > 0) + { + result = 1; + for (MD_u8 *ptr = string.str, *opl = string.str + string.size; + ptr < opl; + ptr += 1) + { + MD_u8 c = *ptr; + if (!md_char_is_integer[c >> 3]) + { + result = 0; + break; + } + if (md_char_to_value[(c - 0x30)&0x1F] >= radix) + { + result = 0; + break; + } + } + } + return(result); +} + +MD_FUNCTION MD_b32 +MD_StringIsCStyleInt(MD_String8 string) +{ + MD_u8 *ptr = string.str; + MD_u8 *opl = string.str + string.size; + + // consume sign + for (;ptr < opl && (*ptr == '+' || *ptr == '-'); ptr += 1); + + // radix from prefix + MD_u64 radix = 10; + if (ptr < opl) + { + MD_u8 c0 = *ptr; + if (c0 == '0') + { + ptr += 1; + radix = 8; + if (ptr < opl) + { + MD_u8 c1 = *ptr; + if (c1 == 'x') + { + ptr += 1; + radix = 0x10; + } + else if (c1 == 'b') + { + ptr += 1; + radix = 2; + } + } + } + } + + // check integer "digits" + MD_String8 digits_substr = MD_S8Range(ptr, opl); + MD_b32 result = MD_StringIsU64(digits_substr, radix); + + return(result); +} + MD_FUNCTION MD_u64 MD_U64FromString(MD_String8 string, MD_u32 radix) { MD_Assert(2 <= radix && radix <= 16); - static MD_u8 char_to_value[] = { - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - }; MD_u64 value = 0; - for (MD_u64 i = 0; i < string.size; i += 1){ + for (MD_u64 i = 0; i < string.size; i += 1) + { value *= radix; MD_u8 c = string.str[i]; - value += char_to_value[(c - 0x30)&0x1F]; + value += md_char_to_value[(c - 0x30)&0x1F]; } return(value); } @@ -1526,31 +1604,39 @@ MD_CStyleIntFromString(MD_String8 string) // consume sign MD_i64 sign = +1; - if (p < string.size){ + if (p < string.size) + { MD_u8 c = string.str[p]; - if (c == '-'){ + if (c == '-') + { sign = -1; p += 1; } - else if (c == '+'){ + else if (c == '+') + { p += 1; } } // radix from prefix MD_u64 radix = 10; - if (p < string.size){ + if (p < string.size) + { MD_u8 c0 = string.str[p]; - if (c0 == '0'){ + if (c0 == '0') + { p += 1; radix = 8; - if (p < string.size){ + if (p < string.size) + { MD_u8 c1 = string.str[p]; - if (c1 == 'x'){ + if (c1 == 'x') + { p += 1; radix = 16; } - else if (c1 == 'b'){ + else if (c1 == 'b') + { p += 1; radix = 2; } @@ -1572,7 +1658,8 @@ MD_F64FromString(MD_String8 string) { char str[64]; MD_u64 str_size = string.size; - if (str_size > sizeof(str) - 1){ + if (str_size > sizeof(str) - 1) + { str_size = sizeof(str) - 1; } MD_MemoryCopy(str, string.str, str_size); diff --git a/source/md.h b/source/md.h index ab42d2f..e26c0db 100644 --- a/source/md.h +++ b/source/md.h @@ -1005,6 +1005,9 @@ MD_FUNCTION MD_String8 MD_S8ChopWhitespace(MD_String8 string); //~ Numeric Strings +MD_FUNCTION MD_b32 MD_StringIsU64(MD_String8 string, MD_u32 radix); +MD_FUNCTION MD_b32 MD_StringIsCStyleInt(MD_String8 string); + MD_FUNCTION MD_u64 MD_U64FromString(MD_String8 string, MD_u32 radix); MD_FUNCTION MD_i64 MD_CStyleIntFromString(MD_String8 string); MD_FUNCTION MD_f64 MD_F64FromString(MD_String8 string);