Support basic container template introspection
This commit is contained in:
parent
bb9fd123e3
commit
1c573478c6
@ -69,12 +69,20 @@ struct DqnInspectMember
|
||||
int name_len;
|
||||
int pod_struct_offset;
|
||||
|
||||
// Includes the template expression if there is any in declaration
|
||||
enum struct DqnInspectDeclType decl_type;
|
||||
char const * decl_type_str;
|
||||
int decl_type_len;
|
||||
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
|
||||
|
||||
// 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;
|
||||
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)
|
||||
{
|
||||
DqnInspectDeclType const *decl_type = decl_types + decl_type_index;
|
||||
@ -463,7 +474,7 @@ struct CPPVariableDecl
|
||||
b32 type_has_const;
|
||||
Slice<char> type;
|
||||
Slice<char> name;
|
||||
Slice<char> template_expr;
|
||||
Slice<char> template_child_expr;
|
||||
b32 array_has_const;
|
||||
int array_dimensions;
|
||||
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;
|
||||
for (int total_asterisks_count = 0;;)
|
||||
{
|
||||
Slice<char> variable_template_expr = {};
|
||||
Slice<char> variable_template_child_expr = {};
|
||||
if (CPPTokeniser_AcceptTokenIfType(tokeniser, CPPTokenType::LessThan, &token))
|
||||
{
|
||||
CPPToken template_start_token = token;
|
||||
@ -708,8 +719,8 @@ CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *to
|
||||
char *expr_end = token.str;
|
||||
int expr_len = static_cast<int>(expr_end - expr_start);
|
||||
|
||||
variable_template_expr.str = expr_start;
|
||||
variable_template_expr.len = expr_len;
|
||||
variable_template_child_expr.str = expr_start;
|
||||
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 = variable_type_str_lit;
|
||||
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_dimensions = total_asterisks_count;
|
||||
|
||||
@ -998,7 +1009,7 @@ b32 ParseCPPVariableType(CPPTokeniser *tokeniser, Slice<char> *type)
|
||||
//
|
||||
// Parse Template If Any
|
||||
//
|
||||
Slice<char> template_expr = {};
|
||||
Slice<char> template_child_expr = {};
|
||||
{
|
||||
CPPToken peek_token = CPPTokeniser_PeekToken(tokeniser);
|
||||
if (peek_token.type == CPPTokenType::LessThan)
|
||||
@ -1020,8 +1031,8 @@ b32 ParseCPPVariableType(CPPTokeniser *tokeniser, Slice<char> *type)
|
||||
char *expr_end = token.str;
|
||||
int expr_len = static_cast<int>(expr_end - expr_start);
|
||||
|
||||
template_expr.str = expr_start;
|
||||
template_expr.len = expr_len;
|
||||
template_child_expr.str = expr_start;
|
||||
template_child_expr.len = expr_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1404,26 +1415,43 @@ char *EnumOrStructOrFunctionLexer(CPPTokeniser *tokeniser, char *ptr, b32 lexing
|
||||
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];
|
||||
if (ch == '*')
|
||||
{
|
||||
char prev_ch = type.str[i - 1];
|
||||
if (prev_ch != ' ' && prev_ch != '*') fputc('_', output_file);
|
||||
type,
|
||||
template_child_expr
|
||||
};
|
||||
|
||||
fputs("Ptr", output_file);
|
||||
if (i < (type.len - 1)) fputc('_', output_file);
|
||||
}
|
||||
else
|
||||
for (int array_index = 0; array_index < ARRAY_COUNT(array); ++array_index)
|
||||
{
|
||||
Slice<char> const *slice = array + array_index;
|
||||
if (array_index > 0 && slice->len > 0)
|
||||
fputc('_', output_file);
|
||||
|
||||
for (int i = 0; i < slice->len; ++i)
|
||||
{
|
||||
if (ch == ' ') ch = '_';
|
||||
fputc(ch, output_file);
|
||||
char ch = slice->str[i];
|
||||
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[])
|
||||
@ -1704,25 +1732,26 @@ int main(int argc, char *argv[])
|
||||
link = link->next)
|
||||
{
|
||||
CPPVariableDecl const *decl = &link->value;
|
||||
Slice<char> type_name = {};
|
||||
#if 0
|
||||
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);
|
||||
else type_name = Asprintf(&global_main_arena, "%.*s", decl->type.len, decl->type.str);
|
||||
#else
|
||||
// TODO(doyle): Hmmm. Maybe we don't serialise the template expression since they can become arbitrarily complex
|
||||
type_name = Asprintf(&global_main_arena, "%.*s", decl->type.len, decl->type.str);
|
||||
#endif
|
||||
unique_decl_type_table.insert(type_name);
|
||||
|
||||
unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s", decl->type.len, decl->type.str));
|
||||
if (decl->template_child_expr.len > 0)
|
||||
{
|
||||
if (!CharIsDigit(decl->template_child_expr.str[0]))
|
||||
unique_decl_type_table.insert(Asprintf(&global_main_arena, "%.*s", decl->template_child_expr.len, decl->template_child_expr.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));
|
||||
}
|
||||
|
||||
for (CPPDeclLinkedList<CPPVariableDecl> const *meta_link = link->metadata_list;
|
||||
meta_link;
|
||||
meta_link = meta_link->next)
|
||||
{
|
||||
CPPVariableDecl const *meta_decl = &meta_link->value;
|
||||
Slice<char> meta_type_name = {};
|
||||
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);
|
||||
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->type.len, meta_decl->type.str));
|
||||
if (meta_decl->template_child_expr.len > 0)
|
||||
{
|
||||
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");
|
||||
indent_level++;
|
||||
FprintfIndented(output_file, indent_level, "NotAvailable_,\n");
|
||||
for (Slice<char> const &type : unique_decl_type_table)
|
||||
{
|
||||
FprintfIndented(output_file, indent_level, "");
|
||||
FprintDeclType(output_file, type);
|
||||
FprintDeclType(output_file, type, {});
|
||||
fprintf(output_file, ",\n");
|
||||
}
|
||||
indent_level--;
|
||||
@ -2084,7 +2114,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
CPPVariableDecl const *metadata = &metadata_link->value;
|
||||
FprintfIndented(output_file, indent_level, "{ DqnInspectDeclType::");
|
||||
FprintDeclType(output_file, metadata->type);
|
||||
FprintDeclType(output_file, metadata->type, metadata->template_child_expr);
|
||||
fprintf(output_file,
|
||||
", DqnInspectMetaType::%.*s, &DqnInspectMetadata_%.*s_%.*s_%.*s},\n",
|
||||
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);
|
||||
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)
|
||||
FprintfIndented(output_file, indent_level, "nullptr, 0, // template_expr and template_expr_len\n");
|
||||
else
|
||||
FprintfIndented(output_file, indent_level, "STR_AND_LEN(\"%.*s\"), // template_expr\n", decl->template_expr.len, decl->template_expr.str);
|
||||
// NOTE: Write pod_struct_offset
|
||||
{
|
||||
FprintfIndented(output_file, indent_level, "offsetof(%.*s, %.*s),\n", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user