mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	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:
		| @@ -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 ) ); | ||||||
|   | |||||||
| @@ -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" ); | ||||||
|   | |||||||
| @@ -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. | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 ) | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 ); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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 ); | ||||||
|   | |||||||
| @@ -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 ); | ||||||
|   | |||||||
| @@ -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 ); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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__) | ||||||
|   | |||||||
| @@ -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() | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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* () | ||||||
|   | |||||||
| @@ -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 }; | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user