[examples] progress on type metadata commentary

This commit is contained in:
Allen Webster
2021-10-08 23:12:32 -07:00
parent a5436aec0e
commit c8c5763d0a
5 changed files with 74 additions and 24 deletions
@@ -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] = {
{"r", 1, -1, &F32_type_info},
{"pos", 3, -1, &V2F32_type_info},
@@ -14,14 +14,14 @@ TypeInfoMember RoundedPolygon_members[3] = {
{"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] = {
{"Circle", 6, 1},
{"Segment", 7, 2},
{"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 F32_type_info = {TypeKind_Basic, "F32", 3, 4, 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 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*
type_info_from_shape(Shape v)
{
@@ -1,6 +1,6 @@
#if !defined(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;
struct Circle
{
@@ -29,11 +29,11 @@ Shape_Segment = 2,
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);
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 F32_type_info;
extern TypeInfo V2F32_type_info;
@@ -44,7 +44,8 @@ U8 raw_buffer[] = {
#include <assert.h>
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[] =
" ";
@@ -108,20 +109,16 @@ print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int inde
// decode single members
if (member->array_count_member_index == -1)
{
// save the offset of this member for later
U8 *ptr_og = *ptr_inout;
// decode this member
if (member_type_info == &U32_type_info && *ptr_inout + 4 <= opl)
{
member_value_memory[i] = *(U32*)*ptr_inout;
}
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))
{
result = 0;
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
@@ -176,13 +173,14 @@ print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int inde
int
main(int argc, char **argv)
{
// decode the raw buffer
// decode the raw buffer of shape data
U8 *ptr = raw_buffer;
U8 *opl = ptr + sizeof(raw_buffer);
for (;ptr < opl;)
{
// decode a shape discriminator
if (ptr + sizeof(Shape) > opl){
if (ptr + sizeof(Shape) > opl)
{
fprintf(stdout, "Could not decode shape discriminator\n");
break;
}
@@ -191,7 +189,8 @@ main(int argc, char **argv)
// get type info
TypeInfo *type_info = type_info_from_shape(shape);
if (type_info == 0){
if (type_info == 0)
{
fprintf(stdout, "Unrecognized shape discriminator\n");
break;
}
+54 -5
View File
@@ -54,6 +54,18 @@ static MD_Arena *arena = 0;
FILE *error_file = 0;
// 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 *last_type = 0;
MD_Map type_map = {0};
@@ -77,6 +89,12 @@ GEN_TypeInfo*
gen_resolve_type_info_from_string(MD_String8 name)
{
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));
if (slot != 0)
{
@@ -136,6 +154,15 @@ gen_map_case_from_enumerant(GEN_MapInfo *map, GEN_TypeEnumerant *enumerant)
//~ 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
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))
{
// TODO(allen): check for duplicates
GEN_TypeKind kind = GEN_TypeKind_Null;
MD_Node *tag_arg_node = type_tag->first_child;
MD_String8 tag_arg_str = tag_arg_node->string;
@@ -185,6 +214,8 @@ gen_gather_types_and_maps(MD_Node *list)
// gather map
if (MD_NodeHasTag(node, MD_S8Lit("map"), 0))
{
// TODO(allen): check for duplicates
GEN_MapInfo *map_info = MD_PushArrayZero(arena, GEN_MapInfo, 1);
map_info->node = node;
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
gen_equip_basic_type_size(void)
{
@@ -745,9 +780,14 @@ gen_check_complete_map_cases(void)
//~ generators ////////////////////////////////////////////////////////////////
// @notes Each generator function does all of the generation for one of the
// generated features we want. TODO keep going here.
void
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);
for (GEN_TypeInfo *type = first_type;
@@ -1163,6 +1203,13 @@ main(int argc, char **argv)
gen_check_duplicate_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
{
FILE *h = fopen("meta_types.h", "wb");
@@ -1177,20 +1224,22 @@ main(int argc, char **argv)
// generate definitions file
{
// open output file
FILE *c = fopen("meta_types.c", "wb");
gen_struct_member_tables_from_types(c);
gen_enum_member_tables_from_types(c);
gen_type_info_definitions_from_types(c);
gen_function_definitions_from_maps(c);
// close output file
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
#if 0
#if 1
for (GEN_TypeInfo *type = first_type;
type != 0;
type = type->next)
+2
View File
@@ -120,6 +120,8 @@ void gen_equip_map_cases(void);
void gen_check_duplicate_cases(void);
void gen_check_complete_map_cases(void);
// TODO: check array member indexes point to members from before the array
//~ generators ////////////////////////////////////////////////////////////////
void gen_type_definitions_from_types(FILE *out);
void gen_function_declarations_from_maps(FILE *out);