diff --git a/build.bat b/build.bat index 646fc42..03d76e0 100644 --- a/build.bat +++ b/build.bat @@ -68,6 +68,7 @@ popd echo. echo ~~~ Running Namespace Type Versioning Sample ~~~ pushd build +if not exist ..\samples\namespaced_types\generated mkdir ..\samples\namespaced_types\generated namespaced_types.exe ..\samples\namespaced_types\spec.md ..\samples\namespaced_types\generated\converter.c cl %compile_flags% ..\samples\namespaced_types\conversion_test.c conversion_test.exe diff --git a/docs/md_docs.md b/docs/md_docs.md index 0e52812..460fb41 100644 --- a/docs/md_docs.md +++ b/docs/md_docs.md @@ -100,7 +100,7 @@ MAX, }; -@doc("Flags put on nodes to indicate extra information about specific details about the strings that were parsed to create the node.") +@doc("Flags put on nodes to indicate extra details about the strings that were parsed to create the node.") @see(MD_Node) @see(MD_TokenKind) @prefix(MD_NodeFlag) @@ -211,6 +211,9 @@ //~ String-To-Node table @doc("Controls the behavior of routines that write into maps when the written key was already in the map.") +@see(MD_Map) +@see(MD_StringMap_Insert) +@see(MD_PtrMap_Insert) @enum MD_MapCollisionRule: { @doc("When the key written was already in the map, a new key value pair is attached to the same chain always. Leaving multiple values associated to the same key.") Chain, @@ -218,13 +221,20 @@ Overwrite, } +@doc("A slot containing one (key,value) pair in a MD_Map.") +@see(MD_Map) @struct MD_MapSlot: { + @doc("The next slot in the same bucket of the MD_Map") next: *MD_MapSlot, + @doc("For slots with a string key, the hash of the key.") hash: MD_u64, + @doc("The key for slots with a pointer key.") key: *void; + @doc("The value part of the pair.") value: *void; }; +@doc("The map is a chained hash table data structure. Data written to the map is a key-value pair. The key of a pair may either be a pointer, or a string. Both types may be mixed inside a single map. Keys stored with one type never match keys of the other type. The values of the pairs are pointers.") @struct MD_Map: { table_size: MD_u64, table: **MD_MapSlot, @@ -721,15 +731,15 @@ }; //////////////////////////////// -//~ String-To-Node-List Table +//~ String-To-Pointer Table -@func MD_Map_Lookup: { +@func MD_StringMap_Lookup: { table: *MD_Map, string: MD_String8, return: *MD_MapSlot, }; -@func MD_Map_Insert: { +@func MD_StringMap_Insert: { table: *MD_Map, collision_rule: MD_MapCollisionRule, string: MD_String8, @@ -737,6 +747,23 @@ return: MD_b32, }; +//////////////////////////////// +//~ Pointer-To-Pointer Table + +@func MD_PtrMap_Lookup: { + table: *MD_Map, + key: *void, + return: *MD_MapSlot, +}; + +@func MD_PtrMap_Insert: { + table: *MD_Map, + collision_rule: MD_MapCollisionRule, + key: *void, + node: *MD_Node, + return: MD_b32, +}; + //////////////////////////////// //~ Parsing diff --git a/samples/namespaced_types/generated/converter.c b/samples/namespaced_types/generated/converter.c new file mode 100644 index 0000000..8e3e9de --- /dev/null +++ b/samples/namespaced_types/generated/converter.c @@ -0,0 +1,131 @@ +// V1 +typedef enum +{ + v1_EntryKind_A, + v1_EntryKind_B, + v1_EntryKind_C, + v1_EntryKind_E, +} v1_EntryKind; + +typedef enum +{ + v1_EntryFlag_A = (1<<0), + v1_EntryFlag_B = (1<<1), + v1_EntryFlag_C = (1<<2), +} v1_EntryFlags; + +typedef union v1_Color v1_Color; +union v1_Color +{ + struct + { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + } components; + uint8_t raw[4]; +}; + +typedef struct v1_Entry v1_Entry; +struct v1_Entry +{ + uint16_t to_remove; + v1_EntryKind kind; + v1_EntryFlags flags; + v1_Color color; + struct + { + float x; + float y; + } p; +}; + +// V2 +typedef enum +{ + EntryKind_A, + EntryKind_B, + EntryKind_B2, + EntryKind_C, +} EntryKind; + +typedef enum +{ + EntryFlag_B = (1<<0), + EntryFlag_C = (1<<1), + EntryFlag_D = (1<<2), +} EntryFlags; + +typedef union Color Color; +union Color +{ + struct + { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + } components; + uint8_t raw[4]; +}; + +typedef struct Entry Entry; +struct Entry +{ + EntryKind kind; + Color color; + struct + { + float x; + float y; + float z; + } p; + EntryFlags flags; +}; + +// V1->V2 +static EntryKind EntryKindFromV1(v1_EntryKind v) +{ + EntryKind result = 0; + switch(v) + { + case v1_EntryKind_A: result = EntryKind_A; break; + case v1_EntryKind_B: result = EntryKind_B; break; + case v1_EntryKind_C: result = EntryKind_C; break; + case v1_EntryKind_E: assert(!"Enumerand v1_EntryKind_E is no longer allowed\n"); + default: assert(!"Illegal value for enum v1_EntryKind\n"); break; + } + return result; +} + +static EntryFlags EntryFlagsFromV1(v1_EntryFlags v) +{ + EntryFlags result = 0; + if(v & v1_EntryFlag_A) assert(!"Flag v1_A is no longer allowed\n"); + if(v & v1_EntryFlag_B) result |= EntryFlag_B; + if(v & v1_EntryFlag_C) result |= EntryFlag_C; + return result; +} + +static Color ColorFromV1(v1_Color v) +{ + Color result = {0}; + result.components.r = v.components.r; + result.components.g = v.components.g; + result.components.b = v.components.b; + result.components.a = v.components.a; + return result; +} + +static Entry EntryFromV1(v1_Entry v) +{ + Entry result = {0}; + result.kind = EntryKindFromV1(v.kind); + result.color = ColorFromV1(v.color); + result.p.x = v.p.x; + result.p.y = v.p.y; + result.flags = EntryFlagsFromV1(v.flags); + return result; +} +