mirror of
https://github.com/Ed94/metadesk.git
synced 2026-08-06 07:38:45 +00:00
[examples] pull out each big piece into a function
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:199
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:493
|
||||||
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:238
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:532
|
||||||
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:274
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:568
|
||||||
TypeInfo U32_type_info = {TypeKind_Basic, "U32", 3, 0, 0, 0};
|
TypeInfo U32_type_info = {TypeKind_Basic, "U32", 3, 0, 0, 0};
|
||||||
TypeInfo F32_type_info = {TypeKind_Basic, "F32", 3, 0, 0, 0};
|
TypeInfo F32_type_info = {TypeKind_Basic, "F32", 3, 0, 0, 0};
|
||||||
TypeInfo V2F32_type_info = {TypeKind_Basic, "V2F32", 5, 0, 0, 0};
|
TypeInfo V2F32_type_info = {TypeKind_Basic, "V2F32", 5, 0, 0, 0};
|
||||||
|
|||||||
@@ -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:99
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:393
|
||||||
typedef struct Circle Circle;
|
typedef struct Circle Circle;
|
||||||
struct Circle
|
struct Circle
|
||||||
{
|
{
|
||||||
@@ -28,11 +28,11 @@ Shape_Segment = 2,
|
|||||||
Shape_Polygon = 3,
|
Shape_Polygon = 3,
|
||||||
} Shape;
|
} Shape;
|
||||||
|
|
||||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:158
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:452
|
||||||
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:183
|
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:477
|
||||||
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;
|
||||||
|
|||||||
@@ -80,6 +80,22 @@ struct GEN_MapInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//~ helpers ///////////////////////////////////////////////////////////////////
|
||||||
|
MD_Node* gen_get_md_child_value(MD_Node *parent, MD_String8 child_name);
|
||||||
|
|
||||||
|
//~ analyzers /////////////////////////////////////////////////////////////////
|
||||||
|
void gen_gather_types_and_maps(MD_Node *list);
|
||||||
|
void gen_gather_struct_members(void);
|
||||||
|
|
||||||
|
//~ generators ////////////////////////////////////////////////////////////////
|
||||||
|
void gen_type_definitions_from_types(FILE *out, GEN_TypeInfo *first_type);
|
||||||
|
void gen_function_declarations_from_maps(FILE *out, GEN_MapInfo *first_map);
|
||||||
|
void gen_type_info_declarations_from_types(FILE *out, GEN_TypeInfo *first_type);
|
||||||
|
void gen_struct_member_tables_from_types(FILE *out, GEN_TypeInfo *first_type);
|
||||||
|
void gen_enum_member_tables_from_types(FILE *out, GEN_TypeInfo *first_type);
|
||||||
|
void gen_type_info_definitions_from_types(FILE *out, GEN_TypeInfo *first_type);
|
||||||
|
|
||||||
|
|
||||||
//~ node maps /////////////////////////////////////////////////////////////////
|
//~ node maps /////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GEN_TypeInfo *first_type = 0;
|
GEN_TypeInfo *first_type = 0;
|
||||||
@@ -91,7 +107,285 @@ GEN_MapInfo *last_map = 0;
|
|||||||
MD_Map map_map = {0};
|
MD_Map map_map = {0};
|
||||||
|
|
||||||
|
|
||||||
//~ feature generators ////////////////////////////////////////////////////////
|
//~ helpers ///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MD_Node*
|
||||||
|
gen_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//~ analyzers /////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void
|
||||||
|
gen_gather_types_and_maps(MD_Node *list)
|
||||||
|
{
|
||||||
|
for(MD_EachNode(ref, list->first_child))
|
||||||
|
{
|
||||||
|
MD_Node *root = MD_ResolveNodeFromReference(ref);
|
||||||
|
for(MD_EachNode(node, root->first_child))
|
||||||
|
{
|
||||||
|
// gather type
|
||||||
|
MD_Node *type_tag = MD_TagFromString(node, MD_S8Lit("type"), 0);
|
||||||
|
|
||||||
|
if (!MD_NodeIsNil(type_tag))
|
||||||
|
{
|
||||||
|
GEN_TypeKind kind = GEN_TypeKind_Null;
|
||||||
|
MD_Node *tag_arg_node = type_tag->first_child;
|
||||||
|
MD_String8 tag_arg_str = tag_arg_node->string;
|
||||||
|
if (MD_S8Match(tag_arg_str, MD_S8Lit("basic"), 0))
|
||||||
|
{
|
||||||
|
kind = GEN_TypeKind_Basic;
|
||||||
|
}
|
||||||
|
else if (MD_S8Match(tag_arg_str, MD_S8Lit("struct"), 0))
|
||||||
|
{
|
||||||
|
kind = GEN_TypeKind_Struct;
|
||||||
|
}
|
||||||
|
else if (MD_S8Match(tag_arg_str, MD_S8Lit("enum"), 0))
|
||||||
|
{
|
||||||
|
kind = GEN_TypeKind_Enum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kind == GEN_TypeKind_Null)
|
||||||
|
{
|
||||||
|
MD_CodeLoc loc = MD_CodeLocFromNode(node);
|
||||||
|
MD_PrintMessageFmt(error_file, loc, MD_MessageKind_Error,
|
||||||
|
"Unrecognized type kind '%.*s'\n",
|
||||||
|
MD_S8VArg(tag_arg_str));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GEN_TypeInfo *type_info = MD_PushArrayZero(arena, GEN_TypeInfo, 1);
|
||||||
|
type_info->kind = kind;
|
||||||
|
type_info->node = node;
|
||||||
|
|
||||||
|
MD_QueuePush(first_type, last_type, type_info);
|
||||||
|
MD_MapInsert(arena, &type_map, MD_MapKeyStr(node->string), type_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather map
|
||||||
|
MD_Node *map_tag = MD_TagFromString(node, MD_S8Lit("map"), 0);
|
||||||
|
|
||||||
|
if (!MD_NodeIsNil(map_tag))
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
{
|
||||||
|
MD_Node *error_at = 0;
|
||||||
|
if (MD_NodeIsNil(in))
|
||||||
|
{
|
||||||
|
error_at = map_tag;
|
||||||
|
}
|
||||||
|
else if (!MD_S8Match(arrow->string, MD_S8Lit("->"), 0) ||
|
||||||
|
MD_NodeIsNil(out))
|
||||||
|
{
|
||||||
|
error_at = in;
|
||||||
|
}
|
||||||
|
if (error_at != 0)
|
||||||
|
{
|
||||||
|
MD_CodeLoc loc = MD_CodeLocFromNode(error_at);
|
||||||
|
MD_PrintMessage(error_file, loc, MD_MessageKind_Error,
|
||||||
|
MD_S8Lit("Map's type should be specified like: `In -> Out`"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for named children in the map tag
|
||||||
|
int is_complete = MD_NodeHasChild(map_tag, MD_S8Lit("complete"), 0);
|
||||||
|
MD_Node *default_val = gen_get_md_child_value(map_tag, MD_S8Lit("default"));
|
||||||
|
MD_Node *auto_val = gen_get_md_child_value(map_tag, MD_S8Lit("auto"));
|
||||||
|
|
||||||
|
// save a new map
|
||||||
|
GEN_MapInfo *map_info = MD_PushArrayZero(arena, GEN_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gen_gather_struct_members(void)
|
||||||
|
{
|
||||||
|
for (GEN_TypeInfo *type = first_type;
|
||||||
|
type != 0;
|
||||||
|
type = type->next)
|
||||||
|
{
|
||||||
|
if (type->kind == GEN_TypeKind_Struct)
|
||||||
|
{
|
||||||
|
// build the list
|
||||||
|
MD_b32 got_list = 1;
|
||||||
|
GEN_TypeMember *first_member = 0;
|
||||||
|
GEN_TypeMember *last_member = 0;
|
||||||
|
int member_count = 0;
|
||||||
|
|
||||||
|
MD_Node *type_root_node = type->node;
|
||||||
|
for (MD_EachNode(member_node, type_root_node->first_child))
|
||||||
|
{
|
||||||
|
MD_Node *type_name_node = member_node->first_child;
|
||||||
|
|
||||||
|
// missing type node?
|
||||||
|
if (MD_NodeIsNil(type_name_node))
|
||||||
|
{
|
||||||
|
MD_CodeLoc loc = MD_CodeLocFromNode(member_node);
|
||||||
|
MD_PrintMessage(error_file, loc, MD_MessageKind_Error,
|
||||||
|
MD_S8Lit("Missing type name for member"));
|
||||||
|
got_list = 0;
|
||||||
|
goto skip_member;
|
||||||
|
}
|
||||||
|
|
||||||
|
// has type node:
|
||||||
|
MD_String8 type_name = type_name_node->string;
|
||||||
|
MD_MapSlot *type_info_slot = (MD_MapSlot*)MD_MapLookup(&type_map, MD_MapKeyStr(type_name));
|
||||||
|
|
||||||
|
// could not resolve type?
|
||||||
|
if (type_info_slot == 0)
|
||||||
|
{
|
||||||
|
MD_CodeLoc loc = MD_CodeLocFromNode(type_name_node);
|
||||||
|
MD_PrintMessageFmt(error_file, loc, MD_MessageKind_Error,
|
||||||
|
"Could not resolve type name '%.*s'", MD_S8VArg(type_name));
|
||||||
|
got_list = 0;
|
||||||
|
goto skip_member;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolved type:
|
||||||
|
if (got_list)
|
||||||
|
{
|
||||||
|
GEN_TypeInfo *type_info = (GEN_TypeInfo*)type_info_slot->val;
|
||||||
|
|
||||||
|
MD_Node *array_count = MD_NilNode();
|
||||||
|
MD_Node *array_tag = MD_TagFromString(type_name_node, MD_S8Lit("array"), 0);
|
||||||
|
if (!MD_NodeIsNil(array_tag))
|
||||||
|
{
|
||||||
|
MD_Node *array_count_referencer = array_tag->first_child;
|
||||||
|
if (array_count_referencer->string.size == 0)
|
||||||
|
{
|
||||||
|
MD_CodeLoc loc = MD_CodeLocFromNode(array_tag);
|
||||||
|
MD_PrintMessage(error_file, loc, MD_MessageKind_Error,
|
||||||
|
MD_S8Lit("array tags must specify a parameter for their count"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
array_count = MD_ChildFromString(type_root_node, array_count_referencer->string, 0);
|
||||||
|
if (MD_NodeIsNil(array_count))
|
||||||
|
{
|
||||||
|
MD_CodeLoc loc = MD_CodeLocFromNode(array_count_referencer);
|
||||||
|
MD_PrintMessageFmt(error_file, loc, MD_MessageKind_Error,
|
||||||
|
"'%.*s' is not a member of %.*s",
|
||||||
|
MD_S8VArg(array_count_referencer->string), MD_S8VArg(type_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_TypeMember *member = MD_PushArray(arena, GEN_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_member:;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the list
|
||||||
|
if (got_list)
|
||||||
|
{
|
||||||
|
type->first_member = first_member;
|
||||||
|
type->last_member = last_member;
|
||||||
|
type->member_count = member_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gen_gather_enum_members(void)
|
||||||
|
{
|
||||||
|
for (GEN_TypeInfo *type = first_type;
|
||||||
|
type != 0;
|
||||||
|
type = type->next)
|
||||||
|
{
|
||||||
|
if (type->kind == GEN_TypeKind_Enum)
|
||||||
|
{
|
||||||
|
|
||||||
|
// build the list
|
||||||
|
MD_b32 got_list = 1;
|
||||||
|
GEN_TypeEnumerant *first_enumerant = 0;
|
||||||
|
GEN_TypeEnumerant *last_enumerant = 0;
|
||||||
|
int enumerant_count = 0;
|
||||||
|
|
||||||
|
int next_implicit_value = 0;
|
||||||
|
|
||||||
|
MD_Node *type_root_node = type->node;
|
||||||
|
for (MD_EachNode(enumerant_node, type_root_node->first_child))
|
||||||
|
{
|
||||||
|
MD_Node *value_node = enumerant_node->first_child;
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
// missing value node?
|
||||||
|
if (MD_NodeIsNil(value_node))
|
||||||
|
{
|
||||||
|
value = next_implicit_value;
|
||||||
|
next_implicit_value += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// has value node
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MD_String8 value_string = value_node->string;
|
||||||
|
if (!MD_StringIsCStyleInt(value_string))
|
||||||
|
{
|
||||||
|
got_list = 0;
|
||||||
|
goto skip_enumerant;
|
||||||
|
}
|
||||||
|
value = (int)MD_CStyleIntFromString(value_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set next implicit value
|
||||||
|
next_implicit_value = value + 1;
|
||||||
|
|
||||||
|
// save enumerant
|
||||||
|
if (got_list)
|
||||||
|
{
|
||||||
|
GEN_TypeEnumerant *enumerant = MD_PushArray(arena, GEN_TypeEnumerant, 1);
|
||||||
|
enumerant->node = enumerant_node;
|
||||||
|
enumerant->value = value;
|
||||||
|
MD_QueuePush(first_enumerant, last_enumerant, enumerant);
|
||||||
|
enumerant_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_enumerant:;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the list
|
||||||
|
if (got_list)
|
||||||
|
{
|
||||||
|
type->first_enumerant = first_enumerant;
|
||||||
|
type->last_enumerant = last_enumerant;
|
||||||
|
type->enumerant_count = enumerant_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ generators ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
gen_type_definitions_from_types(FILE *out, GEN_TypeInfo *first_type)
|
gen_type_definitions_from_types(FILE *out, GEN_TypeInfo *first_type)
|
||||||
@@ -329,14 +623,6 @@ gen_type_info_definitions_from_types(FILE *out, GEN_TypeInfo *first_type)
|
|||||||
|
|
||||||
//~ main //////////////////////////////////////////////////////////////////////
|
//~ 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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -379,266 +665,19 @@ main(int argc, char **argv)
|
|||||||
map_map = MD_MapMake(arena);
|
map_map = MD_MapMake(arena);
|
||||||
|
|
||||||
// gather types & maps
|
// gather types & maps
|
||||||
for(MD_EachNode(ref, list->first_child))
|
gen_gather_types_and_maps(list);
|
||||||
{
|
|
||||||
MD_Node *root = MD_ResolveNodeFromReference(ref);
|
|
||||||
for(MD_EachNode(node, root->first_child))
|
|
||||||
{
|
|
||||||
// gather type
|
|
||||||
MD_Node *type_tag = MD_TagFromString(node, MD_S8Lit("type"), 0);
|
|
||||||
|
|
||||||
if (!MD_NodeIsNil(type_tag))
|
|
||||||
{
|
|
||||||
GEN_TypeKind kind = GEN_TypeKind_Null;
|
|
||||||
MD_Node *tag_arg_node = type_tag->first_child;
|
|
||||||
MD_String8 tag_arg_str = tag_arg_node->string;
|
|
||||||
if (MD_S8Match(tag_arg_str, MD_S8Lit("basic"), 0))
|
|
||||||
{
|
|
||||||
kind = GEN_TypeKind_Basic;
|
|
||||||
}
|
|
||||||
else if (MD_S8Match(tag_arg_str, MD_S8Lit("struct"), 0))
|
|
||||||
{
|
|
||||||
kind = GEN_TypeKind_Struct;
|
|
||||||
}
|
|
||||||
else if (MD_S8Match(tag_arg_str, MD_S8Lit("enum"), 0))
|
|
||||||
{
|
|
||||||
kind = GEN_TypeKind_Enum;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kind == GEN_TypeKind_Null)
|
|
||||||
{
|
|
||||||
MD_CodeLoc loc = MD_CodeLocFromNode(node);
|
|
||||||
MD_PrintMessageFmt(error_file, loc, MD_MessageKind_Error,
|
|
||||||
"Unrecognized type kind '%.*s'\n",
|
|
||||||
MD_S8VArg(tag_arg_str));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GEN_TypeInfo *type_info = MD_PushArrayZero(arena, GEN_TypeInfo, 1);
|
|
||||||
type_info->kind = kind;
|
|
||||||
type_info->node = node;
|
|
||||||
|
|
||||||
MD_QueuePush(first_type, last_type, type_info);
|
|
||||||
MD_MapInsert(arena, &type_map, MD_MapKeyStr(node->string), type_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// gather map
|
|
||||||
MD_Node *map_tag = MD_TagFromString(node, MD_S8Lit("map"), 0);
|
|
||||||
|
|
||||||
if (!MD_NodeIsNil(map_tag))
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
{
|
|
||||||
MD_Node *error_at = 0;
|
|
||||||
if (MD_NodeIsNil(in))
|
|
||||||
{
|
|
||||||
error_at = map_tag;
|
|
||||||
}
|
|
||||||
else if (!MD_S8Match(arrow->string, MD_S8Lit("->"), 0) ||
|
|
||||||
MD_NodeIsNil(out))
|
|
||||||
{
|
|
||||||
error_at = in;
|
|
||||||
}
|
|
||||||
if (error_at != 0)
|
|
||||||
{
|
|
||||||
MD_CodeLoc loc = MD_CodeLocFromNode(error_at);
|
|
||||||
MD_PrintMessage(error_file, loc, MD_MessageKind_Error,
|
|
||||||
MD_S8Lit("Map's type should be specified like: `In -> Out`"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for named children in the map tag
|
|
||||||
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"));
|
|
||||||
|
|
||||||
// save a new map
|
|
||||||
GEN_MapInfo *map_info = MD_PushArrayZero(arena, GEN_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO no duplicate member names check
|
// TODO no duplicate member names check
|
||||||
|
|
||||||
// TODO basic type sizes
|
// TODO basic type sizes
|
||||||
|
|
||||||
// build member lists
|
// build member lists
|
||||||
for (GEN_TypeInfo *type = first_type;
|
gen_gather_struct_members();
|
||||||
type != 0;
|
|
||||||
type = type->next)
|
|
||||||
{
|
|
||||||
if (type->kind == GEN_TypeKind_Struct)
|
|
||||||
{
|
|
||||||
// build the list
|
|
||||||
MD_b32 got_list = 1;
|
|
||||||
GEN_TypeMember *first_member = 0;
|
|
||||||
GEN_TypeMember *last_member = 0;
|
|
||||||
int member_count = 0;
|
|
||||||
|
|
||||||
MD_Node *type_root_node = type->node;
|
|
||||||
for (MD_EachNode(member_node, type_root_node->first_child))
|
|
||||||
{
|
|
||||||
MD_Node *type_name_node = member_node->first_child;
|
|
||||||
|
|
||||||
// missing type node?
|
|
||||||
if (MD_NodeIsNil(type_name_node))
|
|
||||||
{
|
|
||||||
MD_CodeLoc loc = MD_CodeLocFromNode(member_node);
|
|
||||||
MD_PrintMessage(error_file, loc, MD_MessageKind_Error,
|
|
||||||
MD_S8Lit("Missing type name for member"));
|
|
||||||
got_list = 0;
|
|
||||||
goto skip_member;
|
|
||||||
}
|
|
||||||
|
|
||||||
// has type node:
|
|
||||||
MD_String8 type_name = type_name_node->string;
|
|
||||||
MD_MapSlot *type_info_slot = (MD_MapSlot*)MD_MapLookup(&type_map, MD_MapKeyStr(type_name));
|
|
||||||
|
|
||||||
// could not resolve type?
|
|
||||||
if (type_info_slot == 0)
|
|
||||||
{
|
|
||||||
MD_CodeLoc loc = MD_CodeLocFromNode(type_name_node);
|
|
||||||
MD_PrintMessageFmt(error_file, loc, MD_MessageKind_Error,
|
|
||||||
"Could not resolve type name '%.*s'", MD_S8VArg(type_name));
|
|
||||||
got_list = 0;
|
|
||||||
goto skip_member;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolved type:
|
|
||||||
if (got_list)
|
|
||||||
{
|
|
||||||
GEN_TypeInfo *type_info = (GEN_TypeInfo*)type_info_slot->val;
|
|
||||||
|
|
||||||
MD_Node *array_count = MD_NilNode();
|
|
||||||
MD_Node *array_tag = MD_TagFromString(type_name_node, MD_S8Lit("array"), 0);
|
|
||||||
if (!MD_NodeIsNil(array_tag))
|
|
||||||
{
|
|
||||||
MD_Node *array_count_referencer = array_tag->first_child;
|
|
||||||
if (array_count_referencer->string.size == 0)
|
|
||||||
{
|
|
||||||
MD_CodeLoc loc = MD_CodeLocFromNode(array_tag);
|
|
||||||
MD_PrintMessage(error_file, loc, MD_MessageKind_Error,
|
|
||||||
MD_S8Lit("array tags must specify a parameter for their count"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
array_count = MD_ChildFromString(type_root_node, array_count_referencer->string, 0);
|
|
||||||
if (MD_NodeIsNil(array_count))
|
|
||||||
{
|
|
||||||
MD_CodeLoc loc = MD_CodeLocFromNode(array_count_referencer);
|
|
||||||
MD_PrintMessageFmt(error_file, loc, MD_MessageKind_Error,
|
|
||||||
"'%.*s' is not a member of %.*s",
|
|
||||||
MD_S8VArg(array_count_referencer->string), MD_S8VArg(type_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GEN_TypeMember *member = MD_PushArray(arena, GEN_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_member:;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the list
|
|
||||||
if (got_list)
|
|
||||||
{
|
|
||||||
type->first_member = first_member;
|
|
||||||
type->last_member = last_member;
|
|
||||||
type->member_count = member_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO check enum base types
|
// TODO check enum base types
|
||||||
|
|
||||||
// build enumerant lists
|
// build enumerant lists
|
||||||
for (GEN_TypeInfo *type = first_type;
|
gen_gather_enum_members();
|
||||||
type != 0;
|
|
||||||
type = type->next)
|
|
||||||
{
|
|
||||||
if (type->kind == GEN_TypeKind_Enum)
|
|
||||||
{
|
|
||||||
|
|
||||||
// build the list
|
|
||||||
MD_b32 got_list = 1;
|
|
||||||
GEN_TypeEnumerant *first_enumerant = 0;
|
|
||||||
GEN_TypeEnumerant *last_enumerant = 0;
|
|
||||||
int enumerant_count = 0;
|
|
||||||
|
|
||||||
int next_implicit_value = 0;
|
|
||||||
|
|
||||||
MD_Node *type_root_node = type->node;
|
|
||||||
for (MD_EachNode(enumerant_node, type_root_node->first_child))
|
|
||||||
{
|
|
||||||
MD_Node *value_node = enumerant_node->first_child;
|
|
||||||
int value = 0;
|
|
||||||
|
|
||||||
// missing value node?
|
|
||||||
if (MD_NodeIsNil(value_node))
|
|
||||||
{
|
|
||||||
value = next_implicit_value;
|
|
||||||
next_implicit_value += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// has value node
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MD_String8 value_string = value_node->string;
|
|
||||||
if (!MD_StringIsCStyleInt(value_string))
|
|
||||||
{
|
|
||||||
got_list = 0;
|
|
||||||
goto skip_enumerant;
|
|
||||||
}
|
|
||||||
value = (int)MD_CStyleIntFromString(value_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set next implicit value
|
|
||||||
next_implicit_value = value + 1;
|
|
||||||
|
|
||||||
// save enumerant
|
|
||||||
if (got_list)
|
|
||||||
{
|
|
||||||
GEN_TypeEnumerant *enumerant = MD_PushArray(arena, GEN_TypeEnumerant, 1);
|
|
||||||
enumerant->node = enumerant_node;
|
|
||||||
enumerant->value = value;
|
|
||||||
MD_QueuePush(first_enumerant, last_enumerant, enumerant);
|
|
||||||
enumerant_count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_enumerant:;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the list
|
|
||||||
if (got_list)
|
|
||||||
{
|
|
||||||
type->first_enumerant = first_enumerant;
|
|
||||||
type->last_enumerant = last_enumerant;
|
|
||||||
type->enumerant_count = enumerant_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO check maps & build case lists
|
// TODO check maps & build case lists
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user