diff --git a/bin/type_info_example.sh b/bin/type_metadata_example.sh similarity index 80% rename from bin/type_info_example.sh rename to bin/type_metadata_example.sh index 84dc9f9..0be198c 100644 --- a/bin/type_info_example.sh +++ b/bin/type_metadata_example.sh @@ -30,12 +30,20 @@ $build_path/type_metadata.exe $examps_path/type_metadata/types.mdesk echo if [ -f $examps_path/type_metadata/generated/meta_types.h ]; then -echo ~~~ Building Program ~~~ -$bin_path/bld_core.sh unit type_info $examps/type_metadata/type_info_final_program.c -else -echo !!! Skipping Program !!! -fi +echo ~~~ Building Final Program ~~~ +$bin_path/bld_core.sh unit type_info_final $examps/type_metadata/type_info_final_program.c echo +echo ~~~ Running Final Program ~~~ +$build_path/type_info_final +echo + +else + +echo !!! Skipping Final Program !!! +echo + +fi + ###### Restore Path ########################################################### cd $og_path diff --git a/examples/type_metadata/generated/meta_types.c b/examples/type_metadata/generated/meta_types.c index 80ae53a..f0b52fa 100644 --- a/examples/type_metadata/generated/meta_types.c +++ b/examples/type_metadata/generated/meta_types.c @@ -1,4 +1,4 @@ -// generated by W:/metadesk/examples/type_metadata/type_metadata.c:837 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:874 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:876 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:913 TypeInfoEnumerant Shape_members[3] = { {"Circle", 6, 1}, {"Segment", 7, 2}, {"Polygon", 7, 3}, }; -// generated by W:/metadesk/examples/type_metadata/type_metadata.c:912 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:949 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:972 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:1009 TypeInfo* type_info_from_shape(Shape v) { diff --git a/examples/type_metadata/generated/meta_types.h b/examples/type_metadata/generated/meta_types.h index 74939a4..5fe38c9 100644 --- a/examples/type_metadata/generated/meta_types.h +++ b/examples/type_metadata/generated/meta_types.h @@ -1,6 +1,6 @@ #if !defined(META_TYPES_H) #define META_TYPES_H -// generated by W:/metadesk/examples/type_metadata/type_metadata.c:714 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:751 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:798 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:835 TypeInfo* type_info_from_shape(Shape v); U32 max_slot_from_shape(Shape v); -// generated by W:/metadesk/examples/type_metadata/type_metadata.c:821 +// generated by W:/metadesk/examples/type_metadata/type_metadata.c:858 extern TypeInfo U32_type_info; extern TypeInfo F32_type_info; extern TypeInfo V2F32_type_info; diff --git a/examples/type_metadata/type_info_final_program.c b/examples/type_metadata/type_info_final_program.c index 2ccfafc..886d8c5 100644 --- a/examples/type_metadata/type_info_final_program.c +++ b/examples/type_metadata/type_info_final_program.c @@ -1,13 +1,15 @@ /* ** Example: type metadata ** -** This file shows including the generated type information into a final -** program and using that type info to unpack a buffer of data. +** This file shows including the generated types and metadata in the a final +** program and using it to unpack a buffer of data. ** */ //~ setup base types ////////////////////////////////////////////////////////// #include +typedef uint8_t U8; +typedef uint16_t U16; typedef uint32_t U32; typedef float F32; typedef struct V2F32 V2F32; @@ -26,12 +28,184 @@ struct V2F32 //~ main ////////////////////////////////////////////////////////////////////// +U8 raw_buffer[] = { + 0x03,0x00,0x00,0x00,0x00,0x00,0x90,0x40,0x06,0x00,0x00,0x00, + 0x00,0x00,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F, + 0x2D,0xB2,0x5D,0x3F,0x00,0x00,0x00,0xBF,0x2D,0xB2,0x5D,0x3F, + 0x00,0x00,0x80,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF, + 0x2D,0xB2,0x5D,0xBF,0x00,0x00,0x00,0x3F,0x2D,0xB2,0x5D,0xBF, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0, + 0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xC0, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x00,0xC0,0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00, +}; + #include +#include + +int +print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int indent){ + static char spaces[] = + " "; + + int result = 1; + + switch (type_info->kind){ + case TypeKind_Basic: + { + // special case each basic type + + if (type_info == &U32_type_info) + { + if (*ptr_inout + sizeof(U32) > opl) + { + result = 0; + goto finish; + } + U32 x = *(U32*)*ptr_inout; + *ptr_inout += sizeof(x); + fprintf(stdout, "%u\n", x); + } + + if (type_info == &F32_type_info) + { + if (*ptr_inout + sizeof(F32) > opl) + { + result = 0; + goto finish; + } + F32 x = *(F32*)*ptr_inout; + *ptr_inout += sizeof(x); + fprintf(stdout, "%f\n", x); + } + + if (type_info == &V2F32_type_info) + { + if (*ptr_inout + sizeof(V2F32) > opl) + { + result = 0; + goto finish; + } + V2F32 x = *(V2F32*)*ptr_inout; + *ptr_inout += sizeof(x); + fprintf(stdout, "(%f,%f)\n", x.x, x.y); + } + }break; + + case TypeKind_Struct: + { + U32 member_value_memory[20] = {0}; + + // iterate members + TypeInfoMember *first_member = (TypeInfoMember*)type_info->children; + TypeInfoMember *member = first_member; + int child_count = type_info->child_count; + for (int i = 0; i < child_count; i += 1, member += 1) + { + assert(i < 20); + TypeInfo *member_type_info = member->type; + + // 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 + 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 + else + { + assert(member->array_count_member_index < i); + U32 count = member_value_memory[member->array_count_member_index]; + fprintf(stdout, "%.*s%.*s:\n", indent, spaces, member->name_length, member->name); + indent += 1; + for (U32 j = 0; j < count; j += 1) + { + fprintf(stdout, "%.*s[%d]: ", indent, spaces, j); + if (!print_data_from_type_info(ptr_inout, opl, member_type_info, indent + 1)) + { + result = 0; + goto finish; + } + } + indent -= 1; + } + } + }break; + + case TypeKind_Enum: + { + // rely on the underlying type (default to U32) to print enums + TypeInfo *underlying_type = type_info->underlying_type; + if (underlying_type == 0) + { + underlying_type = &U32_type_info; + } + fprintf(stdout, "(%.*s)", type_info->name_length, type_info->name); + if (!print_data_from_type_info(ptr_inout, opl, underlying_type, indent)) + { + result = 0; + goto finish; + } + }break; + + default: + { + result = 0; + goto finish; + }break; + } + + finish:; + + return(result); +} int main(int argc, char **argv) { - // TODO(allen): write example final program + // decode the raw buffer + U8 *ptr = raw_buffer; + U8 *opl = ptr + sizeof(raw_buffer); + for (;ptr < opl;) + { + // decode a shape discriminator + if (ptr + sizeof(Shape) > opl){ + fprintf(stdout, "Could not decode shape discriminator\n"); + break; + } + Shape shape = *(Shape*)ptr; + ptr += sizeof(shape); + + // get type info + TypeInfo *type_info = type_info_from_shape(shape); + if (type_info == 0){ + fprintf(stdout, "Unrecognized shape discriminator\n"); + break; + } + + // print type name + fprintf(stdout, "%.*s:\n", type_info->name_length, type_info->name); + + // print contents + if (!print_data_from_type_info(&ptr, opl, type_info, 1)) + { + fprintf(stdout, "Decoding error\n"); + break; + } + } return(0); } diff --git a/examples/type_metadata/type_metadata.c b/examples/type_metadata/type_metadata.c index f3ae63a..ae6aa1f 100644 --- a/examples/type_metadata/type_metadata.c +++ b/examples/type_metadata/type_metadata.c @@ -34,7 +34,7 @@ ** type_info_final_program.c - In addition to the metaprogram this example ** includes a "final program", i.e. one that depends on ** generated code. There is more commentary there. -** generated/* - This is the output folder where the generated files +** generated/ * - This is the output folder where the generated files ** should be saved by the metaprogram. ** types.mdesk - Sample input for this metaprogram. The code generated ** from this metadesk file will be necessary to make diff --git a/examples/type_metadata/type_metadata.h b/examples/type_metadata/type_metadata.h index 204e52c..a2a3f79 100644 --- a/examples/type_metadata/type_metadata.h +++ b/examples/type_metadata/type_metadata.h @@ -1,7 +1,8 @@ /* ** Example: type metadata ** -** TODO full commentary +** The header file for the metaprogram's main file. There isn't much commentary +** here, this file is just to help us keep the example organized. ** */ diff --git a/project.4coder b/project.4coder index ad07c0f..1dbe6ba 100644 --- a/project.4coder +++ b/project.4coder @@ -94,16 +94,16 @@ command_list = }, }, { - .name = "type_info_example", + .name = "type_metadata_example", .out = "*run*", .footer_panel = false, .save_dirty_files = true, .cursor_at_end = false, .cmd = { - { "git_bash bin\\type_info_example.sh", .os = "win" }, - { "bin/type_info_example.sh", .os = "linux" }, - { "bin/type_info_example.sh", .os = "mac" }, + { "git_bash bin\\type_metadata_example.sh", .os = "win" }, + { "bin/type_metadata_example.sh", .os = "linux" }, + { "bin/type_metadata_example.sh", .os = "mac" }, }, }, }; @@ -112,4 +112,4 @@ fkey_command[1] = "build_tests"; fkey_command[2] = "run_tests"; fkey_command[3] = "build_examples"; fkey_command[4] = "run_examples"; -fkey_command[5] = "type_info_example"; +fkey_command[5] = "type_metadata_example";