More fixes while completing sanity check for enums

Typepunning failed, didn't know about the difference between C/C++ with strict aliasing in this specific case...
This commit is contained in:
Edward R. Gonzalez 2023-06-28 21:20:29 -04:00
parent 0192cd49ef
commit 44ab1c2fc3
7 changed files with 163 additions and 134 deletions

View File

@ -114,6 +114,7 @@
<ClInclude Include="project\Bloat.redef.hpp" /> <ClInclude Include="project\Bloat.redef.hpp" />
<ClInclude Include="project\Bloat.undef.hpp" /> <ClInclude Include="project\Bloat.undef.hpp" />
<ClInclude Include="project\gen.hpp" /> <ClInclude Include="project\gen.hpp" />
<ClInclude Include="test\NonParsed\Sanity.hpp" />
<ClInclude Include="thirdparty\zpl.h" /> <ClInclude Include="thirdparty\zpl.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -50,6 +50,9 @@
<ClInclude Include="thirdparty\zpl.h"> <ClInclude Include="thirdparty\zpl.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="test\NonParsed\Sanity.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".editorconfig" /> <None Include=".editorconfig" />

View File

@ -411,9 +411,7 @@ namespace gen
return false; return false;
} }
array_append( Entries, other ); add_entry( other );
other->Parent = this;
return true; return true;
#else #else
log_failure( "AST::add: Incremental AST building is not enabled." ); log_failure( "AST::add: Incremental AST building is not enabled." );
@ -495,7 +493,7 @@ namespace gen
// This will naturally duplicate the entire chain duplicate all of the ast nodes. // This will naturally duplicate the entire chain duplicate all of the ast nodes.
// It may not be the most optimal way for memory reasons, however figuring out the heuristic // It may not be the most optimal way for memory reasons, however figuring out the heuristic
// For when it should reparent all nodes or not is not within the simple scope of this library. // For when it should reparent all nodes or not is not within the simple scope of this library.
result->add_entry( Entries[index]->duplicate() ); result->add_entry( entry(index)->duplicate() );
index++; index++;
} }
return result; return result;
@ -506,7 +504,7 @@ namespace gen
} }
String AST::to_string() String AST::to_string()
{ {
# define ProcessModuleFlags() \ # define ProcessModuleFlags() \
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export )) \ if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export )) \
result.append( "export " ); \ result.append( "export " ); \
@ -616,15 +614,15 @@ namespace gen
s32 idx = 1; s32 idx = 1;
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
result.append( Name ); result.append( Name );
AST* parent = Entries[idx]; AST* parent = entry( idx );
if ( parent ) if ( parent )
{ {
@ -668,43 +666,53 @@ namespace gen
result.append( "enum " ); result.append( "enum " );
s32 idx = 1; if ( num_entries() > 1 )
if ( Entries[idx]->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); s32 idx = 1;
idx++;
}
if ( Entries[idx]->Type == Typename) AST* Entry = entry( idx);
{
result.append_fmt( "%s : %s\n%s{\n" if ( Entry->Type == Attributes )
, Name {
, Entries[idx]->to_string() result.append_fmt( "%s ", entry( idx )->to_string() );
, indent_str idx++;
); }
if ( Entry->Type == Typename)
{
result.append_fmt( "%s : %s\n{\n"
, Name
, entry( idx )->to_string()
);
}
else
{
result.append_fmt( "%s\n{\n"
, Name
);
}
} }
else else
{ {
result.append_fmt( result, "%s\n%s{\n" result.append_fmt( "%s\n{\n"
, Name , Name
, indent_str
); );
} }
result.append_fmt( result, "%s\n%s};" result.append_fmt( "%s};"
, body()->to_string() , body()->to_string()
, indent_str
); );
} }
break; break;
case Enum_Fwd: case Enum_Fwd:
{
result.append( indent ); result.append( indent );
ProcessModuleFlags(); ProcessModuleFlags();
result.append_fmt( "enum %s : %s;\n", Name, Entries[1]->to_string() ); result.append_fmt( "enum %s : %s;", Name, entry( 0 )->to_string() );
}
break; break;
case Enum_Class: case Enum_Class:
@ -717,17 +725,17 @@ namespace gen
s32 idx = 0; s32 idx = 0;
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
if ( Entries[idx]->Type == Typename ) if ( entry( idx )->Type == Typename )
{ {
result.append_fmt( ": %s\n%s{\n" result.append_fmt( ": %s\n%s{\n"
, Name , Name
, Entries[idx]->to_string() , entry( idx )->to_string()
, indent_str , indent_str
); );
} }
@ -756,13 +764,13 @@ namespace gen
s32 idx = 0; s32 idx = 0;
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
result.append_fmt( ": %s;\n", Name, Entries[idx]->to_string() ); result.append_fmt( ": %s;\n", Name, entry( idx )->to_string() );
} }
break; break;
@ -778,7 +786,7 @@ namespace gen
s32 left = num_entries(); s32 left = num_entries();
while ( left -- ) while ( left -- )
{ {
result.append_fmt( "%s\t%s\n", indent_str, Entries[index]->to_string() ); result.append_fmt( "%s\t%s\n", indent_str, entry( index )->to_string() );
index++; index++;
} }
@ -800,7 +808,7 @@ namespace gen
break; break;
case Friend: case Friend:
result.append_fmt( "%sfriend %s;\n", indent_str, Entries[0]->to_string() ); result.append_fmt( "%sfriend %s;\n", indent_str, entry( 0 )->to_string() );
break; break;
case Function: case Function:
@ -812,27 +820,27 @@ namespace gen
u32 idx = 1; u32 idx = 1;
u32 left = num_entries(); u32 left = num_entries();
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
left--; left--;
} }
if ( Entries[idx]->Type == Specifiers ) if ( entry( idx )->Type == Specifiers )
{ {
result.append_fmt( "%s\n", Entries[idx]->to_string() ); result.append_fmt( "%s\n", entry( idx )->to_string() );
idx++; idx++;
left--; left--;
} }
result.append_fmt( "%s %s(", Entries[idx]->to_string(), Name ); result.append_fmt( "%s %s(", entry( idx )->to_string(), Name );
idx++; idx++;
left--; left--;
if ( left && Entries[idx]->Type == Parameters ) if ( left && entry( idx )->Type == Parameters )
{ {
result.append_fmt( "%s", Entries[idx]->to_string() ); result.append_fmt( "%s", entry( idx )->to_string() );
idx++; idx++;
left--; left--;
} }
@ -858,14 +866,14 @@ namespace gen
u32 idx = 0; u32 idx = 0;
u32 left = num_entries(); u32 left = num_entries();
AST* Entry = Entries[idx]; AST* Entry = entry( idx );
if ( Entry && Entry->Type == Attributes ) if ( Entry && Entry->Type == Attributes )
{ {
result.append_fmt( "%s ", Entry->to_string() ); result.append_fmt( "%s ", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx]; Entry = entry( idx );
} }
if ( Entry && Entry->Type == Specifiers ) if ( Entry && Entry->Type == Specifiers )
@ -873,7 +881,7 @@ namespace gen
result.append_fmt( "%s\n", Entry->to_string() ); result.append_fmt( "%s\n", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx]; Entry = entry( idx );
} }
if ( Entry && Entry->Type == Typename ) if ( Entry && Entry->Type == Typename )
@ -881,7 +889,7 @@ namespace gen
result.append_fmt( "%s ", Entry->to_string() ); result.append_fmt( "%s ", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx]; Entry = entry( idx );
} }
result.append_fmt( "%s(", Name ); result.append_fmt( "%s(", Name );
@ -891,7 +899,7 @@ namespace gen
result.append_fmt("%s", Entry->to_string() ); result.append_fmt("%s", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx]; Entry = entry( idx );
} }
else else
{ {
@ -932,24 +940,24 @@ namespace gen
s32 idx = 1; s32 idx = 1;
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
if ( Entries[idx]->Type == Specifiers ) if ( entry( idx )->Type == Specifiers )
{ {
result.append_fmt( "%s\n", Entries[idx]->to_string() ); result.append_fmt( "%s\n", entry( idx )->to_string() );
idx++; idx++;
} }
result.append_fmt( "%s operator %s (", Entries[idx]->to_string(), Name ); result.append_fmt( "%s operator %s (", entry( idx )->to_string(), Name );
idx++; idx++;
if ( Entries[idx]->Type == Parameters ) if ( entry( idx )->Type == Parameters )
{ {
result.append_fmt( "%s", Entries[idx]->to_string() ); result.append_fmt( "%s", entry( idx )->to_string() );
idx++; idx++;
} }
else else
@ -974,18 +982,18 @@ namespace gen
s32 idx = 0; s32 idx = 0;
if ( Entries[idx]->Type == Specifiers ) if ( entry( idx )->Type == Specifiers )
{ {
result.append_fmt( "%s", Entries[idx]->to_string() ); result.append_fmt( "%s", entry( idx )->to_string() );
idx++; idx++;
} }
result.append_fmt( "%s operator%s(", Entries[idx]->to_string(), Name ); result.append_fmt( "%s operator%s(", entry( idx )->to_string(), Name );
idx++; idx++;
if ( Entries[idx]->Type == Parameters ) if ( entry( idx )->Type == Parameters )
{ {
result.append_fmt( "%s);\n", Entries[idx]->to_string() ); result.append_fmt( "%s);\n", entry( idx )->to_string() );
idx++; idx++;
} }
else else
@ -997,15 +1005,15 @@ namespace gen
case Parameters: case Parameters:
{ {
result.append_fmt( "%s %s", Entries[0]->to_string(), Name ); result.append_fmt( "%s %s", entry( 0 )->to_string(), Name );
s32 index = 1; s32 index = 1;
s32 left = array_count( Entries ) - 1; s32 left = num_entries() - 1;
while ( left--, left > 0 ) while ( left--, left > 0 )
result.append_fmt( ", %s %s" result.append_fmt( ", %s %s"
, Entries[index]->Entries[0]->to_string() , entry( index )->entry( 0 )->to_string()
, Entries[index]->Name , entry( index )->Name
); );
} }
break; break;
@ -1033,19 +1041,19 @@ namespace gen
s32 idx = 1; s32 idx = 1;
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
result.append_fmt( "%s ", Name ); result.append_fmt( "%s ", Name );
if ( Entries[idx] ) if ( entry( idx ) )
{ {
char const* access_str = to_str( ParentAccess ); char const* access_str = to_str( ParentAccess );
result.append_fmt( ": %s %s", access_str, Entries[idx]->to_string() ); result.append_fmt( ": %s %s", access_str, entry( idx )->to_string() );
} }
result.append_fmt( "\n{\n%s\n};\n", body()->to_string() ); result.append_fmt( "\n{\n%s\n};\n", body()->to_string() );
@ -1062,9 +1070,9 @@ namespace gen
s32 idx = 1; s32 idx = 1;
if ( Entries[idx]->Type == Specifiers ) if ( entry( idx )->Type == Specifiers )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
@ -1080,16 +1088,16 @@ namespace gen
s32 idx = 1; s32 idx = 1;
if ( Entries[idx]->Type == Specifiers ) if ( entry( idx )->Type == Specifiers )
{ {
result.append_fmt( "%s", Entries[idx]->to_string() ); result.append_fmt( "%s", entry( idx )->to_string() );
idx++; idx++;
} }
result.append_fmt( "%s %s", Entries[0]->to_string(), Name ); result.append_fmt( "%s %s", entry( 0 )->to_string(), Name );
if ( Entries[idx] ) if ( entry( idx ) )
result.append_fmt( " = %s", Entries[idx]->to_string() ); result.append_fmt( " = %s", entry( idx )->to_string() );
} }
break; break;
@ -1099,18 +1107,18 @@ namespace gen
ProcessModuleFlags(); ProcessModuleFlags();
AST* type = Entries[0]; AST* type = entry( 0 );
if ( Entries[1] && Entries[1]->Type == Attributes ) if ( entry( 1 ) && entry( 1 )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[1]->to_string() ); result.append_fmt( "%s ", entry( 1 )->to_string() );
} }
result.append_fmt( "typedef %s %s", type->to_string(), Name ); result.append_fmt( "typedef %s %s", type->to_string(), Name );
if ( type->Entries[1] ) if ( type->entry( 1 ) )
{ {
result.append_fmt( "[%s];", type->Entries[1]->to_string() ); result.append_fmt( "[%s];", type->entry( 1 )->to_string() );
} }
else else
{ {
@ -1120,9 +1128,9 @@ namespace gen
break; break;
case Typename: case Typename:
if ( num_entries() && Entries[0] ) if ( num_entries() && entry( 0 ) )
{ {
result.append_fmt( "%s %s", Name, Entries[0]->to_string() ); result.append_fmt( "%s %s", Name, entry( 0 )->to_string() );
} }
else else
{ {
@ -1140,9 +1148,9 @@ namespace gen
result.append( "union " ); result.append( "union " );
if ( Entries[idx]->Type == Attributes ) if ( entry( idx )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", entry( idx )->to_string() );
idx++; idx++;
} }
@ -1161,19 +1169,19 @@ namespace gen
ProcessModuleFlags(); ProcessModuleFlags();
AST* type = Entries[0]; AST* type = entry( 0 );
if ( Entries[1] && Entries[1]->Type == Attributes ) if ( entry( 1 ) && entry( 1 )->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[1]->to_string() ); result.append_fmt( "%s ", entry( 1 )->to_string() );
} }
if ( type ) if ( type )
{ {
result.append_fmt( "using %s = %s", Name, type->to_string() ); result.append_fmt( "using %s = %s", Name, type->to_string() );
if ( type->Entries[1] ) if ( type->entry( 1 ) )
result.append_fmt( "[%s]", type->Entries[1]->to_string() ); result.append_fmt( "[%s]", type->entry( 1 )->to_string() );
} }
else else
@ -1200,7 +1208,7 @@ namespace gen
s32 left = num_entries(); s32 left = num_entries();
while ( left -- ) while ( left -- )
{ {
result.append_fmt( "%s%s\n", indent_str, Entries[index]->to_string() ); result.append_fmt( "%s%s\n", indent_str, entry( index )->to_string() );
index++; index++;
} }
} }
@ -1471,20 +1479,6 @@ namespace gen
return result; return result;
} }
// Code get_cached_type( StrC name )
// {
// s32 hash_length = name.Len > kilobytes(1) ? kilobytes(1) : name.Len;
// s32 key = crc32( name.Ptr, hash_length );
// {
// Code* result = type_tbl_get( & StaticData::TypeMap, key );
// if ( result )
// return * result;
// }
// return Code::Invalid;
// }
/* /*
Used internally to retireve a Code object form the CodePool. Used internally to retireve a Code object form the CodePool.
*/ */
@ -1533,7 +1527,6 @@ namespace gen
result->StaticIndex = 0; result->StaticIndex = 0;
result->Readonly = false; result->Readonly = false;
result->DynamicEntries = false; result->DynamicEntries = false;
result->Entries = result->ArrStatic;
return result; return result;
} }
@ -2126,7 +2119,7 @@ namespace gen
result->add_entry( body ); result->add_entry( body );
} }
else if ( specifier == EnumClass ) else
{ {
result->Type = specifier == EnumClass ? result->Type = specifier == EnumClass ?
Enum_Class_Fwd : Enum_Fwd; Enum_Class_Fwd : Enum_Fwd;
@ -2354,7 +2347,6 @@ namespace gen
result = make_code(); result = make_code();
result->Type = Namespace; result->Type = Namespace;
result->Name = get_cached_string( name ); result->Name = get_cached_string( name );
result->Entries = make_code_entries();
result->ModuleFlags = mflags; result->ModuleFlags = mflags;
result->add_entry( body ); result->add_entry( body );

View File

@ -396,15 +396,20 @@ namespace gen
inline inline
AST* body() AST* body()
{ {
return Entries[0]; return entry( 0 );
} }
AST* duplicate(); AST* duplicate();
AST*& entry( u32 idx )
{
return DynamicEntries ? ArrDyn[ idx ] : ArrStatic[ idx ];
}
inline inline
bool has_entries() bool has_entries()
{ {
return Entries[0]; return entry( 0 );
} }
inline inline
@ -416,7 +421,7 @@ namespace gen
inline inline
s32 num_entries() s32 num_entries()
{ {
return DynamicEntries ? array_count(Entries) : StaticIndex; return DynamicEntries ? array_count( ArrDyn ) : StaticIndex;
} }
// Parameter // Parameter
@ -429,7 +434,7 @@ namespace gen
if ( index <= 0 ) if ( index <= 0 )
return this; return this;
return Entries[ index + 1 ]; return entry( index + 1 );
} }
inline inline
@ -442,7 +447,7 @@ namespace gen
inline inline
AST* param_type() AST* param_type()
{ {
return Entries[0]; return entry( 0 );
} }
// Specifiers // Specifiers
@ -492,7 +497,7 @@ namespace gen
inline inline
AST* typename_specifiers() AST* typename_specifiers()
{ {
return Entries[0]; return entry( 0 );
} }
// Serialization // Serialization
@ -547,10 +552,12 @@ namespace gen
constexpr static constexpr static
uw ArrSpecs_Cap = ArrS_Cap * (sizeof(AST*) / sizeof(SpecifierT)); uw ArrSpecs_Cap = ArrS_Cap * (sizeof(AST*) / sizeof(SpecifierT));
// static_assert( sizeof( AST* ) * ArrS_Cap == sizeof( AST** ) * ArrS_Cap, "Blah" );
# define Using_AST_POD \ # define Using_AST_POD \
union { \ union { \
AST* ArrStatic[AST::ArrS_Cap]; \ AST* ArrStatic[AST::ArrS_Cap]; \
Array(AST*) Entries; \ Array(AST*) ArrDyn; \
StringCached Content; \ StringCached Content; \
SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; \ SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; \
}; \ }; \
@ -613,19 +620,13 @@ namespace gen
return Invalid; return Invalid;
} }
if ( ast->Entries == nullptr || array_count(ast->Entries) == 0 ) #ifdef GEN_ENFORCE_READONLY_AST
{
log_failure("Code::body: Entries of ast not properly setup.");
return Invalid;
}
# ifdef GEN_ENFORCE_READONLY_AST
if ( ast->Readonly ) if ( ast->Readonly )
{ {
log_failure("Attempted to a body AST from a readonly AST!"); log_failure("Attempted to a body AST from a readonly AST!");
return Invalid; return Invalid;
} }
# endif #endif
return * (Code*)( ast->body() ); return * (Code*)( ast->body() );
} }
@ -691,13 +692,13 @@ namespace gen
return nullptr; return nullptr;
} }
# ifdef GEN_ENFORCE_READONLY_AST #ifdef GEN_ENFORCE_READONLY_AST
if ( ast->Readonly ) if ( ast->Readonly )
{ {
log_failure("Attempted to access a member from a readonly AST!"); log_failure("Attempted to access a member from a readonly AST!");
return nullptr; return nullptr;
} }
# endif #endif
return ast; return ast;
} }
@ -1162,7 +1163,7 @@ namespace gen
other->duplicate() : other; other->duplicate() : other;
if (DynamicEntries) if (DynamicEntries)
array_append( Entries, to_add ); array_append( ArrDyn, to_add );
else else
{ {
@ -1173,16 +1174,16 @@ namespace gen
} }
else else
{ {
Entries = make_code_entries(); ArrDyn = make_code_entries();
s32 index = 0; s32 index = 0;
do do
{ {
array_append( Entries, ArrStatic[index] ); array_append( ArrDyn, ArrStatic[index] );
} }
while ( StaticIndex--, StaticIndex ); while ( StaticIndex--, StaticIndex );
array_append( Entries, to_add ); array_append( ArrDyn, to_add );
} }
} }
@ -1213,7 +1214,7 @@ namespace gen
s32 s32
score = 0; score = 0;
score += Name == nullptr; score += Name == nullptr;
score += Entries[0] == nullptr; score += entry( 0 ) == nullptr;
if ( score == 1 ) if ( score == 1 )
{ {
@ -1223,7 +1224,7 @@ namespace gen
else if ( score == 2) else if ( score == 2)
{ {
Name = get_cached_string( name ); Name = get_cached_string( name );
Entries[0] = type; entry( 0 ) = type;
return true; return true;
} }

View File

@ -36,9 +36,36 @@ u32 gen_sanity()
gen_sanity_file.print_fmt("\n"); gen_sanity_file.print_fmt("\n");
// // Typedef
{ {
Code t_unsigned_char = def_type( name(unsigned char) );
Code u8_typedef = def_typedef( name(u8), t_unsigned_char );
gen_sanity_file.print(u8_typedef);
}
gen_sanity_file.print_fmt("\n");
// Enum
{
Code fwd = def_enum( StrC::from("Test_Enum"), NoCode, t_u8 );
Code def;
{
Code body = untyped_str( StrC::from(
#define enum_entry( id ) "\t" #id ",\n"
enum_entry( A )
enum_entry( B )
enum_entry( C )
#undef enum_entry
));
def = def_enum( StrC::from("Test_Enum"), body, t_u8 );
}
gen_sanity_file.print(fwd);
gen_sanity_file.print(def);
} }
gen_sanity_file.write(); gen_sanity_file.write();

View File

@ -4,9 +4,16 @@ class Test_EmptyClass;
class Test_EmptyClass class Test_EmptyClass
{ {
// Empty class // Empty class
}; };
UFUNCTION( BlueprintCallable, Category = "Test" ) typedef unsigned char u8;
void Test_UFunction(void);
enum Test_Enum : u8;
enum Test_Enum : u8
{
A,
B,
C,
};

View File

@ -9,8 +9,6 @@
using namespace gen; using namespace gen;
int gen_main() int gen_main()
{ {
Memory::setup(); Memory::setup();