mirror of
https://github.com/Ed94/metadesk.git
synced 2026-07-16 14:31:25 -07: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] = {
|
||||
{"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,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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user