mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	changes based off of metadesk genc_c11
This commit is contained in:
		| @@ -38,13 +38,13 @@ void body_to_strbuilder_export( CodeBody body, StrBuilder* result ) | ||||
| 	GEN_ASSERT(result != nullptr); | ||||
| 	strbuilder_append_fmt( result, "export\n{\n" ); | ||||
|  | ||||
| 	Code curr = cast(Code, body); | ||||
| 	Code curr = body->Front; | ||||
| 	s32  left = body->NumEntries; | ||||
| 	while ( left-- ) | ||||
| 	{ | ||||
| 		code_to_strbuilder_ref(curr, result); | ||||
| 		// strbuilder_append_fmt( result, "%SB", code_to_strbuilder(curr) ); | ||||
| 		++curr; | ||||
| 		curr = curr->Next; | ||||
| 	} | ||||
|  | ||||
| 	strbuilder_append_fmt( result, "};\n" ); | ||||
|   | ||||
| @@ -38,7 +38,7 @@ void body_to_strbuilder_ref( CodeBody body, StrBuilder* result ) | ||||
| 	{ | ||||
| 		code_to_strbuilder_ref(curr, result); | ||||
| 		// strbuilder_append_fmt( result, "%SB", code_to_strbuilder(curr) ); | ||||
| 		++curr; | ||||
| 		curr = curr->Next; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -283,6 +283,15 @@ void init(Context* ctx) | ||||
| 		ctx->InitSize_Fallback_Allocator_Bucket_Size = megabytes(8); | ||||
| 	} | ||||
|  | ||||
| 	if (ctx->InitSize_StrCacheTable == 0) | ||||
| 	{ | ||||
| 		ctx->InitSize_StrCacheTable = kilobytes(8); | ||||
| 	} | ||||
| 	if (ctx->InitSize_MacrosTable == 0) | ||||
| 	{ | ||||
| 		ctx->InitSize_MacrosTable = kilobytes(8); | ||||
| 	} | ||||
|  | ||||
| 	// Override the current context (user has to put it back if unwanted). | ||||
| 	_ctx = ctx; | ||||
|  | ||||
| @@ -311,11 +320,11 @@ void init(Context* ctx) | ||||
| 	} | ||||
| 	// Setup the hash tables | ||||
| 	{ | ||||
| 		ctx->StrCache = hashtable_init(StrCached, ctx->Allocator_DyanmicContainers); | ||||
| 		ctx->StrCache = hashtable_init_reserve(StrCached, ctx->Allocator_DyanmicContainers, ctx->InitSize_StrCacheTable); | ||||
| 		if ( ctx->StrCache.Entries == nullptr ) | ||||
| 			GEN_FATAL( "gen::init: Failed to initialize the StringCache"); | ||||
|  | ||||
| 		ctx->Macros = hashtable_init(Macro, ctx->Allocator_DyanmicContainers); | ||||
| 		ctx->Macros = hashtable_init_reserve(Macro, ctx->Allocator_DyanmicContainers, ctx->InitSize_MacrosTable); | ||||
| 		if (ctx->Macros.Hashes == nullptr || ctx->Macros.Entries == nullptr) { | ||||
| 			GEN_FATAL( "gen::init: Failed to initialize the PreprocessMacros table" ); | ||||
| 		} | ||||
|   | ||||
| @@ -64,6 +64,9 @@ struct Context | ||||
| 	u32 InitSize_LexerTokens; | ||||
| 	u32 SizePer_StringArena; | ||||
|  | ||||
| 	u32 InitSize_StrCacheTable; | ||||
| 	u32 InitSize_MacrosTable; | ||||
|  | ||||
| // TODO(Ed): Symbol Table | ||||
| 	// Keep track of all resolved symbols (naemspaced identifiers) | ||||
|  | ||||
|   | ||||
| @@ -1443,6 +1443,22 @@ CodeFn parse_function_after_name( | ||||
| 	} | ||||
| 	// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> | ||||
|  | ||||
| 	// Check for trailing specifiers... | ||||
| 	CodeAttributes post_rt_attributes = parse_attributes(); | ||||
| 	if (post_rt_attributes) | ||||
| 	{ | ||||
| 		if (attributes) | ||||
| 		{ | ||||
| 			StrBuilder merged   =  strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S %S", attributes->Content, post_rt_attributes->Content); | ||||
| 			attributes->Content = cache_str(strbuilder_to_str(merged)); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			attributes = post_rt_attributes; | ||||
| 		} | ||||
| 	} | ||||
| 	// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> <Attributes>  | ||||
|  | ||||
| 	CodeBody    body       = NullCode; | ||||
| 	CodeComment inline_cmt = NullCode; | ||||
| 	if ( check( Tok_BraceCurly_Open ) ) | ||||
| @@ -1481,17 +1497,19 @@ CodeFn parse_function_after_name( | ||||
| 		 | ||||
| 		if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) | ||||
| 			inline_cmt = parse_comment(); | ||||
| 		// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>; <InlineCmt> | ||||
| 			// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> < = 0 or delete > ; <InlineCmt> | ||||
| 	} | ||||
| 	else | ||||
|  | ||||
|  | ||||
| 	if (body == nullptr) | ||||
| 	{ | ||||
| 		Token stmt_end = currtok; | ||||
| 		eat( Tok_Statement_End ); | ||||
| 		// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>; | ||||
| 		// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> <Attributes> < = 0 or delete > ; | ||||
|  | ||||
| 		if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) | ||||
| 			inline_cmt = parse_comment(); | ||||
| 			// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>; <InlineCmt> | ||||
| 			// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> < = 0 or delete > ; <InlineCmt> | ||||
| 	} | ||||
|  | ||||
| 	StrBuilder | ||||
| @@ -1766,7 +1784,7 @@ CodeBody parse_global_nspace( CodeType which ) | ||||
|  | ||||
| 			case Tok_Preprocess_Macro_Expr:  | ||||
| 			{ | ||||
| 				if (tok_is_attribute(currtok)) | ||||
| 				if ( ! tok_is_attribute(currtok)) | ||||
| 				{ | ||||
| 					log_failure("Unbounded macro expression residing in class/struct body\n%S", parser_to_strbuilder(_ctx->parser)); | ||||
| 					return InvalidCode; | ||||
| @@ -2049,11 +2067,20 @@ Token parse_identifier( bool* possible_member_function ) | ||||
|  | ||||
| 	Macro* macro = lookup_macro(currtok.Text); | ||||
| 	b32 accept_as_identifier = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Identifier ); | ||||
| 	b32 is_decarator         = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Identifier_Decorator ); | ||||
|  | ||||
| 	// Typename can be: '::' <name> | ||||
| 	// If that is the case first  option will be Tok_Access_StaticSymbol below | ||||
| 	if (check(Tok_Identifier) || accept_as_identifier) | ||||
| 		eat( Tok_Identifier ); | ||||
| 	if (check(Tok_Identifier) || accept_as_identifier)  | ||||
| 	{ | ||||
| 		if (is_decarator) { | ||||
| 			Code name_macro = parse_simple_preprocess(currtok.Type); | ||||
| 			name.Text.Len   = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr; | ||||
| 		}	 | ||||
| 		else { | ||||
| 			eat(Tok_Identifier); | ||||
| 		} | ||||
| 	} | ||||
| 	// <Name> | ||||
|  | ||||
| 	parse_template_args( & name ); | ||||
| @@ -4714,21 +4741,37 @@ CodeTypename parser_parse_type( bool from_template, bool* typedef_is_function ) | ||||
| 	else if ( currtok.Type == Tok_Decl_Class || currtok.Type == Tok_Decl_Enum || currtok.Type == Tok_Decl_Struct | ||||
| 			|| currtok.Type == Tok_Decl_Union ) | ||||
| 	{ | ||||
| 		switch (currtok.Type) { | ||||
| 			case Tok_Decl_Class  : tag = Tag_Class;  break; | ||||
| 			case Tok_Decl_Enum   : tag = Tag_Enum;   break; | ||||
| 			case Tok_Decl_Struct : tag = Tag_Struct; break; | ||||
| 			case Tok_Decl_Union  : tag = Tag_Union;  break; | ||||
| 			default: | ||||
| 				break; | ||||
| 		Token next = nexttok; | ||||
|  | ||||
| 		if (next.Type == Tok_Identifier) | ||||
| 		{ | ||||
| 			switch (currtok.Type) { | ||||
| 				case Tok_Decl_Class  : tag = Tag_Class;  break; | ||||
| 				case Tok_Decl_Enum   : tag = Tag_Enum;   break; | ||||
| 				case Tok_Decl_Struct : tag = Tag_Struct; break; | ||||
| 				case Tok_Decl_Union  : tag = Tag_Union;  break; | ||||
| 				default: | ||||
| 					break; | ||||
| 			} | ||||
| 			eat( currtok.Type ); | ||||
| 			// <Attributes> <Specifiers> <class, enum, struct, union> | ||||
|  | ||||
| 			name = parse_identifier(nullptr); | ||||
| 			// <Attributes> <Specifiers> <class, enum, struct, union> <Name>  | ||||
| 		} | ||||
| 		eat( currtok.Type ); | ||||
| 		// <Attributes> <Specifiers> <class, enum, struct, union> | ||||
| 		else if  (next.Type == Tok_BraceCurly_Open) | ||||
| 		{ | ||||
| 			name = currtok; | ||||
| 			// We have an inplace definition, we need to consume that... | ||||
|  | ||||
| 		name = parse_identifier(nullptr); | ||||
| 			// TODO(Ed): we need to add a way for AST_CodeTypename to track an implace definition.. | ||||
| 			b32 const inplace = true; | ||||
| 			Code indplace_def = cast(Code, parser_parse_struct(inplace)); | ||||
|  | ||||
| 		// name.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )name.Text; | ||||
| 		// eat( Tok_Identifier ); | ||||
| 			// For now we lose the structural information,  | ||||
| 			name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr; | ||||
| 			// <Attributes> <Specifiers> <class, enum, struct, union> <inplace def> | ||||
| 		} | ||||
| 		_ctx->parser.Scope->Name = name.Text; | ||||
| 		// <Attributes> <Specifiers> <class, enum, struct, union> <Name> | ||||
| 	} | ||||
|   | ||||
| @@ -168,26 +168,36 @@ Str macrotype_to_str( MacroType type ) | ||||
|  | ||||
| enum EMacroFlags : u16 | ||||
| { | ||||
| 	MF_Functional          = bit(0), // Macro has parameters (args expected to be passed) | ||||
| 	MF_Expects_Body        = bit(1), // Expects to assign a braced scope to its body. | ||||
| 	// Macro has parameters (args expected to be passed) | ||||
| 	MF_Functional          = bit(0),  | ||||
|  | ||||
| 	// Expects to assign a braced scope to its body. | ||||
| 	MF_Expects_Body        = bit(1),  | ||||
|  | ||||
| 	// lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one. | ||||
| 	//  ^^^ This is a kludge because we don't support push/pop macro pragmas rn. | ||||
| 	// This is a kludge because we don't support push/pop macro pragmas rn. | ||||
| 	MF_Allow_As_Identifier = bit(2),  | ||||
|  | ||||
| 	// When parsing identifiers, it will allow the consumption of the macro parameters (as its expected to be a part of constructing the identifier) | ||||
| 	// Example of a decarator macro from stb_sprintf.h:  | ||||
| 	// STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char* buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); | ||||
| 	//                       ^^ STB_SPRINTF_DECORATE is decorating sprintf | ||||
| 	MF_Identifier_Decorator = bit(3),  | ||||
|  | ||||
| 	// lex__eat wil treat this macro as an attribute if the parser attempts to consume it as one. | ||||
| 	//  ^^^ This a kludge because unreal has a macro that behaves as both a 'statement' and an attribute (UE_DEPRECATED, PRAGMA_ENABLE_DEPRECATION_WARNINGS, etc) | ||||
| 	// This a kludge because unreal has a macro that behaves as both a 'statement' and an attribute (UE_DEPRECATED, PRAGMA_ENABLE_DEPRECATION_WARNINGS, etc) | ||||
| 	// TODO(Ed): We can keep the MF_Allow_As_Attribute flag for macros, however, we need to add the ability of AST_Attributes to chain themselves. | ||||
| 	// Its thats already a thing in the standard language anyway | ||||
| 	// & it would allow UE_DEPRECATED, (UE_PROPERTY / UE_FUNCTION) to chain themselves as attributes of a resolved member function/variable definition | ||||
| 	MF_Allow_As_Attribute  = bit(3), | ||||
| 	MF_Allow_As_Attribute  = bit(4), | ||||
|  | ||||
| 	// When a macro is encountered after attributes and specifiers while parsing a function, or variable: | ||||
| 	// It will consume the macro and treat it as resolving the definition. (Yes this is for Unreal Engine) | ||||
| 	// It will consume the macro and treat it as resolving the definition. | ||||
| 	// (MUST BE OF MT_Statement TYPE) | ||||
| 	MF_Allow_As_Definition = bit(4), | ||||
| 	MF_Allow_As_Definition = bit(5), | ||||
|  | ||||
| 	MF_Allow_As_Specifier = bit(5), // Created for Unreal's PURE_VIRTUAL | ||||
| 	// Created for Unreal's PURE_VIRTUAL | ||||
| 	MF_Allow_As_Specifier = bit(6), | ||||
|  | ||||
| 	MF_Null           = 0, | ||||
| 	MF_UnderlyingType = GEN_U16_MAX, | ||||
|   | ||||
| @@ -198,21 +198,16 @@ | ||||
| #ifndef        forceinline | ||||
| #	if GEN_COMPILER_MSVC | ||||
| #		define forceinline __forceinline | ||||
| #		define neverinline __declspec( noinline ) | ||||
| #	elif GEN_COMPILER_GCC | ||||
| #		define forceinline inline __attribute__((__always_inline__)) | ||||
| #		define neverinline __attribute__( ( __noinline__ ) ) | ||||
| #	elif GEN_COMPILER_CLANG | ||||
| #	if __has_attribute(__always_inline__) | ||||
| #		define forceinline inline __attribute__((__always_inline__)) | ||||
| #		define neverinline __attribute__( ( __noinline__ ) ) | ||||
| #	else | ||||
| #		define forceinline | ||||
| #		define neverinline | ||||
| #	endif | ||||
| #	else | ||||
| #		define forceinline | ||||
| #		define neverinline | ||||
| #	endif | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -138,7 +138,7 @@ constexpr AllocatorInfo heap( void ) { AllocatorInfo allocator = { heap_allocato | ||||
| #define malloc( sz ) alloc( heap(), sz ) | ||||
|  | ||||
| //! Helper to free memory allocated by heap allocator. | ||||
| #define mfree( ptr ) free( heap(), ptr ) | ||||
| #define mfree( ptr ) allocator_free( heap(), ptr ) | ||||
|  | ||||
| struct VirtualMemory | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user