Align nicely generated prototypes to ease reading
This commit is contained in:
parent
a91eb241c4
commit
a38ef363db
@ -266,8 +266,8 @@ struct DqnInspect_Struct
|
|||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(doyle): For compiler testing
|
// NOTE(doyle): For compiler testing
|
||||||
// #include "../Data/DqnInspect_TestData.h"
|
#include "../Data/DqnInspect_TestData.h"
|
||||||
// #include "../Data/DqnInspect_TestDataGenerated.cpp"
|
#include "../Data/DqnInspect_TestDataGenerated.cpp"
|
||||||
|
|
||||||
#ifdef DQN_INSPECT_EXECUTABLE_IMPLEMENTATION
|
#ifdef DQN_INSPECT_EXECUTABLE_IMPLEMENTATION
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
@ -278,6 +278,7 @@ struct DqnInspect_Struct
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using usize = size_t;
|
using usize = size_t;
|
||||||
using isize = ptrdiff_t;
|
using isize = ptrdiff_t;
|
||||||
@ -742,35 +743,72 @@ struct MetadataEntry
|
|||||||
FixedArray<CPPDeclToMetaValue, 32> cpp_decl_to_val;
|
FixedArray<CPPDeclToMetaValue, 32> cpp_decl_to_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ParseCPPEnum(CPPTokeniser *tokeniser)
|
enum struct ParsedResultType
|
||||||
{
|
{
|
||||||
|
Invalid,
|
||||||
|
Struct,
|
||||||
|
Enum,
|
||||||
|
FunctionPrototype,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParsedEnum
|
||||||
|
{
|
||||||
|
b32 struct_or_class_decl;
|
||||||
|
StringLiteral name;
|
||||||
|
CPPDeclLinkedList<StringLiteral> *members;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParsedStruct
|
||||||
|
{
|
||||||
|
StringLiteral name;
|
||||||
|
CPPDeclLinkedList<CPPVariableDecl> *members;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ParsedFunctionPrototype
|
||||||
|
{
|
||||||
|
StringLiteral return_type;
|
||||||
|
StringLiteral name;
|
||||||
|
CPPDeclLinkedList<CPPVariableDecl> *members;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParsedResult
|
||||||
|
{
|
||||||
|
ParsedResultType type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ParsedEnum parsed_enum;
|
||||||
|
ParsedFunctionPrototype parsed_func_prototype;
|
||||||
|
ParsedStruct parsed_struct;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
b32 ParseCPPEnum(CPPTokeniser *tokeniser, ParsedEnum *parsed_enum)
|
||||||
|
{
|
||||||
|
*parsed_enum = {};
|
||||||
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier) || !IsIdentifierToken(token, STR_LITERAL("enum")))
|
if (!ExpectToken(token, CPPTokenType::Identifier) || !IsIdentifierToken(token, STR_LITERAL("enum")))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
token = CPPTokeniser_NextToken(tokeniser);
|
||||||
b32 enum_is_struct_or_class = false;
|
|
||||||
|
|
||||||
if (IsIdentifierToken(token, STR_LITERAL("class")) ||
|
if (IsIdentifierToken(token, STR_LITERAL("class")) ||
|
||||||
IsIdentifierToken(token, STR_LITERAL("struct")))
|
IsIdentifierToken(token, STR_LITERAL("struct")))
|
||||||
{
|
{
|
||||||
enum_is_struct_or_class = true;
|
parsed_enum->struct_or_class_decl = true;
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
token = CPPTokeniser_NextToken(tokeniser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier))
|
if (!ExpectToken(token, CPPTokenType::Identifier))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
int original_indent_level = tokeniser->indent_level;
|
int original_indent_level = tokeniser->indent_level;
|
||||||
CPPToken const enum_name = token;
|
CPPToken const enum_name = token;
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
token = CPPTokeniser_NextToken(tokeniser);
|
||||||
|
|
||||||
if (!ExpectToken(token, CPPTokenType::LeftBrace))
|
if (!ExpectToken(token, CPPTokenType::LeftBrace))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
CPPDeclLinkedList<StringLiteral> *enum_members = nullptr;
|
|
||||||
MemArenaScopedRegion mem_region = MemArena_MakeScopedRegion(&global_main_arena);
|
|
||||||
|
|
||||||
|
parsed_enum->name = StringLiteral(enum_name.str, enum_name.len);
|
||||||
{
|
{
|
||||||
CPPDeclLinkedList<StringLiteral> *link_iterator = nullptr;
|
CPPDeclLinkedList<StringLiteral> *link_iterator = nullptr;
|
||||||
for (token = CPPTokeniser_NextToken(tokeniser);
|
for (token = CPPTokeniser_NextToken(tokeniser);
|
||||||
@ -781,7 +819,7 @@ void ParseCPPEnum(CPPTokeniser *tokeniser)
|
|||||||
{
|
{
|
||||||
auto *link = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, CPPDeclLinkedList<StringLiteral>);
|
auto *link = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, CPPDeclLinkedList<StringLiteral>);
|
||||||
*link = {};
|
*link = {};
|
||||||
if (!link_iterator) enum_members = link; // Set members to first linked list entry
|
if (!link_iterator) parsed_enum->members = link; // Set members to first linked list entry
|
||||||
else link_iterator->next = link;
|
else link_iterator->next = link;
|
||||||
link_iterator = link;
|
link_iterator = link;
|
||||||
|
|
||||||
@ -795,159 +833,7 @@ void ParseCPPEnum(CPPTokeniser *tokeniser)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
return true;
|
||||||
// Write Stringified Enum Array
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "char const *DqnInspect_%.*s_Strings[] = {", enum_name.len, enum_name.str);
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
for (CPPDeclLinkedList<StringLiteral> *link = enum_members; link; link = link->next)
|
|
||||||
{
|
|
||||||
StringLiteral enum_value = link->value;
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "\"%.*s\", ", enum_value.len, enum_value.str);
|
|
||||||
}
|
|
||||||
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "};\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write InspectEnumString Function
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "char const *DqnInspect_EnumString(%.*s val)\n{\n", enum_name.len, enum_name.str);
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
DEFER
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "return nullptr;\n");
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "}\n\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SourceCode
|
|
||||||
{
|
|
||||||
StringLiteral decl;
|
|
||||||
StringLiteral enum_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
LinkedList<SourceCode> src_code = {};
|
|
||||||
int longest_decl_len = 0;
|
|
||||||
{
|
|
||||||
LinkedList<SourceCode> *curr_src_code = nullptr;
|
|
||||||
char const *fmt = (enum_is_struct_or_class) ? "if (val == %.*s::%.*s) " : "if (val == %.*s) ";
|
|
||||||
for (CPPDeclLinkedList<StringLiteral> *link = enum_members; link; link = link->next)
|
|
||||||
{
|
|
||||||
if (!curr_src_code) curr_src_code = &src_code;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
curr_src_code->next = static_cast<LinkedList<SourceCode> *>( MemArena_Alloc(&global_main_arena, sizeof(*curr_src_code)));
|
|
||||||
curr_src_code = curr_src_code->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringLiteral enum_value = link->value;
|
|
||||||
int required_len = 0;
|
|
||||||
|
|
||||||
if (enum_is_struct_or_class) required_len = snprintf(nullptr, 0, fmt, enum_name.len, enum_name.str, enum_value.len, enum_value.str) + 1;
|
|
||||||
else required_len = snprintf(nullptr, 0, fmt, enum_value.len, enum_value.str) + 1;
|
|
||||||
|
|
||||||
longest_decl_len = INSPECT_MAX(longest_decl_len, required_len);
|
|
||||||
curr_src_code->value.decl.str = MEM_ARENA_ALLOC_ARRAY(&global_main_arena, char, required_len);
|
|
||||||
curr_src_code->value.decl.len = required_len;
|
|
||||||
curr_src_code->value.enum_value = enum_value;
|
|
||||||
|
|
||||||
if (enum_is_struct_or_class) snprintf(curr_src_code->value.decl.str, curr_src_code->value.decl.len, fmt, enum_name.len, enum_name.str, enum_value.len, enum_value.str);
|
|
||||||
else snprintf(curr_src_code->value.decl.str, curr_src_code->value.decl.len, fmt, enum_value.len, enum_value.str);
|
|
||||||
}
|
|
||||||
curr_src_code->next = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int enum_index = 0;
|
|
||||||
for (LinkedList<SourceCode> *src_code_ptr = &src_code;
|
|
||||||
src_code_ptr;
|
|
||||||
src_code_ptr = src_code_ptr->next, ++enum_index)
|
|
||||||
{
|
|
||||||
StringLiteral enum_value = src_code_ptr->value.enum_value;
|
|
||||||
int padding = longest_decl_len - src_code_ptr->value.decl.len;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "%.*s%*s", src_code_ptr->value.decl.len, src_code_ptr->value.decl.str, padding, "");
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser,
|
|
||||||
"return DqnInspect_%.*s_Strings[%d]; // \"%.*s\"\n",
|
|
||||||
enum_name.len, enum_name.str,
|
|
||||||
enum_index,
|
|
||||||
enum_value.len, enum_value.str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write User Annotated Metadata Getter Functions
|
|
||||||
//
|
|
||||||
{
|
|
||||||
FixedArray<MetadataEntry, 32> metadata_entries = {};
|
|
||||||
for (CPPDeclLinkedList<StringLiteral> *link = enum_members;
|
|
||||||
link;
|
|
||||||
link = link->next)
|
|
||||||
{
|
|
||||||
for (CPPInspectMetadataEntry const &inspect_entry : link->metadata_array)
|
|
||||||
{
|
|
||||||
MetadataEntry *metadata_entry_to_append_to = nullptr;
|
|
||||||
for (MetadataEntry &check_metadata_entry : metadata_entries)
|
|
||||||
{
|
|
||||||
if (StrCmp(check_metadata_entry.key, inspect_entry.key))
|
|
||||||
{
|
|
||||||
metadata_entry_to_append_to = &check_metadata_entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!metadata_entry_to_append_to)
|
|
||||||
{
|
|
||||||
metadata_entry_to_append_to = FixedArray_Make(&metadata_entries, 1);
|
|
||||||
metadata_entry_to_append_to->key = inspect_entry.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPDeclToMetaValue decl_to_val = {};
|
|
||||||
decl_to_val.cpp_decl = StringLiteral(link->value.str, link->value.len);
|
|
||||||
decl_to_val.value = inspect_entry.value;
|
|
||||||
FixedArray_Add(&metadata_entry_to_append_to->cpp_decl_to_val, decl_to_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MetadataEntry const &metadata : metadata_entries)
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser,
|
|
||||||
"char const *DqnInspect_%.*sMetadata(%.*s val)\n{\n",
|
|
||||||
metadata.key.len, metadata.key.str,
|
|
||||||
enum_name.len, enum_name.str);
|
|
||||||
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
DEFER
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "return nullptr;\n");
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "}\n\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
for (CPPDeclToMetaValue const &decl_to_val : metadata.cpp_decl_to_val)
|
|
||||||
{
|
|
||||||
StringLiteral const *cpp_decl = &decl_to_val.cpp_decl;
|
|
||||||
StringLiteral const *value = &decl_to_val.value;
|
|
||||||
|
|
||||||
if (enum_is_struct_or_class)
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser,
|
|
||||||
"if (val == %.*s::%.*s) ",
|
|
||||||
enum_name.len, enum_name.str,
|
|
||||||
cpp_decl->len, cpp_decl->str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser,
|
|
||||||
"if (val == %.*s) ",
|
|
||||||
cpp_decl->len, cpp_decl->str);
|
|
||||||
}
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "return \"%.*s\";\n", value->len, value->str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConsumeAsterisks(CPPTokeniser *tokeniser)
|
int ConsumeAsterisks(CPPTokeniser *tokeniser)
|
||||||
@ -1043,7 +929,7 @@ b32 ParseCPPVariableType(CPPTokeniser *tokeniser, StringLiteral *type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
// NOTE(doyle): Doesn't parse the ending semicolon so we can reuse this function for parsing function arguments
|
// NOTE(doyle): Doesn't parse the ending semicolon so we can reuse this function for parsing function arguments
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *tokeniser, b32 parse_function_param)
|
CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *tokeniser, b32 parse_function_param)
|
||||||
@ -1102,11 +988,6 @@ CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *to
|
|||||||
|
|
||||||
CPPTokeniser_NextToken(tokeniser);
|
CPPTokeniser_NextToken(tokeniser);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int break_here = 5;
|
|
||||||
(void)break_here;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate A Member Declaration
|
// Allocate A Member Declaration
|
||||||
auto *link = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, CPPDeclLinkedList<CPPVariableDecl>);
|
auto *link = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, CPPDeclLinkedList<CPPVariableDecl>);
|
||||||
@ -1154,26 +1035,23 @@ CPPDeclLinkedList<CPPVariableDecl> *ParseCPPTypeAndVariableDecl(CPPTokeniser *to
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseCPPStruct(CPPTokeniser *tokeniser)
|
b32 ParseCPPStruct(CPPTokeniser *tokeniser, ParsedStruct *parsed_struct)
|
||||||
{
|
{
|
||||||
|
*parsed_struct = {};
|
||||||
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier) ||
|
if (!ExpectToken(token, CPPTokenType::Identifier) ||
|
||||||
(!IsIdentifierToken(token, STR_LITERAL("struct")) && !IsIdentifierToken(token, STR_LITERAL("class"))))
|
(!IsIdentifierToken(token, STR_LITERAL("struct")) && !IsIdentifierToken(token, STR_LITERAL("class"))))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
int const original_indent_level = tokeniser->indent_level;
|
int const original_indent_level = tokeniser->indent_level;
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
token = CPPTokeniser_NextToken(tokeniser);
|
||||||
|
|
||||||
StringLiteral name = STR_LITERAL("");
|
|
||||||
if (token.type != CPPTokenType::LeftBrace)
|
if (token.type != CPPTokenType::LeftBrace)
|
||||||
{
|
{
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier)) return;
|
if (!ExpectToken(token, CPPTokenType::Identifier)) return false;
|
||||||
name = StringLiteral(token.str, token.len);
|
parsed_struct->name = StringLiteral(token.str, token.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *struct_members = nullptr;
|
|
||||||
MemArenaScopedRegion mem_region = MemArena_MakeScopedRegion(&global_main_arena);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *link_iterator = nullptr;
|
CPPDeclLinkedList<CPPVariableDecl> *link_iterator = nullptr;
|
||||||
for (token = CPPTokeniser_NextToken(tokeniser);
|
for (token = CPPTokeniser_NextToken(tokeniser);
|
||||||
@ -1184,7 +1062,7 @@ void ParseCPPStruct(CPPTokeniser *tokeniser)
|
|||||||
{
|
{
|
||||||
CPPTokeniser_RewindToken(tokeniser);
|
CPPTokeniser_RewindToken(tokeniser);
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *link = ParseCPPTypeAndVariableDecl(tokeniser, false);
|
CPPDeclLinkedList<CPPVariableDecl> *link = ParseCPPTypeAndVariableDecl(tokeniser, false);
|
||||||
if (!struct_members) struct_members = link;
|
if (!parsed_struct->members) parsed_struct->members = link;
|
||||||
if (!link_iterator) link_iterator = link;
|
if (!link_iterator) link_iterator = link;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1197,108 +1075,10 @@ void ParseCPPStruct(CPPTokeniser *tokeniser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): Don't support anonymous/nameless structs yet
|
// TODO(doyle): Don't support anonymous/nameless structs yet
|
||||||
if (name.len == 0)
|
if (parsed_struct->name.len == 0)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
//
|
return true;
|
||||||
// Write DqnInspect_StructMemberMetadata Definition
|
|
||||||
//
|
|
||||||
for (CPPDeclLinkedList<CPPVariableDecl> const *member = struct_members; member; member = member->next)
|
|
||||||
{
|
|
||||||
CPPVariableDecl const *decl = &member->value;
|
|
||||||
if (member->metadata_array.len <= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
CPPTokeniser_SprintfToFile(
|
|
||||||
tokeniser,
|
|
||||||
"DqnInspect_StructMemberMetadata const DqnInspect_%.*s_%.*s_StructMemberMetadata[] =\n{\n",
|
|
||||||
name.len,
|
|
||||||
name.str,
|
|
||||||
decl->name.len,
|
|
||||||
decl->name.str);
|
|
||||||
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
for (CPPInspectMetadataEntry const &entry : member->metadata_array)
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "{\n");
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_StructMemberMetadataType::String,\n");
|
|
||||||
|
|
||||||
// metadata->key
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "STR_AND_LEN(\"%.*s\"), ", entry.key.len, entry.key.str);
|
|
||||||
|
|
||||||
// metadata->value
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "STR_AND_LEN(\"%.*s\"),\n", entry.value.len, entry.value.str);
|
|
||||||
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "},\n");
|
|
||||||
}
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "};\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write DqnInspect_StructMembers Definition
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_StructMember const DqnInspect_%.*s_StructMembers[] =\n{\n", name.len, name.str);
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
|
|
||||||
for (CPPDeclLinkedList<CPPVariableDecl> const *member = struct_members; member; member = member->next)
|
|
||||||
{
|
|
||||||
CPPVariableDecl const *decl = &member->value;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "{\n");
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "STR_AND_LEN(\"%.*s\"), ", decl->type.len, decl->type.str);
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "STR_AND_LEN(\"%.*s\"),\n", decl->name.len, decl->name.str);
|
|
||||||
|
|
||||||
if (decl->template_expr.len <= 0)
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "nullptr, 0, // template_expr and template_expr_len\n");
|
|
||||||
else
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "STR_AND_LEN(\"%.*s\"), // template_expr\n", decl->template_expr.len, decl->template_expr.str);
|
|
||||||
|
|
||||||
if (member->metadata_array.len <= 0) CPPTokeniser_SprintfToFile(tokeniser, "nullptr, 0, // metadata and metadata_len\n");
|
|
||||||
else CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_%.*s_%.*s_StructMemberMetadata, %d,\n", name.len, name.str, decl->name.len, decl->name.str, member->metadata_array.len);
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "%d // array_dimensions\n", decl->array_dimensions);
|
|
||||||
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "},\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "};\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write DqnInspect_Struct Definition
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_Struct const DqnInspect_%.*s_Struct =\n{\n", name.len, name.str);
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "STR_AND_LEN(\"%.*s\"),\n", name.len, name.str);
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_%.*s_StructMembers, // members\n", name.len, name.str);
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "ARRAY_COUNT(DqnInspect_%.*s_StructMembers) // members_len\n", name.len, name.str);
|
|
||||||
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "};\n\n");
|
|
||||||
assert(tokeniser->indent_level == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write DqnInspect_Struct getter
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_Struct const *DqnInspect_GetStruct(%.*s const *val)\n", name.len, name.str);
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "{\n");
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "(void)val;\n");
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "DqnInspect_Struct const *result = &DqnInspect_%.*s_Struct;\n", name.len, name.str);
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "return result;\n");
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "}\n\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkipFunctionParam(CPPTokeniser *tokeniser)
|
void SkipFunctionParam(CPPTokeniser *tokeniser)
|
||||||
@ -1344,11 +1124,12 @@ void SkipFunctionParam(CPPTokeniser *tokeniser)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
b32 ParseCPPInspectPrototype(CPPTokeniser *tokeniser, ParsedFunctionPrototype *parsed_func)
|
||||||
{
|
{
|
||||||
|
*parsed_func = {};
|
||||||
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
||||||
if (!ExpectToken(token, CPPTokenType::InspectGeneratePrototype))
|
if (!ExpectToken(token, CPPTokenType::InspectGeneratePrototype))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
struct FunctionDefaultParam
|
struct FunctionDefaultParam
|
||||||
{
|
{
|
||||||
@ -1356,12 +1137,14 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
|||||||
StringLiteral value;
|
StringLiteral value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// NOTE: Parse default params in the inspect prototype macro
|
||||||
|
//
|
||||||
LinkedList<FunctionDefaultParam> *default_param_list = nullptr;
|
LinkedList<FunctionDefaultParam> *default_param_list = nullptr;
|
||||||
MemArenaScopedRegion mem_region = MemArena_MakeScopedRegion(&global_main_arena);
|
|
||||||
{
|
{
|
||||||
LinkedList<FunctionDefaultParam> *link_iterator = nullptr;
|
LinkedList<FunctionDefaultParam> *link_iterator = nullptr;
|
||||||
if (!CPPTokeniser_AcceptTokenIfType(tokeniser, CPPTokenType::OpenParen, &token))
|
if (!CPPTokeniser_AcceptTokenIfType(tokeniser, CPPTokenType::OpenParen, &token))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
for (token = CPPTokeniser_NextToken(tokeniser);
|
for (token = CPPTokeniser_NextToken(tokeniser);
|
||||||
token.type != CPPTokenType::CloseParen && token.type != CPPTokenType::EndOfStream;
|
token.type != CPPTokenType::CloseParen && token.type != CPPTokenType::EndOfStream;
|
||||||
@ -1419,19 +1202,17 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
|||||||
StringLiteral default_value;
|
StringLiteral default_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
StringLiteral return_type = {};
|
|
||||||
StringLiteral function_name = {};
|
|
||||||
// Grab return type token
|
// Grab return type token
|
||||||
{
|
{
|
||||||
token = CPPTokeniser_PeekToken(tokeniser);
|
token = CPPTokeniser_PeekToken(tokeniser);
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier)) return;
|
if (!ExpectToken(token, CPPTokenType::Identifier)) return false;
|
||||||
if (!ParseCPPVariableType(tokeniser, &return_type)) return;
|
if (!ParseCPPVariableType(tokeniser, &parsed_func->return_type)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab function name token
|
// Grab function name token
|
||||||
{
|
{
|
||||||
token = CPPTokeniser_PeekToken(tokeniser);
|
token = CPPTokeniser_PeekToken(tokeniser);
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier)) return;
|
if (!ExpectToken(token, CPPTokenType::Identifier)) return false;
|
||||||
|
|
||||||
char *name_start = token.str;
|
char *name_start = token.str;
|
||||||
while (token.type != CPPTokenType::OpenParen && token.type != CPPTokenType::EndOfStream)
|
while (token.type != CPPTokenType::OpenParen && token.type != CPPTokenType::EndOfStream)
|
||||||
@ -1440,16 +1221,18 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
|||||||
token = CPPTokeniser_PeekToken(tokeniser);
|
token = CPPTokeniser_PeekToken(tokeniser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExpectToken(token, CPPTokenType::OpenParen)) return;
|
if (!ExpectToken(token, CPPTokenType::OpenParen)) return false;
|
||||||
char *name_end = token.str;
|
char *name_end = token.str;
|
||||||
function_name = StringLiteral(name_start, static_cast<int>(name_end - name_start));
|
parsed_func->name = StringLiteral(name_start, static_cast<int>(name_end - name_start));
|
||||||
}
|
}
|
||||||
|
|
||||||
token = CPPTokeniser_PeekToken(tokeniser);
|
token = CPPTokeniser_PeekToken(tokeniser);
|
||||||
if (!ExpectToken(token, CPPTokenType::OpenParen))
|
if (!ExpectToken(token, CPPTokenType::OpenParen))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *param_list = nullptr;
|
//
|
||||||
|
// NOTE: Parse CPP Function Parameters
|
||||||
|
//
|
||||||
{
|
{
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *link_iterator = nullptr;
|
CPPDeclLinkedList<CPPVariableDecl> *link_iterator = nullptr;
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
token = CPPTokeniser_NextToken(tokeniser);
|
||||||
@ -1461,7 +1244,7 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
|||||||
{
|
{
|
||||||
CPPTokeniser_RewindToken(tokeniser);
|
CPPTokeniser_RewindToken(tokeniser);
|
||||||
CPPDeclLinkedList<CPPVariableDecl> *link = ParseCPPTypeAndVariableDecl(tokeniser, true);
|
CPPDeclLinkedList<CPPVariableDecl> *link = ParseCPPTypeAndVariableDecl(tokeniser, true);
|
||||||
if (!param_list) param_list = link;
|
if (!parsed_func->members) parsed_func->members = link;
|
||||||
if (!link_iterator) link_iterator = link;
|
if (!link_iterator) link_iterator = link;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1473,10 +1256,13 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NOTE: Map Default Parameters in the inspect prototype macro to the actual declaration in the CPP Prototype
|
||||||
|
//
|
||||||
for (LinkedList<FunctionDefaultParam> const *default_link = default_param_list; default_link; default_link = default_link->next)
|
for (LinkedList<FunctionDefaultParam> const *default_link = default_param_list; default_link; default_link = default_link->next)
|
||||||
{
|
{
|
||||||
FunctionDefaultParam const *default_param = &default_link->value;
|
FunctionDefaultParam const *default_param = &default_link->value;
|
||||||
for (CPPDeclLinkedList<CPPVariableDecl> *param_link = param_list; param_link; param_link = param_link->next)
|
for (CPPDeclLinkedList<CPPVariableDecl> *param_link = parsed_func->members; param_link; param_link = param_link->next)
|
||||||
{
|
{
|
||||||
CPPVariableDecl *decl = ¶m_link->value;
|
CPPVariableDecl *decl = ¶m_link->value;
|
||||||
if (StrCmp(decl->name, default_param->name))
|
if (StrCmp(decl->name, default_param->name))
|
||||||
@ -1487,42 +1273,7 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type.str[return_type.len-1] == '*') // NOTE(doyle): Align the pointer to the name
|
return true;
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "%.*s%.*s(", return_type.len, return_type.str, function_name.len, function_name.str);
|
|
||||||
else
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "%.*s %.*s(", return_type.len, return_type.str, function_name.len, function_name.str);
|
|
||||||
|
|
||||||
for (CPPDeclLinkedList<CPPVariableDecl> *param_link = param_list; param_link; param_link = param_link->next)
|
|
||||||
{
|
|
||||||
// TODO(doyle): HACK. We should parse ptrs into the CPPVariableDecl, fixed size arrays into the name and const-ness into the type
|
|
||||||
CPPVariableDecl *decl = ¶m_link->value;
|
|
||||||
StringLiteral *type = &decl->type;
|
|
||||||
char *type_end = (decl->template_expr.len > 0) ? decl->template_expr.str + decl->template_expr.len + 1 // +1 for the ending ">" on the template
|
|
||||||
: type->str + type->len;
|
|
||||||
|
|
||||||
StringLiteral *name = &decl->name;
|
|
||||||
StringLiteral hack_decl_name = {};
|
|
||||||
if (name->len > 0)
|
|
||||||
{
|
|
||||||
char *name_start = type_end + 1;
|
|
||||||
char *name_end = name->str + name->len;
|
|
||||||
hack_decl_name = StringLiteral(name_start, static_cast<int>(name_end - name_start));
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "%.*s", type->len, type->str);
|
|
||||||
if (decl->template_expr.len > 0)
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "<%.*s>", decl->template_expr.len, decl->template_expr.str);
|
|
||||||
|
|
||||||
if (hack_decl_name.len > 0)
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, " %.*s", hack_decl_name.len, hack_decl_name.str);
|
|
||||||
|
|
||||||
if (decl->default_value.len > 0)
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, " = %.*s", decl->default_value.len, decl->default_value.str);
|
|
||||||
|
|
||||||
if (param_link->next)
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, ", ", return_type.len, return_type.str, function_name.len, function_name.str);
|
|
||||||
}
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, ");\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum struct InspectMode
|
enum struct InspectMode
|
||||||
@ -1763,11 +1514,6 @@ int main(int argc, char *argv[])
|
|||||||
"\n"
|
"\n"
|
||||||
"#ifndef DQN_INSPECT_%.*s\n"
|
"#ifndef DQN_INSPECT_%.*s\n"
|
||||||
"#define DQN_INSPECT_%.*s\n"
|
"#define DQN_INSPECT_%.*s\n"
|
||||||
"\n"
|
|
||||||
" // NOTE: These macros are undefined at the end of the file so to not pollute namespace\n"
|
|
||||||
"#define ARRAY_COUNT(array) sizeof(array)/sizeof((array)[0])\n"
|
|
||||||
"#define CHAR_COUNT(str) (ARRAY_COUNT(str) - 1)\n"
|
|
||||||
"#define STR_AND_LEN(str) str, CHAR_COUNT(str)\n"
|
|
||||||
"\n",
|
"\n",
|
||||||
file_name,
|
file_name,
|
||||||
file_include_contents_hash_define_len,
|
file_include_contents_hash_define_len,
|
||||||
@ -1776,6 +1522,17 @@ int main(int argc, char *argv[])
|
|||||||
file_include_contents_hash_define
|
file_include_contents_hash_define
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (mode == InspectMode::All || mode == InspectMode::Code)
|
||||||
|
{
|
||||||
|
fprintf(output_file,
|
||||||
|
" // NOTE: These macros are undefined at the end of the file so to not pollute namespace\n"
|
||||||
|
"#define ARRAY_COUNT(array) sizeof(array)/sizeof((array)[0])\n"
|
||||||
|
"#define CHAR_COUNT(str) (ARRAY_COUNT(str) - 1)\n"
|
||||||
|
"#define STR_AND_LEN(str) str, CHAR_COUNT(str)\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
CPPTokeniser tokeniser = {};
|
CPPTokeniser tokeniser = {};
|
||||||
tokeniser.spaces_per_indent = 4;
|
tokeniser.spaces_per_indent = 4;
|
||||||
tokeniser.output_file = output_file;
|
tokeniser.output_file = output_file;
|
||||||
@ -1828,10 +1585,16 @@ int main(int argc, char *argv[])
|
|||||||
CPPToken *sentinel = CPPTokeniser_MakeToken(&tokeniser);
|
CPPToken *sentinel = CPPTokeniser_MakeToken(&tokeniser);
|
||||||
sentinel->type = CPPTokenType::EndOfStream;
|
sentinel->type = CPPTokenType::EndOfStream;
|
||||||
|
|
||||||
|
std::vector<ParsedResult> parsing_results;
|
||||||
|
parsing_results.reserve(1024);
|
||||||
|
|
||||||
|
int max_func_return_type_decl_len = 0;
|
||||||
|
int max_func_name_decl_len = 0;
|
||||||
for (CPPToken token = CPPTokeniser_PeekToken(&tokeniser);
|
for (CPPToken token = CPPTokeniser_PeekToken(&tokeniser);
|
||||||
;
|
;
|
||||||
token = CPPTokeniser_PeekToken(&tokeniser))
|
token = CPPTokeniser_PeekToken(&tokeniser))
|
||||||
{
|
{
|
||||||
|
ParsedResult parse_result = {};
|
||||||
if (token.type == CPPTokenType::InspectCode || token.type == CPPTokenType::InspectGeneratePrototype)
|
if (token.type == CPPTokenType::InspectCode || token.type == CPPTokenType::InspectGeneratePrototype)
|
||||||
{
|
{
|
||||||
if (token.type == CPPTokenType::InspectCode)
|
if (token.type == CPPTokenType::InspectCode)
|
||||||
@ -1841,16 +1604,23 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (IsIdentifierToken(token, STR_LITERAL("enum")))
|
if (IsIdentifierToken(token, STR_LITERAL("enum")))
|
||||||
{
|
{
|
||||||
ParseCPPEnum(&tokeniser);
|
if (ParseCPPEnum(&tokeniser, &parse_result.parsed_enum))
|
||||||
|
parse_result.type = ParsedResultType::Enum;
|
||||||
}
|
}
|
||||||
else if (IsIdentifierToken(token, STR_LITERAL("struct")) || IsIdentifierToken(token, STR_LITERAL("class")))
|
else if (IsIdentifierToken(token, STR_LITERAL("struct")) || IsIdentifierToken(token, STR_LITERAL("class")))
|
||||||
{
|
{
|
||||||
ParseCPPStruct(&tokeniser);
|
if (ParseCPPStruct(&tokeniser, &parse_result.parsed_struct))
|
||||||
|
parse_result.type = ParsedResultType::Struct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParseCPPInspectPrototype(&tokeniser);
|
if (ParseCPPInspectPrototype(&tokeniser, &parse_result.parsed_func_prototype))
|
||||||
|
{
|
||||||
|
parse_result.type = ParsedResultType::FunctionPrototype;
|
||||||
|
max_func_return_type_decl_len = INSPECT_MAX(max_func_return_type_decl_len, parse_result.parsed_func_prototype.return_type.len);
|
||||||
|
max_func_name_decl_len = INSPECT_MAX(max_func_name_decl_len, parse_result.parsed_func_prototype.name.len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1858,10 +1628,336 @@ int main(int argc, char *argv[])
|
|||||||
token = CPPTokeniser_NextToken(&tokeniser);
|
token = CPPTokeniser_NextToken(&tokeniser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parse_result.type != ParsedResultType::Invalid)
|
||||||
|
parsing_results.push_back(parse_result);
|
||||||
|
|
||||||
if (token.type == CPPTokenType::EndOfStream)
|
if (token.type == CPPTokenType::EndOfStream)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (ParsedResult &parser : parsing_results)
|
||||||
|
{
|
||||||
|
switch(parser.type)
|
||||||
|
{
|
||||||
|
case ParsedResultType::Enum:
|
||||||
|
{
|
||||||
|
ParsedEnum const *parsed_enum = &parser.parsed_enum;
|
||||||
|
//
|
||||||
|
// NOTE: Write Stringified Enum Array
|
||||||
|
//
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "char const *DqnInspect_%.*s_Strings[] = {", parsed_enum->name.len, parsed_enum->name.str);
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
for (CPPDeclLinkedList<StringLiteral> const *link = parsed_enum->members; link; link = link->next)
|
||||||
|
{
|
||||||
|
StringLiteral const enum_value = link->value;
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, "\"%.*s\", ", enum_value.len, enum_value.str);
|
||||||
|
}
|
||||||
|
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "};\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write InspectEnumString Function
|
||||||
|
//
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "char const *DqnInspect_EnumString(%.*s val)\n{\n", parsed_enum->name.len, parsed_enum->name.str);
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
DEFER
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "return nullptr;\n");
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "}\n\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SourceCode
|
||||||
|
{
|
||||||
|
StringLiteral decl;
|
||||||
|
StringLiteral enum_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkedList<SourceCode> src_code = {};
|
||||||
|
int longest_decl_len = 0;
|
||||||
|
{
|
||||||
|
LinkedList<SourceCode> *curr_src_code = nullptr;
|
||||||
|
char const *fmt = (parsed_enum->struct_or_class_decl) ? "if (val == %.*s::%.*s) " : "if (val == %.*s) ";
|
||||||
|
for (CPPDeclLinkedList<StringLiteral> *link = parsed_enum->members; link; link = link->next)
|
||||||
|
{
|
||||||
|
if (!curr_src_code) curr_src_code = &src_code;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curr_src_code->next = static_cast<LinkedList<SourceCode> *>( MemArena_Alloc(&global_main_arena, sizeof(*curr_src_code)));
|
||||||
|
curr_src_code = curr_src_code->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringLiteral enum_value = link->value;
|
||||||
|
int required_len = 0;
|
||||||
|
|
||||||
|
if (parsed_enum->struct_or_class_decl) required_len = snprintf(nullptr, 0, fmt, parsed_enum->name.len, parsed_enum->name.str, enum_value.len, enum_value.str) + 1;
|
||||||
|
else required_len = snprintf(nullptr, 0, fmt, enum_value.len, enum_value.str) + 1;
|
||||||
|
|
||||||
|
longest_decl_len = INSPECT_MAX(longest_decl_len, required_len);
|
||||||
|
curr_src_code->value.decl.str = MEM_ARENA_ALLOC_ARRAY(&global_main_arena, char, required_len);
|
||||||
|
curr_src_code->value.decl.len = required_len;
|
||||||
|
curr_src_code->value.enum_value = enum_value;
|
||||||
|
|
||||||
|
if (parsed_enum->struct_or_class_decl) snprintf(curr_src_code->value.decl.str, curr_src_code->value.decl.len, fmt, parsed_enum->name.len, parsed_enum->name.str, enum_value.len, enum_value.str);
|
||||||
|
else snprintf(curr_src_code->value.decl.str, curr_src_code->value.decl.len, fmt, enum_value.len, enum_value.str);
|
||||||
|
}
|
||||||
|
curr_src_code->next = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int enum_index = 0;
|
||||||
|
for (LinkedList<SourceCode> *src_code_ptr = &src_code;
|
||||||
|
src_code_ptr;
|
||||||
|
src_code_ptr = src_code_ptr->next, ++enum_index)
|
||||||
|
{
|
||||||
|
StringLiteral enum_value = src_code_ptr->value.enum_value;
|
||||||
|
int padding = longest_decl_len - src_code_ptr->value.decl.len;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "%.*s%*s", src_code_ptr->value.decl.len, src_code_ptr->value.decl.str, padding, "");
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser,
|
||||||
|
"return DqnInspect_%.*s_Strings[%d]; // \"%.*s\"\n",
|
||||||
|
parsed_enum->name.len, parsed_enum->name.str,
|
||||||
|
enum_index,
|
||||||
|
enum_value.len, enum_value.str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write User Annotated Metadata Getter Functions
|
||||||
|
//
|
||||||
|
{
|
||||||
|
FixedArray<MetadataEntry, 32> metadata_entries = {};
|
||||||
|
for (CPPDeclLinkedList<StringLiteral> *link = parsed_enum->members;
|
||||||
|
link;
|
||||||
|
link = link->next)
|
||||||
|
{
|
||||||
|
for (CPPInspectMetadataEntry const &inspect_entry : link->metadata_array)
|
||||||
|
{
|
||||||
|
MetadataEntry *metadata_entry_to_append_to = nullptr;
|
||||||
|
for (MetadataEntry &check_metadata_entry : metadata_entries)
|
||||||
|
{
|
||||||
|
if (StrCmp(check_metadata_entry.key, inspect_entry.key))
|
||||||
|
{
|
||||||
|
metadata_entry_to_append_to = &check_metadata_entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!metadata_entry_to_append_to)
|
||||||
|
{
|
||||||
|
metadata_entry_to_append_to = FixedArray_Make(&metadata_entries, 1);
|
||||||
|
metadata_entry_to_append_to->key = inspect_entry.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPDeclToMetaValue decl_to_val = {};
|
||||||
|
decl_to_val.cpp_decl = StringLiteral(link->value.str, link->value.len);
|
||||||
|
decl_to_val.value = inspect_entry.value;
|
||||||
|
FixedArray_Add(&metadata_entry_to_append_to->cpp_decl_to_val, decl_to_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MetadataEntry const &metadata : metadata_entries)
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser,
|
||||||
|
"char const *DqnInspect_%.*sMetadata(%.*s val)\n{\n",
|
||||||
|
metadata.key.len, metadata.key.str,
|
||||||
|
parsed_enum->name.len, parsed_enum->name.str);
|
||||||
|
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
DEFER
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "return nullptr;\n");
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "}\n\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
for (CPPDeclToMetaValue const &decl_to_val : metadata.cpp_decl_to_val)
|
||||||
|
{
|
||||||
|
StringLiteral const *cpp_decl = &decl_to_val.cpp_decl;
|
||||||
|
StringLiteral const *value = &decl_to_val.value;
|
||||||
|
|
||||||
|
if (parsed_enum->struct_or_class_decl)
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser,
|
||||||
|
"if (val == %.*s::%.*s) ",
|
||||||
|
parsed_enum->name.len, parsed_enum->name.str,
|
||||||
|
cpp_decl->len, cpp_decl->str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser,
|
||||||
|
"if (val == %.*s) ",
|
||||||
|
cpp_decl->len, cpp_decl->str);
|
||||||
|
}
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, "return \"%.*s\";\n", value->len, value->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ParsedResultType::Struct:
|
||||||
|
{
|
||||||
|
ParsedStruct const *parsed_struct = &parser.parsed_struct;
|
||||||
|
//
|
||||||
|
// NOTE: Write DqnInspect_StructMemberMetadata Definition
|
||||||
|
//
|
||||||
|
for (CPPDeclLinkedList<CPPVariableDecl> const *member = parsed_struct->members; member; member = member->next)
|
||||||
|
{
|
||||||
|
CPPVariableDecl const *decl = &member->value;
|
||||||
|
if (member->metadata_array.len <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CPPTokeniser_SprintfToFile(
|
||||||
|
&tokeniser,
|
||||||
|
"DqnInspect_StructMemberMetadata const DqnInspect_%.*s_%.*s_StructMemberMetadata[] =\n{\n",
|
||||||
|
parsed_struct->name.len,
|
||||||
|
parsed_struct->name.str,
|
||||||
|
decl->name.len,
|
||||||
|
decl->name.str);
|
||||||
|
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
for (CPPInspectMetadataEntry const &entry : member->metadata_array)
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "{\n");
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_StructMemberMetadataType::String,\n");
|
||||||
|
|
||||||
|
// metadata->key
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "STR_AND_LEN(\"%.*s\"), ", entry.key.len, entry.key.str);
|
||||||
|
|
||||||
|
// metadata->value
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, "STR_AND_LEN(\"%.*s\"),\n", entry.value.len, entry.value.str);
|
||||||
|
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "},\n");
|
||||||
|
}
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "};\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write DqnInspect_StructMembers Definition
|
||||||
|
//
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_StructMember const DqnInspect_%.*s_StructMembers[] =\n{\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
|
||||||
|
for (CPPDeclLinkedList<CPPVariableDecl> const *member = parsed_struct->members; member; member = member->next)
|
||||||
|
{
|
||||||
|
CPPVariableDecl const *decl = &member->value;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "{\n");
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "STR_AND_LEN(\"%.*s\"), ", decl->type.len, decl->type.str);
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, "STR_AND_LEN(\"%.*s\"),\n", decl->name.len, decl->name.str);
|
||||||
|
|
||||||
|
if (decl->template_expr.len <= 0)
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "nullptr, 0, // template_expr and template_expr_len\n");
|
||||||
|
else
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "STR_AND_LEN(\"%.*s\"), // template_expr\n", decl->template_expr.len, decl->template_expr.str);
|
||||||
|
|
||||||
|
if (member->metadata_array.len <= 0) CPPTokeniser_SprintfToFile(&tokeniser, "nullptr, 0, // metadata and metadata_len\n");
|
||||||
|
else CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_%.*s_%.*s_StructMemberMetadata, %d,\n", parsed_struct->name.len, parsed_struct->name.str, decl->name.len, decl->name.str, member->metadata_array.len);
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "%d // array_dimensions\n", decl->array_dimensions);
|
||||||
|
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "},\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "};\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write DqnInspect_Struct Definition
|
||||||
|
//
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_Struct const DqnInspect_%.*s_Struct =\n{\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "STR_AND_LEN(\"%.*s\"),\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_%.*s_StructMembers, // members\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "ARRAY_COUNT(DqnInspect_%.*s_StructMembers) // members_len\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "};\n\n");
|
||||||
|
assert(tokeniser.indent_level == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write DqnInspect_Struct getter
|
||||||
|
//
|
||||||
|
{
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_Struct const *DqnInspect_GetStruct(%.*s const *val)\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "{\n");
|
||||||
|
tokeniser.indent_level++;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "(void)val;\n");
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "DqnInspect_Struct const *result = &DqnInspect_%.*s_Struct;\n", parsed_struct->name.len, parsed_struct->name.str);
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "return result;\n");
|
||||||
|
tokeniser.indent_level--;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "}\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ParsedResultType::FunctionPrototype:
|
||||||
|
{
|
||||||
|
ParsedFunctionPrototype *parsed_func = &parser.parsed_func_prototype;
|
||||||
|
{
|
||||||
|
StringLiteral return_type = parsed_func->return_type;
|
||||||
|
StringLiteral func_name = parsed_func->name;
|
||||||
|
|
||||||
|
int spaces_remaining = max_func_return_type_decl_len - return_type.len;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "%.*s ", return_type.len, return_type.str);
|
||||||
|
for (int i = 0; i < spaces_remaining; ++i) CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, " ");
|
||||||
|
|
||||||
|
spaces_remaining = max_func_name_decl_len - func_name.len;
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "%.*s", func_name.len, func_name.str);
|
||||||
|
for (int i = 0; i < spaces_remaining; ++i) CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, " ");
|
||||||
|
|
||||||
|
CPPTokeniser_SprintfToFile(&tokeniser, "(");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CPPDeclLinkedList<CPPVariableDecl> *param_link = parsed_func->members; param_link; param_link = param_link->next)
|
||||||
|
{
|
||||||
|
// TODO(doyle): HACK. We should parse ptrs into the CPPVariableDecl, fixed size arrays into the name and const-ness into the type
|
||||||
|
CPPVariableDecl *decl = ¶m_link->value;
|
||||||
|
StringLiteral *type = &decl->type;
|
||||||
|
char *type_end = (decl->template_expr.len > 0)
|
||||||
|
? decl->template_expr.str + decl->template_expr.len + 1 // +1 for the ending ">" on the template
|
||||||
|
: type->str + type->len;
|
||||||
|
|
||||||
|
StringLiteral *name = &decl->name;
|
||||||
|
StringLiteral hack_decl_name = {};
|
||||||
|
if (name->len > 0)
|
||||||
|
{
|
||||||
|
char *name_start = type_end + 1;
|
||||||
|
char *name_end = name->str + name->len;
|
||||||
|
hack_decl_name = StringLiteral(name_start, static_cast<int>(name_end - name_start));
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, "%.*s", type->len, type->str);
|
||||||
|
if (decl->template_expr.len > 0)
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, "<%.*s>", decl->template_expr.len, decl->template_expr.str);
|
||||||
|
|
||||||
|
if (hack_decl_name.len > 0)
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, " %.*s", hack_decl_name.len, hack_decl_name.str);
|
||||||
|
|
||||||
|
if (decl->default_value.len > 0)
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, " = %.*s", decl->default_value.len, decl->default_value.str);
|
||||||
|
|
||||||
|
if (param_link->next)
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, ", ", parsed_func->return_type.len, parsed_func->return_type.str, parsed_func->name.len, parsed_func->name.str);
|
||||||
|
}
|
||||||
|
CPPTokeniser_SprintfToFileNoIndenting(&tokeniser, ");\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(output_file,
|
fprintf(output_file,
|
||||||
"\n#undef ARRAY_COUNT\n"
|
"\n#undef ARRAY_COUNT\n"
|
||||||
"#undef CHAR_COUNT\n"
|
"#undef CHAR_COUNT\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user