Support basic container template introspection

This commit is contained in:
doyle 2019-05-02 20:39:31 +10:00
parent bb9fd123e3
commit 1c573478c6

View File

@ -69,12 +69,20 @@ struct DqnInspectMember
int name_len; int name_len;
int pod_struct_offset; int pod_struct_offset;
// Includes the template expression if there is any in declaration
enum struct DqnInspectDeclType decl_type; enum struct DqnInspectDeclType decl_type;
char const * decl_type_str; char const * decl_type_str;
int decl_type_len; int decl_type_len;
int decl_type_sizeof; int decl_type_sizeof;
char const * template_expr;
int template_expr_len; // If there's a template this will be the topmost of the declaration i.e. for vector<int>
// this will just be DqnInspectDeclType::vector_
enum struct DqnInspectDeclType template_parent_decl_type;
enum struct DqnInspectDeclType template_child_decl_type;
char const * template_child_expr;
int template_child_expr_len;
int array_dimensions; // > 0 means array int array_dimensions; // > 0 means array
// NOTE: Supports maximum of 8 dimensions. 0 if unknown (i.e. just a pointer) // NOTE: Supports maximum of 8 dimensions. 0 if unknown (i.e. just a pointer)
@ -104,6 +112,9 @@ inline DqnInspectMetadata const *DqnInspectMember_FindMetadata(DqnInspectMember
DqnInspectMetadata const *metadata = member->metadata + metadata_index; DqnInspectMetadata const *metadata = member->metadata + metadata_index;
if (metadata->meta_type == meta_type) if (metadata->meta_type == meta_type)
{ {
if (!decl_types || num_decl_types == 0)
return metadata;
for (size_t decl_type_index = 0; decl_type_index < num_decl_types; ++decl_type_index) for (size_t decl_type_index = 0; decl_type_index < num_decl_types; ++decl_type_index)
{ {
DqnInspectDeclType const *decl_type = decl_types + decl_type_index; DqnInspectDeclType const *decl_type = decl_types + decl_type_index;
@ -463,7 +474,7 @@ struct CPPVariableDecl
b32 type_has_const; b32 type_has_const;
Slice<char> type; Slice<char> type;
Slice<char> name; Slice<char> name;
Slice<char> template_expr; Slice<char> template_child_expr;
b32 array_has_const; b32 array_has_const;
int array_dimensions; int array_dimensions;
b32 array_dimensions_has_compile_time_size[8]; // TODO(doyle): Max of 8 dimensions, whotf needs more? b32 array_dimensions_has_compile_time_size[8]; // TODO(doyle): Max of 8 dimensions, whotf needs more?
@ -688,7 +699,7 @@ CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *to
CPPToken variable_type = token; CPPToken variable_type = token;
for (int total_asterisks_count = 0;;) for (int total_asterisks_count = 0;;)
{ {
Slice<char> variable_template_expr = {}; Slice<char> variable_template_child_expr = {};
if (CPPTokeniser_AcceptTokenIfType(tokeniser, CPPTokenType::LessThan, &token)) if (CPPTokeniser_AcceptTokenIfType(tokeniser, CPPTokenType::LessThan, &token))
{ {
CPPToken template_start_token = token; CPPToken template_start_token = token;
@ -708,8 +719,8 @@ CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *to
char *expr_end = token.str; char *expr_end = token.str;
int expr_len = static_cast<int>(expr_end - expr_start); int expr_len = static_cast<int>(expr_end - expr_start);
variable_template_expr.str = expr_start; variable_template_child_expr.str = expr_start;
variable_template_expr.len = expr_len; variable_template_child_expr.len = expr_len;
} }
} }
@ -801,7 +812,7 @@ CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *to
link->value.type_has_const = type_has_const; link->value.type_has_const = type_has_const;
link->value.type = variable_type_str_lit; link->value.type = variable_type_str_lit;
link->value.name = Slice<char>(variable_name.str, variable_name.len); link->value.name = Slice<char>(variable_name.str, variable_name.len);
link->value.template_expr = variable_template_expr; link->value.template_child_expr = variable_template_child_expr;
link->value.array_has_const = array_has_const; link->value.array_has_const = array_has_const;
link->value.array_dimensions = total_asterisks_count; link->value.array_dimensions = total_asterisks_count;
@ -998,7 +1009,7 @@ b32 ParseCPPVariableType(CPPTokeniser *tokeniser, Slice<char> *type)
// //
// Parse Template If Any // Parse Template If Any
// //
Slice<char> template_expr = {}; Slice<char> template_child_expr = {};
{ {
CPPToken peek_token = CPPTokeniser_PeekToken(tokeniser); CPPToken peek_token = CPPTokeniser_PeekToken(tokeniser);
if (peek_token.type == CPPTokenType::LessThan) if (peek_token.type == CPPTokenType::LessThan)
@ -1020,8 +1031,8 @@ b32 ParseCPPVariableType(CPPTokeniser *tokeniser, Slice<char> *type)
char *expr_end = token.str; char *expr_end = token.str;
int expr_len = static_cast<int>(expr_end - expr_start); int expr_len = static_cast<int>(expr_end - expr_start);
template_expr.str = expr_start; template_child_expr.str = expr_start;
template_expr.len = expr_len; template_child_expr.len = expr_len;
} }
} }
} }
@ -1404,26 +1415,43 @@ char *EnumOrStructOrFunctionLexer(CPPTokeniser *tokeniser, char *ptr, b32 lexing
return ptr; return ptr;
} }
void FprintDeclType(FILE *output_file, Slice<char> const type) void FprintDeclType(FILE *output_file, Slice<char> const type, Slice<char> const template_child_expr)
{ {
for (int i = 0; i < type.len; ++i) Slice<char> const array[] =
{ {
char ch = type.str[i]; type,
if (ch == '*') template_child_expr
{ };
char prev_ch = type.str[i - 1];
if (prev_ch != ' ' && prev_ch != '*') fputc('_', output_file);
fputs("Ptr", output_file); for (int array_index = 0; array_index < ARRAY_COUNT(array); ++array_index)
if (i < (type.len - 1)) fputc('_', output_file); {
} Slice<char> const *slice = array + array_index;
else if (array_index > 0 && slice->len > 0)
fputc('_', output_file);
for (int i = 0; i < slice->len; ++i)
{ {
if (ch == ' ') ch = '_'; char ch = slice->str[i];
fputc(ch, output_file); if (ch == '*')
{
char prev_ch = slice->str[i - 1];
if (prev_ch != ' ' && prev_ch != '*') fputc('_', output_file);
fputs("Ptr", output_file);
if (i < (slice->len - 1)) fputc('_', output_file);
}
else
{
if (ch != '>')
{
if (ch == ' ' || ch == '<') ch = '_';
fputc(ch, output_file);
}
}
} }
} }
fprintf(output_file, "_");
fputc('_', output_file);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -1704,25 +1732,26 @@ int main(int argc, char *argv[])
link = link->next) link = link->next)
{ {
CPPVariableDecl const *decl = &link->value; CPPVariableDecl const *decl = &link->value;
Slice<char> type_name = {};
#if 0 unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s", decl->type.len, decl->type.str));
if (decl->template_expr.len > 0) type_name = Asprintf(&global_main_arena, "%.*s<%.*s>", decl->type.len, decl->type.str, decl->template_expr.len, decl->template_expr.str); if (decl->template_child_expr.len > 0)
else type_name = Asprintf(&global_main_arena, "%.*s", decl->type.len, decl->type.str); {
#else if (!CharIsDigit(decl->template_child_expr.str[0]))
// TODO(doyle): Hmmm. Maybe we don't serialise the template expression since they can become arbitrarily complex unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s", decl->template_child_expr.len, decl->template_child_expr.str));
type_name = Asprintf(&global_main_arena, "%.*s", decl->type.len, decl->type.str); unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s<%.*s>", decl->type.len, decl->type.str, decl->template_child_expr.len, decl->template_child_expr.str));
#endif }
unique_decl_type_table.insert(type_name);
for (CPPDeclLinkedList<CPPVariableDecl> const *meta_link = link->metadata_list; for (CPPDeclLinkedList<CPPVariableDecl> const *meta_link = link->metadata_list;
meta_link; meta_link;
meta_link = meta_link->next) meta_link = meta_link->next)
{ {
CPPVariableDecl const *meta_decl = &meta_link->value; CPPVariableDecl const *meta_decl = &meta_link->value;
Slice<char> meta_type_name = {}; unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s", meta_decl->type.len, meta_decl->type.str));
if (meta_decl->template_expr.len > 0) meta_type_name = Asprintf(&global_main_arena, "%.*s<%.*s>", meta_decl->type.len, meta_decl->type.str, meta_decl->template_expr.len, meta_decl->template_expr.str); if (meta_decl->template_child_expr.len > 0)
else meta_type_name = Asprintf(&global_main_arena, "%.*s", meta_decl->type.len, meta_decl->type.str); {
unique_decl_type_table.insert(meta_type_name); unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s", meta_decl->template_child_expr.len, meta_decl->template_child_expr.str));
unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s<%.*s>", meta_decl->type.len, meta_decl->type.str, meta_decl->template_child_expr.len, meta_decl->template_child_expr.str));
}
} }
} }
} }
@ -1733,10 +1762,11 @@ int main(int argc, char *argv[])
FprintfIndented(output_file, indent_level, "enum struct DqnInspectDeclType\n{\n"); FprintfIndented(output_file, indent_level, "enum struct DqnInspectDeclType\n{\n");
indent_level++; indent_level++;
FprintfIndented(output_file, indent_level, "NotAvailable_,\n");
for (Slice<char> const &type : unique_decl_type_table) for (Slice<char> const &type : unique_decl_type_table)
{ {
FprintfIndented(output_file, indent_level, ""); FprintfIndented(output_file, indent_level, "");
FprintDeclType(output_file, type); FprintDeclType(output_file, type, {});
fprintf(output_file, ",\n"); fprintf(output_file, ",\n");
} }
indent_level--; indent_level--;
@ -2084,7 +2114,7 @@ int main(int argc, char *argv[])
{ {
CPPVariableDecl const *metadata = &metadata_link->value; CPPVariableDecl const *metadata = &metadata_link->value;
FprintfIndented(output_file, indent_level, "{ DqnInspectDeclType::"); FprintfIndented(output_file, indent_level, "{ DqnInspectDeclType::");
FprintDeclType(output_file, metadata->type); FprintDeclType(output_file, metadata->type, metadata->template_child_expr);
fprintf(output_file, fprintf(output_file,
", DqnInspectMetaType::%.*s, &DqnInspectMetadata_%.*s_%.*s_%.*s},\n", ", DqnInspectMetaType::%.*s, &DqnInspectMetadata_%.*s_%.*s_%.*s},\n",
metadata->name.len, metadata->name.str, metadata->name.len, metadata->name.str,
@ -2115,16 +2145,59 @@ int main(int argc, char *argv[])
FprintfIndented(output_file, indent_level, "DqnInspectMemberType::%.*s_%.*s, ", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str); FprintfIndented(output_file, indent_level, "DqnInspectMemberType::%.*s_%.*s, ", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str);
fprintf(output_file, "STR_AND_LEN(\"%.*s\"),\n", decl->name.len, decl->name.str); fprintf(output_file, "STR_AND_LEN(\"%.*s\"),\n", decl->name.len, decl->name.str);
FprintfIndented(output_file, indent_level, "offsetof(%.*s, %.*s),\n", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str);
FprintfIndented(output_file, indent_level, "DqnInspectDeclType::");
FprintDeclType(output_file, decl->type);
fprintf(output_file, ", STR_AND_LEN(\"%.*s\"),\n", decl->type.len, decl->type.str);
FprintfIndented(output_file, indent_level, "sizeof(((%.*s *)0)->%.*s), // decl_type_sizeof\n", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str);
if (decl->template_expr.len <= 0) // NOTE: Write pod_struct_offset
FprintfIndented(output_file, indent_level, "nullptr, 0, // template_expr and template_expr_len\n"); {
else FprintfIndented(output_file, indent_level, "offsetof(%.*s, %.*s),\n", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str);
FprintfIndented(output_file, indent_level, "STR_AND_LEN(\"%.*s\"), // template_expr\n", decl->template_expr.len, decl->template_expr.str); }
// NOTE: Write decl_type
{
FprintfIndented(output_file, indent_level, "DqnInspectDeclType::");
FprintDeclType(output_file, decl->type, decl->template_child_expr);
}
// NOTE: Write decl_type_str, decl_type_len
{
if (decl->template_child_expr.len > 0)
fprintf(output_file, ", STR_AND_LEN(\"%.*s<%.*s>\"),\n", decl->type.len, decl->type.str, decl->template_child_expr.len, decl->template_child_expr.str);
else
fprintf(output_file, ", STR_AND_LEN(\"%.*s\"),\n", decl->type.len, decl->type.str);
}
// NOTE: Write decl_type_sizeof
{
FprintfIndented(output_file, indent_level, "sizeof(((%.*s *)0)->%.*s), // full_decl_type_sizeof\n", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str);
}
// NOTE: Write template_parent_decl_type
{
FprintfIndented(output_file, indent_level, "DqnInspectDeclType::");
FprintDeclType(output_file, decl->type, {});
fprintf(output_file, ", ");
}
// NOTE: Write template_decl_type
{
if (decl->template_child_expr.len > 0 && !CharIsDigit(decl->template_child_expr.str[0]))
{
fprintf(output_file, "DqnInspectDeclType::");
FprintDeclType(output_file, decl->template_child_expr, {});
}
else
{
fprintf(output_file, "DqnInspectDeclType::NotAvailable_");
}
fprintf(output_file, ",\n");
}
// NOTE: Write template_child_expr, template_child_expr_len
{
if (decl->template_child_expr.len > 0)
FprintfIndented(output_file, indent_level, "STR_AND_LEN(\"%.*s\"), // template_child_expr\n", decl->template_child_expr.len, decl->template_child_expr.str);
else
FprintfIndented(output_file, indent_level, "nullptr, 0, // template_child_expr and template_child_expr_len\n");
}
FprintfIndented(output_file, indent_level, "%d, // array_dimensions\n", decl->array_dimensions); FprintfIndented(output_file, indent_level, "%d, // array_dimensions\n", decl->array_dimensions);