WIP : Fixes and other changes

* Number literals weren't getting properly lexed
* Fixes for compiler errors with Unreal Engine configuration.
* Support for "post-name" macros in parameters
* Support for variables initializing directly using constructor syntax.
* Explicitly added inline keyword to header inlines for compiling compile library in multiple translation units.
This commit is contained in:
Edward R. Gonzalez 2024-10-25 01:04:17 -04:00
parent e1592ba410
commit b8e1aa6eb7
20 changed files with 248 additions and 94 deletions

View File

@ -48,7 +48,7 @@ void Builder::print_fmt( char const* fmt, ... )
void Builder::write() void Builder::write()
{ {
bool result = file_write( & File, Buffer, Buffer.length() ); b32 result = file_write( & File, Buffer, Buffer.length() );
if ( result == false ) if ( result == false )
log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) );

View File

@ -283,6 +283,7 @@ int gen_main()
} }
// gen_scanner.cpp // gen_scanner.cpp
if (0)
{ {
Code parsing = scan_file( "dependencies/parsing.cpp" ); Code parsing = scan_file( "dependencies/parsing.cpp" );
Code scanner = scan_file( "auxillary/scanner.cpp" ); Code scanner = scan_file( "auxillary/scanner.cpp" );

View File

@ -339,13 +339,14 @@ struct AST
}; };
union { union {
AST* ArrExpr; // Typename AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Friend, Function, Namespace, Struct, Union AST* Body; // Class, Constructor, Destructor, Enum, Friend, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable AST* Value; // Parameter, Variable
}; };
union { union {
AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value )
AST* SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) AST* SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed )
AST* PostNameMacro; // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal)
}; };
}; };
StringCached Content; // Attributes, Comment, Execution, Include StringCached Content; // Attributes, Comment, Execution, Include
@ -375,6 +376,7 @@ struct AST
OperatorT Op; OperatorT Op;
AccessSpec ParentAccess; AccessSpec ParentAccess;
s32 NumEntries; s32 NumEntries;
s32 VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression.
}; };
}; };
@ -407,6 +409,7 @@ struct AST_POD
union { union {
AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value )
AST* SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) AST* SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed )
AST* PostNameMacro; // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal)
}; };
}; };
StringCached Content; // Attributes, Comment, Execution, Include StringCached Content; // Attributes, Comment, Execution, Include
@ -436,6 +439,7 @@ struct AST_POD
OperatorT Op; OperatorT Op;
AccessSpec ParentAccess; AccessSpec ParentAccess;
s32 NumEntries; s32 NumEntries;
s32 VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression.
}; };
}; };

View File

@ -644,7 +644,8 @@ struct AST_Param
CodeType ValueType; CodeType ValueType;
Code Macro; Code Macro;
Code Value; Code Value;
char _PAD_PROPERTIES_3_[ sizeof(AST*) ]; Code PostNameMacro; // Thanks Unreal
// char _PAD_PROPERTIES_3_[sizeof( AST* )];
}; };
}; };
CodeParam Last; CodeParam Last;
@ -1115,7 +1116,7 @@ struct AST_Var
StringCached Name; StringCached Name;
CodeT Type; CodeT Type;
ModuleFlag ModuleFlags; ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ]; s32 VarConstructorInit;
}; };
static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST"); static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST");

View File

@ -480,7 +480,7 @@ void CodeFn::to_string_def( String& result )
if ( ast->Attributes ) if ( ast->Attributes )
result.append_fmt( " %S ", ast->Attributes.to_string() ); result.append_fmt( " %S ", ast->Attributes.to_string() );
b32 prefix_specs = false; bool prefix_specs = false;
if ( ast->Specs ) if ( ast->Specs )
{ {
for ( SpecifierT spec : ast->Specs ) for ( SpecifierT spec : ast->Specs )
@ -847,6 +847,11 @@ void CodeParam::to_string( String& result )
else if ( ast->ValueType ) else if ( ast->ValueType )
result.append_fmt( " %S", ast->ValueType.to_string() ); result.append_fmt( " %S", ast->ValueType.to_string() );
if ( ast->PostNameMacro )
{
result.append_fmt(" %S", ast->PostNameMacro.to_string() );
}
if ( ast->Value ) if ( ast->Value )
result.append_fmt( " = %S", ast->Value.to_string() ); result.append_fmt( " = %S", ast->Value.to_string() );
@ -1096,7 +1101,7 @@ String CodeType::to_string()
void CodeType::to_string( String& result ) void CodeType::to_string( String& result )
{ {
#if GEN_USE_NEW_TYPENAME_PARSING #if defined(GEN_USE_NEW_TYPENAME_PARSING)
if ( ast->ReturnType && ast->Params ) if ( ast->ReturnType && ast->Params )
{ {
if ( ast->Attributes ) if ( ast->Attributes )
@ -1253,7 +1258,7 @@ void CodeVar::to_string( String& result )
result.append( ast->Name ); result.append( ast->Name );
if ( ast->ValueType && ast->ValueType->ArrExpr ) if ( ast->ValueType->ArrExpr )
{ {
result.append_fmt( "[ %S ]", ast->ValueType->ArrExpr.to_string() ); result.append_fmt( "[ %S ]", ast->ValueType->ArrExpr.to_string() );
@ -1266,12 +1271,20 @@ void CodeVar::to_string( String& result )
} }
if ( ast->Value ) if ( ast->Value )
{
if ( ast->VarConstructorInit )
result.append_fmt( "( %S ", ast->Value.to_string() );
else
result.append_fmt( " = %S", ast->Value.to_string() ); result.append_fmt( " = %S", ast->Value.to_string() );
}
// Keep the chain going... // Keep the chain going...
if ( ast->NextVar ) if ( ast->NextVar )
result.append_fmt( ", %S", ast->NextVar.to_string() ); result.append_fmt( ", %S", ast->NextVar.to_string() );
if ( ast->VarConstructorInit )
result.append( " )");
return; return;
} }
@ -1304,11 +1317,19 @@ void CodeVar::to_string( String& result )
result.append_fmt( " : %S", ast->BitfieldSize.to_string() ); result.append_fmt( " : %S", ast->BitfieldSize.to_string() );
if ( ast->Value ) if ( ast->Value )
{
if ( ast->VarConstructorInit )
result.append_fmt( "( %S ", ast->Value.to_string() );
else
result.append_fmt( " = %S", ast->Value.to_string() ); result.append_fmt( " = %S", ast->Value.to_string() );
}
if ( ast->NextVar ) if ( ast->NextVar )
result.append_fmt( ", %S", ast->NextVar.to_string() ); result.append_fmt( ", %S", ast->NextVar.to_string() );
if ( ast->VarConstructorInit )
result.append( " )");
if ( ast->InlineCmt ) if ( ast->InlineCmt )
result.append_fmt("; %S", ast->InlineCmt->Content); result.append_fmt("; %S", ast->InlineCmt->Content);
else else
@ -1336,11 +1357,19 @@ void CodeVar::to_string( String& result )
result.append_fmt( "%S %S", ast->ValueType.to_string(), ast->Name ); result.append_fmt( "%S %S", ast->ValueType.to_string(), ast->Name );
if ( ast->Value ) if ( ast->Value )
{
if ( ast->VarConstructorInit )
result.append_fmt( "( %S ", ast->Value.to_string() );
else
result.append_fmt( " = %S", ast->Value.to_string() ); result.append_fmt( " = %S", ast->Value.to_string() );
}
if ( ast->NextVar ) if ( ast->NextVar )
result.append_fmt( ", %S", ast->NextVar.to_string() ); result.append_fmt( ", %S", ast->NextVar.to_string() );
if ( ast->VarConstructorInit )
result.append( " )");
result.append( ";" ); result.append( ";" );
if ( ast->InlineCmt ) if ( ast->InlineCmt )

View File

@ -63,7 +63,6 @@ extern CodeAttributes attrib_api_import;
extern Code module_global_fragment; extern Code module_global_fragment;
extern Code module_private_fragment; extern Code module_private_fragment;
// Exposed, but this is really used for parsing.
extern Code fmt_newline; extern Code fmt_newline;
extern CodePragma pragma_once; extern CodePragma pragma_once;

View File

@ -3,6 +3,7 @@
#include "interface.hpp" #include "interface.hpp"
#endif #endif
inline
void AST::append( AST* other ) void AST::append( AST* other )
{ {
if ( other->Parent ) if ( other->Parent )
@ -27,6 +28,7 @@ void AST::append( AST* other )
NumEntries++; NumEntries++;
} }
inline
Code& AST::entry( u32 idx ) Code& AST::entry( u32 idx )
{ {
AST** current = & Front; AST** current = & Front;
@ -42,21 +44,25 @@ Code& AST::entry( u32 idx )
return * rcast( Code*, current); return * rcast( Code*, current);
} }
inline
bool AST::has_entries() bool AST::has_entries()
{ {
return NumEntries; return NumEntries > 0;
} }
inline
char const* AST::type_str() char const* AST::type_str()
{ {
return ECode::to_str( Type ); return ECode::to_str( Type );
} }
inline
AST::operator Code() AST::operator Code()
{ {
return { this }; return { this };
} }
inline
Code& Code::operator ++() Code& Code::operator ++()
{ {
if ( ast ) if ( ast )
@ -65,6 +71,7 @@ Code& Code::operator ++()
return *this; return *this;
} }
inline
void CodeClass::add_interface( CodeType type ) void CodeClass::add_interface( CodeType type )
{ {
CodeType possible_slot = ast->ParentType; CodeType possible_slot = ast->ParentType;
@ -84,6 +91,7 @@ void CodeClass::add_interface( CodeType type )
possible_slot.ast = type.ast; possible_slot.ast = type.ast;
} }
inline
void CodeParam::append( CodeParam other ) void CodeParam::append( CodeParam other )
{ {
AST* self = (AST*) ast; AST* self = (AST*) ast;
@ -107,6 +115,7 @@ void CodeParam::append( CodeParam other )
self->NumEntries++; self->NumEntries++;
} }
inline
CodeParam CodeParam::get( s32 idx ) CodeParam CodeParam::get( s32 idx )
{ {
CodeParam param = *this; CodeParam param = *this;
@ -122,17 +131,20 @@ CodeParam CodeParam::get( s32 idx )
return { nullptr }; return { nullptr };
} }
inline
bool CodeParam::has_entries() bool CodeParam::has_entries()
{ {
return ast->NumEntries > 0; return ast->NumEntries > 0;
} }
inline
CodeParam& CodeParam::operator ++() CodeParam& CodeParam::operator ++()
{ {
ast = ast->Next.ast; ast = ast->Next.ast;
return * this; return * this;
} }
inline
void CodeStruct::add_interface( CodeType type ) void CodeStruct::add_interface( CodeType type )
{ {
CodeType possible_slot = ast->ParentType; CodeType possible_slot = ast->ParentType;
@ -152,6 +164,7 @@ void CodeStruct::add_interface( CodeType type )
possible_slot.ast = type.ast; possible_slot.ast = type.ast;
} }
inline
CodeBody def_body( CodeT type ) CodeBody def_body( CodeT type )
{ {
switch ( type ) switch ( type )
@ -179,6 +192,7 @@ CodeBody def_body( CodeT type )
return (CodeBody)result; return (CodeBody)result;
} }
inline
StrC token_fmt_impl( sw num, ... ) StrC token_fmt_impl( sw num, ... )
{ {
local_persist thread_local local_persist thread_local

View File

@ -374,7 +374,7 @@ AllocatorInfo get_string_allocator( s32 str_length )
uw size_req = str_length + sizeof(String::Header) + sizeof(char*); uw size_req = str_length + sizeof(String::Header) + sizeof(char*);
if ( last->TotalUsed + size_req > last->TotalSize ) if ( last->TotalUsed + sw(size_req) > last->TotalSize )
{ {
Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena );

View File

@ -586,7 +586,7 @@ TokArray lex( StrC content )
{ {
s32 length = 0; s32 length = 0;
char const* scanner = entry.Data; char const* scanner = entry.Data;
while ( entry.length() > length && (char_is_alphanumeric( *scanner ) || *scanner == '_') ) while ( entry.length() > length && char_is_alphanumeric( *scanner ) || *scanner == '_' )
{ {
scanner++; scanner++;
length ++; length ++;
@ -1202,6 +1202,26 @@ TokArray lex( StrC content )
move_forward(); move_forward();
token.Length++; token.Length++;
} }
// Handle number literal suffixes in a botched way
if (left && (
current == 'l' || current == 'L' || // long/long long
current == 'u' || current == 'U' || // unsigned
current == 'f' || current == 'F' || // float
current == 'i' || current == 'I' || // imaginary
current == 'z' || current == 'Z')) // complex
{
char prev = current;
move_forward();
token.Length++;
// Handle 'll'/'LL' as a special case when we just processed an 'l'/'L'
if (left && (prev == 'l' || prev == 'L') && (current == 'l' || current == 'L'))
{
move_forward();
token.Length++;
}
}
} }
goto FoundToken; goto FoundToken;

View File

@ -481,7 +481,7 @@ Code parse_array_decl()
if ( check( TokType::Operator ) && currtok.Text[0] == '[' && currtok.Text[1] == ']' ) if ( check( TokType::Operator ) && currtok.Text[0] == '[' && currtok.Text[1] == ']' )
{ {
Code array_expr = untyped_str( get_cached_string(txt(" ")) ); Code array_expr = untyped_str( currtok );
eat( TokType::Operator ); eat( TokType::Operator );
// [] // []
@ -554,44 +554,6 @@ Code parse_array_decl()
return { nullptr }; return { nullptr };
} }
internal inline
Code parse_assignment_expression()
{
Code expr = { nullptr };
eat( TokType::Operator );
// <Attributes> <Specifiers> <ValueType> <Name> =
Token expr_tok = currtok;
if ( currtok.Type == TokType::Statement_End && currtok.Type != TokType::Comma )
{
log_failure( "Expected expression after assignment operator\n%s", Context.to_string() );
Context.pop();
return CodeInvalid;
}
s32 level = 0;
while ( left && currtok.Type != TokType::Statement_End && (currtok.Type != TokType::Comma || level > 0) )
{
if (currtok.Type == TokType::BraceCurly_Open )
level++;
if (currtok.Type == TokType::BraceCurly_Close )
level--;
if (currtok.Type == TokType::Capture_Start)
level++;
else if (currtok.Type == TokType::Capture_End)
level--;
eat( currtok.Type );
}
expr_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )expr_tok.Text - 1;
expr = untyped_str( expr_tok );
// = <Expression>
return expr;
}
internal inline internal inline
CodeAttributes parse_attributes() CodeAttributes parse_attributes()
{ {
@ -1349,17 +1311,14 @@ CodeDefine parse_define()
eat( TokType::Identifier ); eat( TokType::Identifier );
// #define <Name> // #define <Name>
// Defines don't necessarily need content.
#if 0
if ( ! check( TokType::Preprocess_Content )) if ( ! check( TokType::Preprocess_Content ))
{ {
log_failure( "Error, expected content after #define %s\n%s", define->Name, Context.to_string() ); log_failure( "Error, expected content after #define %s\n%s", define->Name, Context.to_string() );
Context.pop(); Context.pop();
return CodeInvalid; return CodeInvalid;
} }
#endif
if ( check(TokType::Preprocess_Content) && currtok.Length != 0 ) if ( currtok.Length == 0 )
{ {
define->Content = get_cached_string( currtok ); define->Content = get_cached_string( currtok );
eat( TokType::Preprocess_Content ); eat( TokType::Preprocess_Content );
@ -1377,6 +1336,44 @@ CodeDefine parse_define()
return define; return define;
} }
internal inline
Code parse_assignment_expression()
{
Code expr = { nullptr };
eat( TokType::Operator );
// <Attributes> <Specifiers> <ValueType> <Name> =
Token expr_tok = currtok;
if ( currtok.Type == TokType::Statement_End && currtok.Type != TokType::Comma )
{
log_failure( "Expected expression after assignment operator\n%s", Context.to_string() );
Context.pop();
return CodeInvalid;
}
s32 level = 0;
while ( left && currtok.Type != TokType::Statement_End && (currtok.Type != TokType::Comma || level > 0) )
{
if (currtok.Type == TokType::BraceCurly_Open )
level++;
if (currtok.Type == TokType::BraceCurly_Close )
level--;
if (currtok.Type == TokType::Capture_Start)
level++;
else if (currtok.Type == TokType::Capture_End)
level--;
eat( currtok.Type );
}
expr_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )expr_tok.Text - 1;
expr = untyped_str( expr_tok );
// = <Expression>
return expr;
}
internal inline internal inline
Code parse_forward_or_definition( TokType which, bool is_inplace ) Code parse_forward_or_definition( TokType which, bool is_inplace )
{ {
@ -1407,8 +1404,6 @@ Code parse_forward_or_definition( TokType which, bool is_inplace )
return CodeInvalid; return CodeInvalid;
} }
return CodeInvalid;
} }
// Function parsing is handled in multiple places because its initial signature is shared with variable parsing // Function parsing is handled in multiple places because its initial signature is shared with variable parsing
@ -1755,7 +1750,6 @@ CodeBody parse_global_nspace( CodeT which )
case TokType::Spec_Internal_Linkage: case TokType::Spec_Internal_Linkage:
case TokType::Spec_NeverInline: case TokType::Spec_NeverInline:
case TokType::Spec_Static: case TokType::Spec_Static:
case TokType::Spec_ThreadLocal:
{ {
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
s32 NumSpecifiers = 0; s32 NumSpecifiers = 0;
@ -1779,7 +1773,6 @@ CodeBody parse_global_nspace( CodeT which )
case ESpecifier::NeverInline: case ESpecifier::NeverInline:
case ESpecifier::Static: case ESpecifier::Static:
case ESpecifier::Volatile: case ESpecifier::Volatile:
case ESpecifier::Thread_Local:
break; break;
case ESpecifier::Consteval: case ESpecifier::Consteval:
@ -2300,7 +2293,7 @@ CodeOperator parse_operator_after_ret_type(
case '<': case '<':
{ {
if ( currtok.Text[1] == '=' ) if ( currtok.Text[1] == '=' )
op = LesserEqual; op = LEqual;
else if ( currtok.Text[1] == '<' ) else if ( currtok.Text[1] == '<' )
{ {
@ -2540,7 +2533,14 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
Token name = parse_identifier(); Token name = parse_identifier();
Context.Scope->Name = name; Context.Scope->Name = name;
if ( check( TokType::Capture_Start) ) bool detected_capture = check( TokType::Capture_Start );
// Check three tokens ahead to make sure that were not dealing with a constructor initialization...
// ( 350.0f , <--- Could be the scenario
// Example : <Capture_Start> <Value> <Comma>
// idx +1 +2
bool detected_comma = Context.Tokens.Arr[ Context.Tokens.Idx + 2 ].Type == TokType::Comma;
if ( detected_capture && ! detected_comma )
{ {
// Dealing with a function // Dealing with a function
result = parse_function_after_name( ModuleFlag::None, attributes, specifiers, type, name ); result = parse_function_after_name( ModuleFlag::None, attributes, specifiers, type, name );
@ -2629,6 +2629,7 @@ CodeParam parse_params( bool use_template_capture )
CodeType type = { nullptr }; CodeType type = { nullptr };
Code value = { nullptr }; Code value = { nullptr };
Token name = NullToken; Token name = NullToken;
Code post_name_macro = { nullptr };
if ( check( TokType::Varadic_Argument ) ) if ( check( TokType::Varadic_Argument ) )
{ {
@ -2670,6 +2671,15 @@ CodeParam parse_params( bool use_template_capture )
// ( <Macro> <ValueType> <Name> // ( <Macro> <ValueType> <Name>
} }
// Unreal has yet another type of macro:
// template<class T UE_REQUIRES(TPointerIsConvertibleFromTo<T, UInterface>::Value)>
// class T ... and then ^this^ UE_REQUIRES shows up
// So we need to consume that.
if ( check( TokType::Preprocess_Macro ))
{
post_name_macro = parse_simple_preprocess( ETokType::Preprocess_Macro );
}
// In template captures you can have a typename have direct assignment without a name // In template captures you can have a typename have direct assignment without a name
// typename = typename ... // typename = typename ...
// Which would result in a static value type from a struct expansion (traditionally) // Which would result in a static value type from a struct expansion (traditionally)
@ -2689,7 +2699,7 @@ CodeParam parse_params( bool use_template_capture )
s32 capture_level = 0; s32 capture_level = 0;
s32 template_level = 0; s32 template_level = 0;
while ( left && (currtok.Type != TokType::Comma) && template_level >= 0 && (CheckEndParams() || capture_level > 0 || template_level > 0) ) while ( left && ( currtok.Type != TokType::Comma ) && template_level >= 0 && CheckEndParams() || capture_level > 0 || template_level > 0 )
{ {
if (currtok.Text[ 0 ] == '<') if (currtok.Text[ 0 ] == '<')
++ template_level; ++ template_level;
@ -2773,6 +2783,15 @@ CodeParam parse_params( bool use_template_capture )
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> // ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name>
} }
// Unreal has yet another type of macro:
// template<class T UE_REQUIRES(TPointerIsConvertibleFromTo<T, UInterface>::Value)>
// class T ... and then ^this^ UE_REQUIRES shows up
// So we need to consume that.
if ( check( TokType::Preprocess_Macro ))
{
post_name_macro = parse_simple_preprocess( ETokType::Preprocess_Macro );
}
// In template captures you can have a typename have direct assignment without a name // In template captures you can have a typename have direct assignment without a name
// typename = typename ... // typename = typename ...
// Which would result in a static value type from a struct expansion (traditionally) // Which would result in a static value type from a struct expansion (traditionally)
@ -2795,7 +2814,7 @@ CodeParam parse_params( bool use_template_capture )
while ( left while ( left
&& currtok.Type != TokType::Comma && currtok.Type != TokType::Comma
&& template_level >= 0 && template_level >= 0
&& (CheckEndParams() || capture_level > 0 || template_level > 0) ) && CheckEndParams() || capture_level > 0 || template_level > 0 )
{ {
if (currtok.Text[ 0 ] == '<') if (currtok.Text[ 0 ] == '<')
++ template_level; ++ template_level;
@ -2829,6 +2848,7 @@ CodeParam parse_params( bool use_template_capture )
if ( name.Length > 0 ) if ( name.Length > 0 )
param->Name = get_cached_string( name ); param->Name = get_cached_string( name );
param->PostNameMacro = post_name_macro;
param->ValueType = type; param->ValueType = type;
if ( value ) if ( value )
@ -2872,7 +2892,7 @@ CodePreprocessCond parse_preprocess_cond()
CodePreprocessCond CodePreprocessCond
cond = (CodePreprocessCond) make_code(); cond = (CodePreprocessCond) make_code();
cond->Type = scast(CodeT, currtok.Type - (s32(ETokType::Preprocess_If) - s32(ECode::Preprocess_If)) ); cond->Type = scast(CodeT, currtok.Type - ( TokType::Preprocess_If - ECode::Preprocess_If ) );
eat( currtok.Type ); eat( currtok.Type );
// #<Conditional> // #<Conditional>
@ -3067,6 +3087,8 @@ CodeVar parse_variable_after_name(
Code expr = { nullptr }; Code expr = { nullptr };
Code bitfield_expr = { nullptr }; Code bitfield_expr = { nullptr };
b32 using_constructor_initializer = false;
if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
{ {
// <Attributes> <Specifiers> <ValueType> <Name> = <Expression> // <Attributes> <Specifiers> <ValueType> <Name> = <Expression>
@ -3098,6 +3120,33 @@ CodeVar parse_variable_after_name(
// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> } // <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> }
} }
if ( currtok.Type == TokType::Capture_Start )
{
eat( TokType:: Capture_Start);
// <Attributes> <Specifiers> <ValueType> <Name> (
Token expr_token = currtok;
using_constructor_initializer = true;
s32 level = 0;
while ( left && ( currtok.Type != TokType::Capture_End || level > 0 ) )
{
if ( currtok.Type == TokType::Capture_Start )
level++;
else if ( currtok.Type == TokType::Capture_End && level > 0 )
level--;
eat( currtok.Type );
}
expr_token.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)expr_token.Text;
expr = untyped_str( expr_token );
eat( TokType::Capture_End );
// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> )
}
if ( currtok.Type == TokType::Assign_Classifer ) if ( currtok.Type == TokType::Assign_Classifer )
{ {
eat( TokType::Assign_Classifer ); eat( TokType::Assign_Classifer );
@ -3192,6 +3241,8 @@ CodeVar parse_variable_after_name(
result->NextVar->Parent = result; result->NextVar->Parent = result;
} }
result->VarConstructorInit = using_constructor_initializer;
Context.pop(); Context.pop();
return result; return result;
} }
@ -3246,7 +3297,7 @@ CodeVar parse_variable_declaration_list()
break; break;
} }
eat(currtok.Type); // eat(currtok.Type);
if ( specifiers ) if ( specifiers )
specifiers.append( spec ); specifiers.append( spec );
@ -3650,11 +3701,11 @@ CodeEnum parse_enum( bool inplace_def )
} }
// Consume inline comments // Consume inline comments
if ( currtok.Type == TokType::Comment && prevtok.Line == currtok.Line ) // if ( currtok.Type == TokType::Comment && prevtok.Line == currtok.Line )
{ // {
eat( TokType::Comment ); // eat( TokType::Comment );
// <Name> = <Expression> <Macro>, // <Inline Comment> // <Name> = <Expression> <Macro>, // <Inline Comment>
} // }
entry.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)entry.Text; entry.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)entry.Text;
@ -4399,13 +4450,10 @@ CodeType parse_type( bool from_template, bool* typedef_is_function )
else if ( currtok.Type == TokType::Decl_Class || currtok.Type == TokType::Decl_Enum || currtok.Type == TokType::Decl_Struct else if ( currtok.Type == TokType::Decl_Class || currtok.Type == TokType::Decl_Enum || currtok.Type == TokType::Decl_Struct
|| currtok.Type == TokType::Decl_Union ) || currtok.Type == TokType::Decl_Union )
{ {
Token fwd_key = currtok;
eat( currtok.Type ); eat( currtok.Type );
// <Attributes> <Specifiers> <class, enum, struct, union> // <Attributes> <Specifiers> <class, enum, struct, union>
name = parse_identifier(); name = parse_identifier();
fwd_key.Length = sptr(name.Text + name.Length) - sptr(fwd_key.Text);
name = fwd_key;
// name.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )name.Text; // name.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )name.Text;
// eat( TokType::Identifier ); // eat( TokType::Identifier );

View File

@ -71,6 +71,7 @@ enum class ModuleFlag : u32
Invalid, Invalid,
}; };
inline
StrC to_str( ModuleFlag flag ) StrC to_str( ModuleFlag flag )
{ {
local_persist local_persist
@ -86,6 +87,7 @@ StrC to_str( ModuleFlag flag )
return lookup[ (u32)flag ]; return lookup[ (u32)flag ];
} }
inline
ModuleFlag operator|( ModuleFlag A, ModuleFlag B) ModuleFlag operator|( ModuleFlag A, ModuleFlag B)
{ {
return (ModuleFlag)( (u32)A | (u32)B ); return (ModuleFlag)( (u32)A | (u32)B );

View File

@ -50,6 +50,11 @@ struct Array
return 2 * value + 8; return 2 * value + 8;
} }
bool append( Array other )
{
return append( other, other.num() );
}
bool append( Type value ) bool append( Type value )
{ {
Header* header = get_header(); Header* header = get_header();
@ -158,7 +163,7 @@ struct Array
if ( begin < 0 || end > header.Num ) if ( begin < 0 || end > header.Num )
return false; return false;
for ( sw idx = begin; idx < end; idx++ ) for ( sw idx = sw(begin); idx < sw(end); idx++ )
{ {
Data[ idx ] = value; Data[ idx ] = value;
} }
@ -365,7 +370,7 @@ struct HashTable
{ {
GEN_ASSERT_NOT_NULL( map_proc ); GEN_ASSERT_NOT_NULL( map_proc );
for ( sw idx = 0; idx < Entries.num(); idx++ ) for ( sw idx = 0; idx < sw(Entries.num()); ++idx )
{ {
map_proc( Entries[ idx ].Key, Entries[ idx ].Value ); map_proc( Entries[ idx ].Key, Entries[ idx ].Value );
} }
@ -377,7 +382,7 @@ struct HashTable
{ {
GEN_ASSERT_NOT_NULL( map_proc ); GEN_ASSERT_NOT_NULL( map_proc );
for ( sw idx = 0; idx < Entries.num(); idx++ ) for ( sw idx = 0; idx < sw(Entries.num()); ++idx )
{ {
map_proc( Entries[ idx ].Key, & Entries[ idx ].Value ); map_proc( Entries[ idx ].Key, & Entries[ idx ].Value );
} }

View File

@ -594,7 +594,7 @@ internal GEN_FILE_WRITE_AT_PROC( _memory_file_write )
{ {
Array<u8> arr = { d->buf }; Array<u8> arr = { d->buf };
if ( arr.get_header()->Capacity < new_cap ) if ( arr.get_header()->Capacity < uw(new_cap) )
{ {
if ( ! arr.grow( ( s64 )( new_cap ) ) ) if ( ! arr.grow( ( s64 )( new_cap ) ) )
return false; return false;

View File

@ -13,6 +13,7 @@
#define internal static // Internal linkage #define internal static // Internal linkage
#define local_persist static // Local Persisting variables #define local_persist static // Local Persisting variables
#pragma region ForceInline_Definition
#ifdef GEN_COMPILER_MSVC #ifdef GEN_COMPILER_MSVC
# define forceinline __forceinline # define forceinline __forceinline
# define neverinline __declspec( noinline ) # define neverinline __declspec( noinline )
@ -31,18 +32,23 @@
# define forceinline # define forceinline
# define neverinline # define neverinline
#endif #endif
#pragma endregion ForceInline_Definition
// Bits // Bits
#ifndef bit
#define bit( Value ) ( 1 << Value ) #define bit( Value ) ( 1 << Value )
#define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) )
#endif
// Casting // Casting
#ifndef ccast
#define ccast( Type, Value ) ( * const_cast< Type* >( & (Value) ) ) #define ccast( Type, Value ) ( * const_cast< Type* >( & (Value) ) )
#define pcast( Type, Value ) ( * reinterpret_cast< Type* >( & ( Value ) ) ) #define pcast( Type, Value ) ( * reinterpret_cast< Type* >( & ( Value ) ) )
#define rcast( Type, Value ) reinterpret_cast< Type >( Value ) #define rcast( Type, Value ) reinterpret_cast< Type >( Value )
#define scast( Type, Value ) static_cast< Type >( Value ) #define scast( Type, Value ) static_cast< Type >( Value )
#endif
// Num Arguments (Varadics) // Num Arguments (Varadics)
// #if defined(__GNUC__) || defined(__clang__) // #if defined(__GNUC__) || defined(__clang__)

View File

@ -445,10 +445,14 @@ struct Arena
return alignment_offset; return alignment_offset;
} }
// This id is defined by Unreal for asserts
#pragma push_macro("check")
#undef check
void check() void check()
{ {
GEN_ASSERT( TempCount == 0 ); GEN_ASSERT( TempCount == 0 );
} }
#pragma pop_macro("check")
void free() void free()
{ {

View File

@ -124,7 +124,7 @@ bool String::make_space_for( char const* str, sw add_len )
Data = rcast( char*, header + 1 ); Data = rcast( char*, header + 1 );
return str; return true;
} }
} }
#pragma endregion String #pragma endregion String

View File

@ -139,7 +139,7 @@ struct String
header.Length = curr_len + length; header.Length = curr_len + length;
} }
return str; return str != nullptr;
} }
bool append( StrC str) bool append( StrC str)
@ -353,7 +353,7 @@ struct String
operator bool() operator bool()
{ {
return Data; return Data != nullptr;
} }
operator char* () operator char* ()

View File

@ -35,6 +35,7 @@ CodeBody gen_ecode( char const* path )
#pragma push_macro("local_persist") #pragma push_macro("local_persist")
#undef local_persist #undef local_persist
CodeFn to_str = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( CodeFn to_str = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize(
inline
StrC to_str( Type type ) StrC to_str( Type type )
{ {
local_persist local_persist
@ -89,6 +90,7 @@ CodeBody gen_eoperator( char const* path )
#pragma push_macro("local_persist") #pragma push_macro("local_persist")
#undef local_persist #undef local_persist
CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize(
inline
StrC to_str( Type op ) StrC to_str( Type op )
{ {
local_persist local_persist
@ -142,6 +144,7 @@ CodeBody gen_especifier( char const* path )
))); )));
CodeFn is_trailing = parse_function(token_fmt("specifier", (StrC)to_str_entries, stringize( CodeFn is_trailing = parse_function(token_fmt("specifier", (StrC)to_str_entries, stringize(
inline
bool is_trailing( Type specifier ) bool is_trailing( Type specifier )
{ {
return specifier > Virtual; return specifier > Virtual;
@ -159,6 +162,7 @@ CodeBody gen_especifier( char const* path )
#undef forceinline #undef forceinline
#undef neverinline #undef neverinline
CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize(
inline
StrC to_str( Type type ) StrC to_str( Type type )
{ {
local_persist local_persist
@ -171,6 +175,7 @@ CodeBody gen_especifier( char const* path )
))); )));
CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize(
inline
Type to_type( StrC str ) Type to_type( StrC str )
{ {
local_persist local_persist
@ -282,6 +287,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path )
#undef do_once_start #undef do_once_start
#undef do_once_end #undef do_once_end
CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, "attribute_toks", (StrC)to_str_attributes, stringize( CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, "attribute_toks", (StrC)to_str_attributes, stringize(
inline
StrC to_str( Type type ) StrC to_str( Type type )
{ {
local_persist local_persist
@ -295,6 +301,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path )
))); )));
CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize(
inline
Type to_type( StrC str ) Type to_type( StrC str )
{ {
local_persist local_persist
@ -339,6 +346,7 @@ CodeBody gen_ast_inlines()
#undef log_failure #undef log_failure
char const* code_impl_tmpl = stringize( char const* code_impl_tmpl = stringize(
\n \n
inline
char const* <typename>::debug_str() char const* <typename>::debug_str()
{ {
if ( ast == nullptr ) if ( ast == nullptr )
@ -346,6 +354,7 @@ CodeBody gen_ast_inlines()
return rcast(AST*, ast)->debug_str(); return rcast(AST*, ast)->debug_str();
} }
inline
Code <typename>::duplicate() Code <typename>::duplicate()
{ {
if ( ast == nullptr ) if ( ast == nullptr )
@ -356,19 +365,23 @@ CodeBody gen_ast_inlines()
return { rcast(AST*, ast)->duplicate() }; return { rcast(AST*, ast)->duplicate() };
} }
inline
bool <typename>::is_equal( Code other ) bool <typename>::is_equal( Code other )
{ {
if ( ast == nullptr || other.ast == nullptr ) if ( ast == nullptr || other.ast == nullptr )
{ {
// Just check if they're both null. // Just check if they're both null.
return rcast(AST*, ast) == other.ast; log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
} }
return rcast(AST*, ast)->is_equal( other.ast ); return rcast(AST*, ast)->is_equal( other.ast );
} }
inline
bool <typename>::is_valid() bool <typename>::is_valid()
{ {
return (AST*) ast != nullptr && rcast( AST*, ast)->Type != CodeT::Invalid; return (AST*) ast != nullptr && rcast( AST*, ast)->Type != CodeT::Invalid;
} }
inline
void <typename>::set_global() void <typename>::set_global()
{ {
if ( ast == nullptr ) if ( ast == nullptr )
@ -379,6 +392,7 @@ CodeBody gen_ast_inlines()
rcast(AST*, ast)->Parent = Code::Global.ast; rcast(AST*, ast)->Parent = Code::Global.ast;
} }
inline
<typename>& <typename>::operator =( Code other ) <typename>& <typename>::operator =( Code other )
{ {
if ( other.ast && other->Parent ) if ( other.ast && other->Parent )
@ -390,14 +404,17 @@ CodeBody gen_ast_inlines()
ast = rcast( decltype(ast), other.ast ); ast = rcast( decltype(ast), other.ast );
return *this; return *this;
} }
inline
bool <typename>::operator ==( Code other ) bool <typename>::operator ==( Code other )
{ {
return (AST*) ast == other.ast; return (AST*) ast == other.ast;
} }
inline
bool <typename>::operator !=( Code other ) bool <typename>::operator !=( Code other )
{ {
return (AST*) ast != other.ast; return (AST*) ast != other.ast;
} }
inline
<typename>::operator bool() <typename>::operator bool()
{ {
return ast != nullptr; return ast != nullptr;
@ -405,14 +422,17 @@ CodeBody gen_ast_inlines()
); );
char const* codetype_impl_tmpl = stringize( char const* codetype_impl_tmpl = stringize(
inline
AST* Code<typename>::raw() AST* Code<typename>::raw()
{ {
return rcast( AST*, ast ); return rcast( AST*, ast );
} }
inline
Code<typename>::operator Code() Code<typename>::operator Code()
{ {
return *rcast( Code*, this ); return *rcast( Code*, this );
} }
inline
AST_<typename>* Code<typename>::operator->() AST_<typename>* Code<typename>::operator->()
{ {
if ( ast == nullptr ) if ( ast == nullptr )
@ -480,11 +500,12 @@ CodeBody gen_ast_inlines()
impl_code_var. append( parse_global_body( token_fmt( "typename", StrC name(Var), codetype_impl_tmpl ))); impl_code_var. append( parse_global_body( token_fmt( "typename", StrC name(Var), codetype_impl_tmpl )));
char const* cast_tmpl = stringize( char const* cast_tmpl = stringize(
inline
AST::operator Code<typename>() AST::operator Code<typename>()
{ {
return { rcast( AST_<typename>*, this ) }; return { rcast( AST_<typename>*, this ) };
} }
inline
Code::operator Code<typename>() const Code::operator Code<typename>() const
{ {
return { (AST_<typename>*) ast }; return { (AST_<typename>*) ast };

View File

@ -1,7 +1,7 @@
#if __clang__ #ifdef __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop
#endif #endif
#if __GNUC__ #ifdef __GNUC__
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif

View File

@ -1,4 +1,4 @@
#if __clang__ #ifdef __clang__
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-const-variable" # pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wunused-but-set-variable" # pragma clang diagnostic ignored "-Wunused-but-set-variable"
@ -9,7 +9,7 @@
# pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-function"
#endif #endif
#if __GNUC__ #ifdef __GNUC__
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunknown-pragmas" # pragma GCC diagnostic ignored "-Wunknown-pragmas"
# pragma GCC diagnostic ignored "-Wcomment" # pragma GCC diagnostic ignored "-Wcomment"