diff --git a/bin/run_examples.sh b/bin/run_examples.sh index abd658a..63e65a5 100755 --- a/bin/run_examples.sh +++ b/bin/run_examples.sh @@ -10,14 +10,12 @@ build_path=$root_path/build examps=$root_path/examples echo ~~~ Running Type Metadata Example ~~~ -cd $build_path -./type_metadata.exe $examps/type_metadata/types.mdesk +cd $examps/type_metadata/generated +$build_path/type_metadata.exe $examps/type_metadata/types.mdesk echo echo ~~~ Running Error Generation Example ~~~ -cd $build_path -./user_errors.exe $examps/user_errors/user_errors.mdesk -echo +$build_path/user_errors.exe $examps/user_errors/user_errors.mdesk ###### Restore Path ########################################################### cd $og_path diff --git a/examples/type_metadata/.gitignore b/examples/type_metadata/.gitignore deleted file mode 100644 index 11390d2..0000000 --- a/examples/type_metadata/.gitignore +++ /dev/null @@ -1 +0,0 @@ -generated/* diff --git a/examples/type_metadata/generated/meta_types.c b/examples/type_metadata/generated/meta_types.c new file mode 100644 index 0000000..e69de29 diff --git a/examples/type_metadata/generated/meta_types.h b/examples/type_metadata/generated/meta_types.h new file mode 100644 index 0000000..010e3a0 --- /dev/null +++ b/examples/type_metadata/generated/meta_types.h @@ -0,0 +1,31 @@ +#if !defined(META_TYEPS_H) +#define META_TYEPS_H +typedef struct Circle Circle; +struct Circle +{ +F32 r; +V2F32 pos; +}; +typedef struct RoundedSegment RoundedSegment; +struct RoundedSegment +{ +F32 r; +V2F32 p1; +V2F32 p2; +}; +typedef struct RoundedPolygon RoundedPolygon; +struct RoundedPolygon +{ +F32 r; +U32 count; +V2F32 *p; +}; +enum Shape +{ +Shape_Circle = 1, +Shape_Segment = 2, +Shape_Polygon = 3, +}; +TypeInfo* type_info_from_shape(Shape v); +U32 max_slot_from_shape(Shape v); +#endif // META_TYEPS_H diff --git a/examples/type_metadata/type_metadata.c b/examples/type_metadata/type_metadata.c index 3e55a96..d85ebcb 100644 --- a/examples/type_metadata/type_metadata.c +++ b/examples/type_metadata/type_metadata.c @@ -40,7 +40,6 @@ struct TypeInfo struct TypeEnumerant *first_enumerant; struct TypeEnumerant *last_enumerant; int enumerant_count; - }; typedef struct TypeMember TypeMember; @@ -49,6 +48,7 @@ struct TypeMember TypeMember *next; MD_Node *node; TypeInfo *type; + MD_Node *array_count; }; typedef struct TypeEnumerant TypeEnumerant; @@ -64,6 +64,13 @@ struct MapInfo { MapInfo *next; MD_Node *node; + + MD_Node *in; + MD_Node *out; + + int is_complete; + MD_Node *default_val; + MD_Node *auto_val; }; @@ -78,8 +85,94 @@ MapInfo *last_map = 0; MD_Map map_map = {0}; +//~ feature generators //////////////////////////////////////////////////////// + +void +generate_type_definitions(FILE *out, TypeInfo *first_type) +{ + for (TypeInfo *type = first_type; + type != 0; + type = type->next) + { + switch (type->kind) + { + default:break; + + case TypeKind_Struct: + { + MD_String8 struct_name = type->node->string; + fprintf(out, "typedef struct %.*s %.*s;\n", MD_S8VArg(struct_name), MD_S8VArg(struct_name)); + fprintf(out, "struct %.*s\n", MD_S8VArg(struct_name)); + fprintf(out, "{\n"); + for (TypeMember *member = type->first_member; + member != 0; + member = member->next) + { + MD_String8 type_name = member->type->node->string; + MD_String8 member_name = member->node->string; + int is_array = (!MD_NodeIsNil(member->array_count)); + if (is_array) + { + fprintf(out, "%.*s *%.*s;\n", MD_S8VArg(type_name), MD_S8VArg(member_name)); + } + else + { + fprintf(out, "%.*s %.*s;\n", MD_S8VArg(type_name), MD_S8VArg(member_name)); + } + } + fprintf(out, "};\n"); + }break; + + case TypeKind_Enum: + { + MD_String8 enum_name = type->node->string; + fprintf(out, "enum %.*s\n", MD_S8VArg(enum_name)); + fprintf(out, "{\n"); + for (TypeEnumerant *enumerant = type->first_enumerant; + enumerant != 0; + enumerant = enumerant->next) + { + MD_String8 member_name = enumerant->node->string; + fprintf(out, "%.*s_%.*s = %d,\n", + MD_S8VArg(enum_name), MD_S8VArg(member_name), enumerant->value); + } + fprintf(out, "};\n"); + }break; + } + } +} + +void +generate_function_declarations_from_maps(FILE *out, MapInfo *first_map) +{ + for (MapInfo *map = first_map; + map != 0; + map = map->next) + { + MD_Node *node = map->node; + + MD_String8 in_type = map->in->string; + MD_String8 out_type = map->out->string; + if (MD_S8Match(out_type, MD_S8Lit("$Type"), 0)) + { + out_type = MD_S8Lit("TypeInfo*"); + } + + fprintf(out, "%.*s %.*s(%.*s v);\n", + MD_S8VArg(out_type), MD_S8VArg(node->string), MD_S8VArg(in_type)); + } +} + //~ main ////////////////////////////////////////////////////////////////////// +MD_Node* +get_md_child_value(MD_Node *parent, MD_String8 child_name) +{ + MD_Node *child = MD_ChildFromString(parent, child_name, 0); + MD_Node *result = child->first_child; + return(result); +} + int main(int argc, char **argv) { @@ -162,12 +255,37 @@ main(int argc, char **argv) } // gather map - MD_Node *map_tag = MD_TagFromString(node, MD_S8Lit("map"), 0); + MD_Node *map_tag = MD_TagFromString(node, MD_S8Lit("map"), 0); if (!MD_NodeIsNil(map_tag)) { - MapInfo *map_info = MD_PushArray(arena, MapInfo, 1); + // NOTE we could use an expression parser here to make this fancier + // and check for the 'In -> Out' semicolon delimited syntax more + // carefully, this isn't checking it very rigorously. But there are + // no other cases we need to expect so far so being a bit sloppy + // buys us a lot of simplicity. + MD_Node *in = map_tag->first_child; + MD_Node *arrow = in->next; + MD_Node *out = arrow->next; + + if (!MD_S8Match(arrow->string, MD_S8Lit("->"), 0) || + MD_NodeIsNil(out)) + { + // TODO(allen): error map type + } + + int is_complete = MD_NodeHasChild(map_tag, MD_S8Lit("complete"), 0); + + MD_Node *default_val = get_md_child_value(map_tag, MD_S8Lit("default")); + MD_Node *auto_val = get_md_child_value(map_tag, MD_S8Lit("auto")); + + MapInfo *map_info = MD_PushArrayZero(arena, MapInfo, 1); map_info->node = node; + map_info->in = in; + map_info->out = out; + map_info->is_complete = is_complete; + map_info->default_val = default_val; + map_info->auto_val = auto_val; MD_QueuePush(first_map, last_map, map_info); MD_MapInsert(arena, &map_map, MD_MapKeyStr(node->string), map_info); @@ -224,11 +342,18 @@ main(int argc, char **argv) { TypeInfo *type_info = (TypeInfo*)type_info_slot->val; - // TODO(allen): handle the array tag + MD_Node *array_count = MD_NilNode(); + MD_Node *array_tag = MD_TagFromString(type_name_node, MD_S8Lit("array"), 0); + if (!MD_NodeIsNil(array_tag)) + { + array_count = array_tag->first_child; + // TODO(allen): error if array_count is nil + } TypeMember *member = MD_PushArray(arena, TypeMember, 1); member->node = member_node; member->type = type_info; + member->array_count = array_count; MD_QueuePush(first_member, last_member, member); member_count += 1; } @@ -313,17 +438,42 @@ main(int argc, char **argv) } // TODO check maps & build case lists - // TODO generate type definitions - // TODO generate function declarations - // TODO generate metadata tables - // TODO generate function definitions + + // generate meta types header + { + FILE *h = fopen("meta_types.h", "wb"); + fprintf(h, "#if !defined(META_TYEPS_H)\n"); + fprintf(h, "#define META_TYEPS_H\n"); + + // generate type definitions + generate_type_definitions(h, first_type); + + // generate function declarations + generate_function_declarations_from_maps(h, first_map); + + fprintf(h, "#endif // META_TYEPS_H\n"); + fclose(h); + } + + // generate meta types code + { + // open output file + FILE *c = fopen("meta_types.c", "wb"); + + // TODO generate metadata tables + // TODO generate function definitions + + // close output file + fclose(c); + } // print state for (TypeInfo *type = first_type; type != 0; type = type->next){ char *kind_string = "ERROR"; - switch (type->kind){ + switch (type->kind) + { default:break; case TypeKind_Basic: kind_string = "basic"; break; case TypeKind_Struct: kind_string = "struct"; break; diff --git a/examples/type_metadata/types.mdesk b/examples/type_metadata/types.mdesk index 7e42765..f47ed17 100644 --- a/examples/type_metadata/types.mdesk +++ b/examples/type_metadata/types.mdesk @@ -45,7 +45,6 @@ type_info_from_shape: Polygon -> RoundedPolygon, } - @map(Shape -> U32; default: 0; auto: 64) max_slot_from_shape: { diff --git a/project.4coder b/project.4coder index f925ce6..2575a47 100644 --- a/project.4coder +++ b/project.4coder @@ -82,8 +82,8 @@ command_list = }, { .name = "run_examples", - .out = "*compilation*", - .footer_panel = true, + .out = "*run*", + .footer_panel = false, .save_dirty_files = true, .cursor_at_end = false, .cmd = diff --git a/source/md.c b/source/md.c index c881154..6d97649 100644 --- a/source/md.c +++ b/source/md.c @@ -3005,9 +3005,15 @@ MD_TagArgFromString(MD_Node *node, MD_String8 tag_string, MD_MatchFlags tag_str_ } MD_FUNCTION MD_b32 -MD_NodeHasTag(MD_Node *node, MD_String8 tag_string, MD_MatchFlags flags) +MD_NodeHasChild(MD_Node *node, MD_String8 string, MD_MatchFlags flags) { - return !MD_NodeIsNil(MD_TagFromString(node, tag_string, flags)); + return !MD_NodeIsNil(MD_ChildFromString(node, string, flags)); +} + +MD_FUNCTION MD_b32 +MD_NodeHasTag(MD_Node *node, MD_String8 string, MD_MatchFlags flags) +{ + return !MD_NodeIsNil(MD_TagFromString(node, string, flags)); } MD_FUNCTION MD_i64 diff --git a/source/md.h b/source/md.h index e26c0db..8cc6d88 100644 --- a/source/md.h +++ b/source/md.h @@ -1087,7 +1087,8 @@ MD_FUNCTION MD_Node * MD_ChildFromIndex(MD_Node *node, int n); MD_FUNCTION MD_Node * MD_TagFromIndex(MD_Node *node, int n); MD_FUNCTION MD_Node * MD_TagArgFromIndex(MD_Node *node, MD_String8 tag_string, MD_MatchFlags flags, int n); MD_FUNCTION MD_Node * MD_TagArgFromString(MD_Node *node, MD_String8 tag_string, MD_MatchFlags tag_str_flags, MD_String8 arg_string, MD_MatchFlags arg_str_flags); -MD_FUNCTION MD_b32 MD_NodeHasTag(MD_Node *node, MD_String8 tag_string, MD_MatchFlags flags); +MD_FUNCTION MD_b32 MD_NodeHasChild(MD_Node *node, MD_String8 string, MD_MatchFlags flags); +MD_FUNCTION MD_b32 MD_NodeHasTag(MD_Node *node, MD_String8 string, MD_MatchFlags flags); MD_FUNCTION MD_i64 MD_ChildCountFromNode(MD_Node *node); MD_FUNCTION MD_i64 MD_TagCountFromNode(MD_Node *node); MD_FUNCTION MD_Node * MD_ResolveNodeFromReference(MD_Node *node);