mirror of
https://github.com/Ed94/metadesk.git
synced 2026-08-06 23:58:48 +00:00
[examples] progress on type metadata commentary
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:874
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:914
|
||||||
TypeInfoMember Circle_members[2] = {
|
TypeInfoMember Circle_members[2] = {
|
||||||
{"r", 1, -1, &F32_type_info},
|
{"r", 1, -1, &F32_type_info},
|
||||||
{"pos", 3, -1, &V2F32_type_info},
|
{"pos", 3, -1, &V2F32_type_info},
|
||||||
@@ -14,14 +14,14 @@ TypeInfoMember RoundedPolygon_members[3] = {
|
|||||||
{"p", 1, 1, &V2F32_type_info},
|
{"p", 1, 1, &V2F32_type_info},
|
||||||
};
|
};
|
||||||
|
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:913
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:953
|
||||||
TypeInfoEnumerant Shape_members[3] = {
|
TypeInfoEnumerant Shape_members[3] = {
|
||||||
{"Circle", 6, 1},
|
{"Circle", 6, 1},
|
||||||
{"Segment", 7, 2},
|
{"Segment", 7, 2},
|
||||||
{"Polygon", 7, 3},
|
{"Polygon", 7, 3},
|
||||||
};
|
};
|
||||||
|
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:949
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:989
|
||||||
TypeInfo U32_type_info = {TypeKind_Basic, "U32", 3, 4, 0, 0};
|
TypeInfo U32_type_info = {TypeKind_Basic, "U32", 3, 4, 0, 0};
|
||||||
TypeInfo F32_type_info = {TypeKind_Basic, "F32", 3, 4, 0, 0};
|
TypeInfo F32_type_info = {TypeKind_Basic, "F32", 3, 4, 0, 0};
|
||||||
TypeInfo V2F32_type_info = {TypeKind_Basic, "V2F32", 5, 8, 0, 0};
|
TypeInfo V2F32_type_info = {TypeKind_Basic, "V2F32", 5, 8, 0, 0};
|
||||||
@@ -30,7 +30,7 @@ TypeInfo RoundedSegment_type_info = {TypeKind_Struct, "RoundedSegment", 14, 3, R
|
|||||||
TypeInfo RoundedPolygon_type_info = {TypeKind_Struct, "RoundedPolygon", 14, 3, RoundedPolygon_members, 0};
|
TypeInfo RoundedPolygon_type_info = {TypeKind_Struct, "RoundedPolygon", 14, 3, RoundedPolygon_members, 0};
|
||||||
TypeInfo Shape_type_info = {TypeKind_Enum, "Shape", 5, 3, Shape_members, &U32_type_info};
|
TypeInfo Shape_type_info = {TypeKind_Enum, "Shape", 5, 3, Shape_members, &U32_type_info};
|
||||||
|
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:1009
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:1049
|
||||||
TypeInfo*
|
TypeInfo*
|
||||||
type_info_from_shape(Shape v)
|
type_info_from_shape(Shape v)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#if !defined(META_TYPES_H)
|
#if !defined(META_TYPES_H)
|
||||||
#define META_TYPES_H
|
#define META_TYPES_H
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:751
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:791
|
||||||
typedef struct Circle Circle;
|
typedef struct Circle Circle;
|
||||||
struct Circle
|
struct Circle
|
||||||
{
|
{
|
||||||
@@ -29,11 +29,11 @@ Shape_Segment = 2,
|
|||||||
Shape_Polygon = 3,
|
Shape_Polygon = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:835
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:875
|
||||||
TypeInfo* type_info_from_shape(Shape v);
|
TypeInfo* type_info_from_shape(Shape v);
|
||||||
U32 max_slot_from_shape(Shape v);
|
U32 max_slot_from_shape(Shape v);
|
||||||
|
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:858
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:898
|
||||||
extern TypeInfo U32_type_info;
|
extern TypeInfo U32_type_info;
|
||||||
extern TypeInfo F32_type_info;
|
extern TypeInfo F32_type_info;
|
||||||
extern TypeInfo V2F32_type_info;
|
extern TypeInfo V2F32_type_info;
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ U8 raw_buffer[] = {
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int indent){
|
print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int indent)
|
||||||
|
{
|
||||||
static char spaces[] =
|
static char spaces[] =
|
||||||
" ";
|
" ";
|
||||||
|
|
||||||
@@ -108,20 +109,16 @@ print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int inde
|
|||||||
// decode single members
|
// decode single members
|
||||||
if (member->array_count_member_index == -1)
|
if (member->array_count_member_index == -1)
|
||||||
{
|
{
|
||||||
// save the offset of this member for later
|
if (member_type_info == &U32_type_info && *ptr_inout + 4 <= opl)
|
||||||
U8 *ptr_og = *ptr_inout;
|
{
|
||||||
// decode this member
|
member_value_memory[i] = *(U32*)*ptr_inout;
|
||||||
|
}
|
||||||
fprintf(stdout, "%.*s%.*s: ", indent, spaces, member->name_length, member->name);
|
fprintf(stdout, "%.*s%.*s: ", indent, spaces, member->name_length, member->name);
|
||||||
if (!print_data_from_type_info(ptr_inout, opl, member_type_info, indent + 1))
|
if (!print_data_from_type_info(ptr_inout, opl, member_type_info, indent + 1))
|
||||||
{
|
{
|
||||||
result = 0;
|
result = 0;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
// if we see a U32 we want to remember it in case it's an array count
|
|
||||||
if (member_type_info == &U32_type_info)
|
|
||||||
{
|
|
||||||
member_value_memory[i] = *(U32*)ptr_og;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode arrays
|
// decode arrays
|
||||||
@@ -176,13 +173,14 @@ print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int inde
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// decode the raw buffer
|
// decode the raw buffer of shape data
|
||||||
U8 *ptr = raw_buffer;
|
U8 *ptr = raw_buffer;
|
||||||
U8 *opl = ptr + sizeof(raw_buffer);
|
U8 *opl = ptr + sizeof(raw_buffer);
|
||||||
for (;ptr < opl;)
|
for (;ptr < opl;)
|
||||||
{
|
{
|
||||||
// decode a shape discriminator
|
// decode a shape discriminator
|
||||||
if (ptr + sizeof(Shape) > opl){
|
if (ptr + sizeof(Shape) > opl)
|
||||||
|
{
|
||||||
fprintf(stdout, "Could not decode shape discriminator\n");
|
fprintf(stdout, "Could not decode shape discriminator\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -191,7 +189,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
// get type info
|
// get type info
|
||||||
TypeInfo *type_info = type_info_from_shape(shape);
|
TypeInfo *type_info = type_info_from_shape(shape);
|
||||||
if (type_info == 0){
|
if (type_info == 0)
|
||||||
|
{
|
||||||
fprintf(stdout, "Unrecognized shape discriminator\n");
|
fprintf(stdout, "Unrecognized shape discriminator\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,18 @@ static MD_Arena *arena = 0;
|
|||||||
FILE *error_file = 0;
|
FILE *error_file = 0;
|
||||||
|
|
||||||
// node maps
|
// node maps
|
||||||
|
|
||||||
|
// @notes As we analyze the Metadesk tree we create more data. In this example
|
||||||
|
// the new data is stored in two major types GEN_TypeInfo and GEN_MapInfo.
|
||||||
|
// We form a list for each type of these "processed" types holds a pointer
|
||||||
|
// back to the original MD_Node that generated it, and room for information
|
||||||
|
// that will be equiped to the "processed" type in later stages of analysis.
|
||||||
|
// We also use the MD_Map helper to create a string -> pointer mapping so that
|
||||||
|
// we can look up the "processed" info pointers by name after the initial
|
||||||
|
// gather stage.
|
||||||
|
//
|
||||||
|
// TODO notes on managing output files.
|
||||||
|
|
||||||
GEN_TypeInfo *first_type = 0;
|
GEN_TypeInfo *first_type = 0;
|
||||||
GEN_TypeInfo *last_type = 0;
|
GEN_TypeInfo *last_type = 0;
|
||||||
MD_Map type_map = {0};
|
MD_Map type_map = {0};
|
||||||
@@ -77,6 +89,12 @@ GEN_TypeInfo*
|
|||||||
gen_resolve_type_info_from_string(MD_String8 name)
|
gen_resolve_type_info_from_string(MD_String8 name)
|
||||||
{
|
{
|
||||||
GEN_TypeInfo *result = 0;
|
GEN_TypeInfo *result = 0;
|
||||||
|
// @notes The MD_Map helper is a "flexibly" typed hash table. It's keys can
|
||||||
|
// be a mix of strings and pointers. Here MD_MapKeyStr(name) is making the
|
||||||
|
// `name` string into a key for the map. The lookup function returns a
|
||||||
|
// "map slot" because the map is not restricted to storing just one value
|
||||||
|
// per key, if we were using it that way we could use MD_MapScan to
|
||||||
|
// iterate through the map slots.
|
||||||
MD_MapSlot *slot = MD_MapLookup(&type_map, MD_MapKeyStr(name));
|
MD_MapSlot *slot = MD_MapLookup(&type_map, MD_MapKeyStr(name));
|
||||||
if (slot != 0)
|
if (slot != 0)
|
||||||
{
|
{
|
||||||
@@ -136,6 +154,15 @@ gen_map_case_from_enumerant(GEN_MapInfo *map, GEN_TypeEnumerant *enumerant)
|
|||||||
|
|
||||||
//~ analyzers /////////////////////////////////////////////////////////////////
|
//~ analyzers /////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// @notes The first stage of processing is to loop over the top level nodes
|
||||||
|
// from each parse. We are using the tags `@type` and `@map` to mark the nodes
|
||||||
|
// that this generator will process. Whenever we see one of those tags we
|
||||||
|
// create a GEN_TypeInfo or GEN_MapInfo to gather up information from the
|
||||||
|
// stages of analysis, and we insert the new info pointer into the appropriate
|
||||||
|
// map. On the types we do a little bit of the analysis right in this function
|
||||||
|
// to figure out which "type kind" it is, this lets us avoid ever having info
|
||||||
|
// where the kind field is not one of the expected values.
|
||||||
|
|
||||||
void
|
void
|
||||||
gen_gather_types_and_maps(MD_Node *list)
|
gen_gather_types_and_maps(MD_Node *list)
|
||||||
{
|
{
|
||||||
@@ -149,6 +176,8 @@ gen_gather_types_and_maps(MD_Node *list)
|
|||||||
|
|
||||||
if (!MD_NodeIsNil(type_tag))
|
if (!MD_NodeIsNil(type_tag))
|
||||||
{
|
{
|
||||||
|
// TODO(allen): check for duplicates
|
||||||
|
|
||||||
GEN_TypeKind kind = GEN_TypeKind_Null;
|
GEN_TypeKind kind = GEN_TypeKind_Null;
|
||||||
MD_Node *tag_arg_node = type_tag->first_child;
|
MD_Node *tag_arg_node = type_tag->first_child;
|
||||||
MD_String8 tag_arg_str = tag_arg_node->string;
|
MD_String8 tag_arg_str = tag_arg_node->string;
|
||||||
@@ -185,6 +214,8 @@ gen_gather_types_and_maps(MD_Node *list)
|
|||||||
// gather map
|
// gather map
|
||||||
if (MD_NodeHasTag(node, MD_S8Lit("map"), 0))
|
if (MD_NodeHasTag(node, MD_S8Lit("map"), 0))
|
||||||
{
|
{
|
||||||
|
// TODO(allen): check for duplicates
|
||||||
|
|
||||||
GEN_MapInfo *map_info = MD_PushArrayZero(arena, GEN_MapInfo, 1);
|
GEN_MapInfo *map_info = MD_PushArrayZero(arena, GEN_MapInfo, 1);
|
||||||
map_info->node = node;
|
map_info->node = node;
|
||||||
MD_QueuePush(first_map, last_map, map_info);
|
MD_QueuePush(first_map, last_map, map_info);
|
||||||
@@ -226,6 +257,10 @@ gen_check_duplicate_member_names(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @notes In the next few stages of analysis we 'equip' the info nodes we
|
||||||
|
// gathered with further information by examining the sub-trees rooted at the
|
||||||
|
// metadesk nodes we saw durring the gather phase.
|
||||||
|
|
||||||
void
|
void
|
||||||
gen_equip_basic_type_size(void)
|
gen_equip_basic_type_size(void)
|
||||||
{
|
{
|
||||||
@@ -745,9 +780,14 @@ gen_check_complete_map_cases(void)
|
|||||||
|
|
||||||
//~ generators ////////////////////////////////////////////////////////////////
|
//~ generators ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// @notes Each generator function does all of the generation for one of the
|
||||||
|
// generated features we want. TODO keep going here.
|
||||||
|
|
||||||
void
|
void
|
||||||
gen_type_definitions_from_types(FILE *out)
|
gen_type_definitions_from_types(FILE *out)
|
||||||
{
|
{
|
||||||
|
// @notes This Metadesk helper generates a comment that points back here.
|
||||||
|
// Generating a comment like this can help a lot to with issues later.
|
||||||
MD_PrintGenNoteCComment(out);
|
MD_PrintGenNoteCComment(out);
|
||||||
|
|
||||||
for (GEN_TypeInfo *type = first_type;
|
for (GEN_TypeInfo *type = first_type;
|
||||||
@@ -1163,6 +1203,13 @@ main(int argc, char **argv)
|
|||||||
gen_check_duplicate_cases();
|
gen_check_duplicate_cases();
|
||||||
gen_check_complete_map_cases();
|
gen_check_complete_map_cases();
|
||||||
|
|
||||||
|
// @notes Here we explicitly use one block to generate each output file.
|
||||||
|
// This approach makes it a lot easier to understand where the contents
|
||||||
|
// of generated files come from, because it's all layed out it one place.
|
||||||
|
// However if the number of output files grows, this can get out of hand
|
||||||
|
// and the situation may start calling for more automation of the output
|
||||||
|
// files. There is a large amount of judgement calling in this part!
|
||||||
|
|
||||||
// generate header file
|
// generate header file
|
||||||
{
|
{
|
||||||
FILE *h = fopen("meta_types.h", "wb");
|
FILE *h = fopen("meta_types.h", "wb");
|
||||||
@@ -1177,20 +1224,22 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
// generate definitions file
|
// generate definitions file
|
||||||
{
|
{
|
||||||
// open output file
|
|
||||||
FILE *c = fopen("meta_types.c", "wb");
|
FILE *c = fopen("meta_types.c", "wb");
|
||||||
|
|
||||||
gen_struct_member_tables_from_types(c);
|
gen_struct_member_tables_from_types(c);
|
||||||
gen_enum_member_tables_from_types(c);
|
gen_enum_member_tables_from_types(c);
|
||||||
gen_type_info_definitions_from_types(c);
|
gen_type_info_definitions_from_types(c);
|
||||||
gen_function_definitions_from_maps(c);
|
gen_function_definitions_from_maps(c);
|
||||||
|
|
||||||
// close output file
|
|
||||||
fclose(c);
|
fclose(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @notes The generated code doesn't go straight to stdout, and has a lot
|
||||||
|
// of transforms applied. When writing the analyzers, it's often useful to
|
||||||
|
// have a way to directly dump the results of analysis right to stdout to
|
||||||
|
// see what's going on.
|
||||||
|
|
||||||
// print diagnostics of the parse analysis
|
// print diagnostics of the parse analysis
|
||||||
#if 0
|
#if 1
|
||||||
for (GEN_TypeInfo *type = first_type;
|
for (GEN_TypeInfo *type = first_type;
|
||||||
type != 0;
|
type != 0;
|
||||||
type = type->next)
|
type = type->next)
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ void gen_equip_map_cases(void);
|
|||||||
void gen_check_duplicate_cases(void);
|
void gen_check_duplicate_cases(void);
|
||||||
void gen_check_complete_map_cases(void);
|
void gen_check_complete_map_cases(void);
|
||||||
|
|
||||||
|
// TODO: check array member indexes point to members from before the array
|
||||||
|
|
||||||
//~ generators ////////////////////////////////////////////////////////////////
|
//~ generators ////////////////////////////////////////////////////////////////
|
||||||
void gen_type_definitions_from_types(FILE *out);
|
void gen_type_definitions_from_types(FILE *out);
|
||||||
void gen_function_declarations_from_maps(FILE *out);
|
void gen_function_declarations_from_maps(FILE *out);
|
||||||
|
|||||||
Reference in New Issue
Block a user