mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	Design: Added additional keywords to specifiers, added def_friend. Fleshed out scanner.
This commit is contained in:
		
							
								
								
									
										368
									
								
								project/gen.cpp
									
									
									
									
									
								
							
							
						
						
									
										368
									
								
								project/gen.cpp
									
									
									
									
									
								
							| @@ -71,10 +71,11 @@ namespace gen | |||||||
| 		static StringTable StringMap; | 		static StringTable StringMap; | ||||||
| 		static TypeTable   TypeMap; | 		static TypeTable   TypeMap; | ||||||
|  |  | ||||||
| 		static sw InitSize_CodePool       = megabytes(64); | 		static sw InitSize_CodePool            = megabytes(64); | ||||||
| 		static sw InitSize_StringArena    = megabytes(32); | 		static sw InitSize_StringTable         = megabytes(4); | ||||||
| 		static sw InitSize_StringTable    = megabytes(4); | 		static sw InitSize_TypeTable           = megabytes(4); | ||||||
| 		static sw InitSize_TypeTable      = megabytes(4); |  | ||||||
|  | 		static sw SizePer_StringArena          = megabytes(32); | ||||||
|  |  | ||||||
| 		static allocator Allocator_CodePool    = heap(); | 		static allocator Allocator_CodePool    = heap(); | ||||||
| 		static allocator Allocator_StringArena = heap(); | 		static allocator Allocator_StringArena = heap(); | ||||||
| @@ -111,33 +112,6 @@ namespace gen | |||||||
| 	Code spec_inline; | 	Code spec_inline; | ||||||
| #pragma endregion CONSTANTS | #pragma endregion CONSTANTS | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Used internally to retireve a Code object form the CodePool. |  | ||||||
| 	*/ |  | ||||||
| 	static Code make_code() |  | ||||||
| 	{ |  | ||||||
| 		using namespace StaticData; |  | ||||||
|  |  | ||||||
| #	ifndef GEN_CODE_USE_SOA |  | ||||||
| 		ct CodePOD Invalid = { ECode::Invalid, false, nullptr, nullptr, nullptr, { nullptr } }; |  | ||||||
|  |  | ||||||
| 		array_append( CodePool, Invalid ); |  | ||||||
|  |  | ||||||
| 		return pcast( Code, array_back( CodePool )); |  | ||||||
| #	else |  | ||||||
|  |  | ||||||
| 		array_append( CodePool::Type, ECode::Invalid ); |  | ||||||
| 		array_append( CodePool::Readonly, false ); |  | ||||||
| 		array_append( CodePool::Name, nullptr ); |  | ||||||
| 		array_append( CodePool::Comment, nullptr ); |  | ||||||
| 		array_append( CodePool::Data, { nullptr } ); |  | ||||||
|  |  | ||||||
| 		Code code { array_count( CodePool::Type) - 1 }; |  | ||||||
|  |  | ||||||
| 		return code; |  | ||||||
| #	endif |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #	pragma region AST | #	pragma region AST | ||||||
| 	bool AST::add( AST* other ) | 	bool AST::add( AST* other ) | ||||||
| 	{ | 	{ | ||||||
| @@ -356,7 +330,7 @@ namespace gen | |||||||
| 		array_init( StaticData::StringArenas, heap() ); | 		array_init( StaticData::StringArenas, heap() ); | ||||||
|  |  | ||||||
| 		arena string_arena; | 		arena string_arena; | ||||||
| 		arena_init_from_allocator( & string_arena, StaticData::Allocator_StringArena, StaticData::InitSize_StringArena ); | 		arena_init_from_allocator( & string_arena, StaticData::Allocator_StringArena, StaticData::SizePer_StringArena ); | ||||||
|  |  | ||||||
| 		str_tbl_init(  & StaticData::StringMap, StaticData::Allocator_StringTable ); | 		str_tbl_init(  & StaticData::StringMap, StaticData::Allocator_StringTable ); | ||||||
| 		type_tbl_init( & StaticData::TypeMap,   StaticData::Allocator_TypeTable ); | 		type_tbl_init( & StaticData::TypeMap,   StaticData::Allocator_TypeTable ); | ||||||
| @@ -427,7 +401,7 @@ namespace gen | |||||||
| 		if ( StringArenas->total_allocated + str_length > StringArenas->total_size ) | 		if ( StringArenas->total_allocated + str_length > StringArenas->total_size ) | ||||||
| 		{ | 		{ | ||||||
| 			arena new_arena; | 			arena new_arena; | ||||||
| 			arena_init_from_allocator( & new_arena, Allocator_StringArena, InitSize_StringArena ); | 			arena_init_from_allocator( & new_arena, Allocator_StringArena, SizePer_StringArena ); | ||||||
|  |  | ||||||
| 			array_append( StringArenas, new_arena ); | 			array_append( StringArenas, new_arena ); | ||||||
|  |  | ||||||
| @@ -438,7 +412,7 @@ namespace gen | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Will either make or retrive a code string. | 	// Will either make or retrive a code string. | ||||||
| 	string code_string( char const* cstr, s32 length ) | 	ro_string cached_string( char const* cstr, s32 length ) | ||||||
| 	{ | 	{ | ||||||
| 		s32 hash_length = length > kilobytes(1) ? kilobytes(1) : length; | 		s32 hash_length = length > kilobytes(1) ? kilobytes(1) : length; | ||||||
|  |  | ||||||
| @@ -451,11 +425,40 @@ namespace gen | |||||||
| 			return * result; | 			return * result; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		* result = string_make( get_string_allocator( length ), cstr ); | ||||||
|  |  | ||||||
| 		str_tbl_set( & StaticData::StringMap, key, * result ); | 		str_tbl_set( & StaticData::StringMap, key, * result ); | ||||||
|  |  | ||||||
| 		return * result; | 		return * result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 		Used internally to retireve a Code object form the CodePool. | ||||||
|  | 	*/ | ||||||
|  | 	Code make_code() | ||||||
|  | 	{ | ||||||
|  | 		using namespace StaticData; | ||||||
|  |  | ||||||
|  | #	ifndef GEN_CODE_USE_SOA | ||||||
|  | 		ct CodePOD Invalid = { nullptr, nullptr, nullptr, nullptr, ECode::Invalid, EOperator::Invalid, false, {0} }; | ||||||
|  |  | ||||||
|  | 		array_append( CodePool, Invalid ); | ||||||
|  |  | ||||||
|  | 		return pcast( Code, array_back( CodePool )); | ||||||
|  | #	else | ||||||
|  |  | ||||||
|  | 		array_append( CodePool::Type, ECode::Invalid ); | ||||||
|  | 		array_append( CodePool::Readonly, false ); | ||||||
|  | 		array_append( CodePool::Name, nullptr ); | ||||||
|  | 		array_append( CodePool::Comment, nullptr ); | ||||||
|  | 		array_append( CodePool::Data, { nullptr } ); | ||||||
|  |  | ||||||
|  | 		Code code { array_count( CodePool::Type) - 1 }; | ||||||
|  |  | ||||||
|  | 		return code; | ||||||
|  | #	endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	void set_init_reserve_code_pool( sw size ) | 	void set_init_reserve_code_pool( sw size ) | ||||||
| 	{ | 	{ | ||||||
| 		StaticData::InitSize_CodePool = size; | 		StaticData::InitSize_CodePool = size; | ||||||
| @@ -501,6 +504,12 @@ namespace gen | |||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace ECode; | ||||||
|  |  | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_class: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if ( name == nullptr ) | 		if ( name == nullptr ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_class: name is null"); | 			log_failure( "gen::def_class: name is null"); | ||||||
| @@ -509,35 +518,35 @@ namespace gen | |||||||
|  |  | ||||||
| 		if ( parent && parent->Type != Class || parent->Type != Struct ) | 		if ( parent && parent->Type != Class || parent->Type != Struct ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_class: parent provided is not type 'Class' or 'Struct' - Type: %s", parent->type_str() ); | 			log_failure( "gen::def_class: parent provided is not type 'Class' or 'Struct' - Type: %s", parent->debug_str() ); | ||||||
| 			return Code::Invalid; | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( specifiers && specifiers->Type != Specifiers ) | 		if ( specifiers && specifiers->Type != Specifiers ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_class: specifiers was not a 'Specifiers' type - Type: %s", specifiers->type_str() ); | 			log_failure( "gen::def_class: specifiers was not a 'Specifiers' type - Type: %s", specifiers->debug_str() ); | ||||||
| 			return Code::Invalid; | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		switch ( body->Type ) |  | ||||||
| 		{ |  | ||||||
| 			case Class_Body: |  | ||||||
| 			case Untyped: |  | ||||||
| 			break; |  | ||||||
|  |  | ||||||
| 			default: |  | ||||||
| 				log_failure("gen_def_class: body must be either of Function_Body or Untyped type."); |  | ||||||
| 				return Code::Invalid; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = code_string( name, length ); | 		result->Name = cached_string( name, length ); | ||||||
|  |  | ||||||
| 		array_init( result->Entries, StaticData::Allocator_CodePool ); | 		array_init( result->Entries, StaticData::Allocator_CodePool ); | ||||||
|  |  | ||||||
| 		if ( body ) | 		if ( body ) | ||||||
| 		{ | 		{ | ||||||
|  | 			switch ( body->Type ) | ||||||
|  | 			{ | ||||||
|  | 				case Class_Body: | ||||||
|  | 				case Untyped: | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 					log_failure("gen::def_class: body must be either of Class_Body or Untyped type - %s", body->debug_str()); | ||||||
|  | 					return Code::Invalid; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			result->Type = Class; | 			result->Type = Class; | ||||||
| 			result->add_entry( body ); | 			result->add_entry( body ); | ||||||
| 		} | 		} | ||||||
| @@ -558,21 +567,61 @@ namespace gen | |||||||
|  |  | ||||||
| 	Code def_enum( s32 length, char const* name, Code type, Code body ) | 	Code def_enum( s32 length, char const* name, Code type, Code body ) | ||||||
| 	{ | 	{ | ||||||
|  | 		using namespace ECode; | ||||||
|  |  | ||||||
| 		if ( length <= 0 ) | 		if ( length <= 0 ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen_def_enum: Invalid name length provided - %d", length ); | 			log_failure( "gen::def_enum: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( name == nullptr ) | 		if ( name == nullptr ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_class: name is null"); | 			log_failure( "gen::def_class: name is null" ); | ||||||
| 			return Code::Invalid; | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if ( type && type->Type != Typename ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_enum: enum underlying type provided was not of type Typename: %s", type->debug_str() ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Code | ||||||
|  | 		result       = make_code(); | ||||||
|  | 		result->Name = cached_string( name, length ); | ||||||
|  |  | ||||||
|  | 		if ( body ) | ||||||
|  | 		{ | ||||||
|  | 			switch ( body->Type ) | ||||||
|  | 			{ | ||||||
|  | 				case Enum_Body: | ||||||
|  | 				case Untyped: | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 					log_failure( "gen::def_enum: body must be of Enum_Body or Untyped type %s", body->debug_str()); | ||||||
|  | 					return Code::Invalid; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			result->Type = Enum; | ||||||
|  | 			result->add_entry( body ); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			result->Type = Enum_FwdDecl; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( type ) | ||||||
|  | 		{ | ||||||
|  | 			result->add_entry( type ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		result.lock(); | ||||||
|  | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_function( char const* name | 	Code def_function( s32 length, char const* name | ||||||
| 		, Code specifiers | 		, Code specifiers | ||||||
| 		, Code params | 		, Code params | ||||||
| 		, Code ret_type | 		, Code ret_type | ||||||
| @@ -581,52 +630,76 @@ namespace gen | |||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace ECode; | ||||||
|  |  | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( name == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: name is null" ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if ( specifiers && specifiers->Type != Specifiers ) | 		if ( specifiers && specifiers->Type != Specifiers ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_function: specifiers was not a `Specifiers` type" ); | 			log_failure( "gen::def_function: specifiers was not a `Specifiers` type %s", specifiers->debug_str() ); | ||||||
| 			return Code::Invalid; | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( params && params->Type != Parameters ) | 		if ( params && params->Type != Parameters ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_function: params was not a `Parameters` type" ); | 			log_failure( "gen::def_function: params was not a `Parameters` type %s", params->debug_str() ); | ||||||
| 			return Code::Invalid; | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( ret_type == nullptr || ret_type->Type != Typename ) | 		if ( ret_type == nullptr || ret_type->Type != Typename ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_function: ret_type was not a Typename" ); | 			log_failure( "gen::def_function: ret_type was not a Typename %s", ret_type->debug_str() ); | ||||||
| 			return Code::Invalid; | 			return Code::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		switch ( body->Type ) |  | ||||||
| 		{ |  | ||||||
| 			case Function_Body: |  | ||||||
| 			case Untyped: |  | ||||||
| 				break; |  | ||||||
|  |  | ||||||
| 			default: |  | ||||||
| 			{ |  | ||||||
| 				log_failure("gen::def_function: body must be either of Function_Body or Untyped type."); |  | ||||||
| 				return Code::Invalid; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		s32 name_length = zpl_strnlen( name, MaxNameLength ); |  | ||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = code_string( name, name_length ); | 		result->Name = cached_string( name, length ); | ||||||
| 		result->Type = Function; |  | ||||||
|  |  | ||||||
| 		array_init( result->Entries, StaticData::Allocator_CodePool ); | 		array_init( result->Entries, StaticData::Allocator_CodePool ); | ||||||
|  |  | ||||||
| 		result->add_entry( body ); | 		if ( body ) | ||||||
|  | 		{ | ||||||
|  | 			switch ( body->Type ) | ||||||
|  | 			{ | ||||||
|  | 				case Function_Body: | ||||||
|  | 				case Untyped: | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 				{ | ||||||
|  | 					log_failure("gen::def_function: body must be either of Function_Body or Untyped type. %s", body->debug_str()); | ||||||
|  | 					return Code::Invalid; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			result->Type = Function; | ||||||
|  | 			result->add_entry( body ); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			result->Type = Function_FwdDecl; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if ( specifiers ) | 		if ( specifiers ) | ||||||
| 			result->add_entry( specifiers ); | 			result->add_entry( specifiers ); | ||||||
|  |  | ||||||
| 		result->add_entry( ret_type ); | 		if ( ret_type ) | ||||||
|  | 		{ | ||||||
|  | 			result->add_entry( ret_type ); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			result->add_entry( type_ns(void) ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if ( params ) | 		if ( params ) | ||||||
| 			result->add_entry( params ); | 			result->add_entry( params ); | ||||||
| @@ -635,6 +708,45 @@ namespace gen | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	Code def_namespace( s32 length, char const* name, Code body ) | ||||||
|  | 	{ | ||||||
|  | 		using namespace ECode; | ||||||
|  |  | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_namespace: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( name == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_namespace: name is null" ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Code | ||||||
|  | 		result       = make_code(); | ||||||
|  | 		result->Type = Namespace; | ||||||
|  | 		result->Name = cached_string( name, length ); | ||||||
|  |  | ||||||
|  | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
|  | 		if ( body->Type != Namespace_Body || body->Type != Untyped ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body->debug_str()); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		result->add_entry( body ); | ||||||
|  |  | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Code def_operator( OperatorT Op, Code params, Code ret_type, Code specifiers, Code body ) | ||||||
|  | 	{ | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	Code def_function_body( s32 num, ... ) | 	Code def_function_body( s32 num, ... ) | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace ECode; | ||||||
| @@ -763,7 +875,7 @@ namespace gen | |||||||
| 		char const* name        = va_arg(va, char const*); | 		char const* name        = va_arg(va, char const*); | ||||||
| 		s32         name_length = zpl_strnlen(name, MaxNameLength); | 		s32         name_length = zpl_strnlen(name, MaxNameLength); | ||||||
|  |  | ||||||
| 		result->Name = code_string( name, name_length ); | 		result->Name = cached_string( name, name_length ); | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
| @@ -785,7 +897,7 @@ namespace gen | |||||||
| 			Code | 			Code | ||||||
| 			param       = make_code(); | 			param       = make_code(); | ||||||
| 			param->Type = Parameters; | 			param->Type = Parameters; | ||||||
| 			param->Name = code_string(name, name_length); | 			param->Name = cached_string(name, name_length); | ||||||
|  |  | ||||||
| 			array_init( param->Entries, StaticData::Allocator_CodePool ); | 			array_init( param->Entries, StaticData::Allocator_CodePool ); | ||||||
|  |  | ||||||
| @@ -806,27 +918,6 @@ namespace gen | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_namespace( char const* name, Code body ) |  | ||||||
| 	{ |  | ||||||
| 		using namespace ECode; |  | ||||||
|  |  | ||||||
| 		Code |  | ||||||
| 		result       = make_code(); |  | ||||||
| 		result->Type = Namespace; |  | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); |  | ||||||
|  |  | ||||||
| 		if ( body->Type != Namespace_Body || body->Type != Untyped ) |  | ||||||
| 		{ |  | ||||||
| 			log_failure("gen::def_namespace: body is not of namespace or untyped type"); |  | ||||||
| 			return Code::Invalid; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		result->add_entry( body ); |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Code def_namespace_body( s32 num, ... ) | 	Code def_namespace_body( s32 num, ... ) | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace ECode; | ||||||
| @@ -874,10 +965,19 @@ namespace gen | |||||||
| 		if ( num <= 0 ) | 		if ( num <= 0 ) | ||||||
| 			fatal("gen::make_specifier: num cannot be zero or less"); | 			fatal("gen::make_specifier: num cannot be zero or less"); | ||||||
|  |  | ||||||
|  | 		// This should be more than enough... | ||||||
|  | 		static u8 FixedSizedBuffer[kilobytes(1024)]; | ||||||
|  |  | ||||||
|  | 		static arena str_arena; | ||||||
|  | 		do_once_start | ||||||
|  | 			arena_init_from_memory( & str_arena, FixedSizedBuffer, kilobytes(1024) ); | ||||||
|  | 		do_once_end | ||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result          = make_code(); | 		result          = make_code(); | ||||||
| 		result->Type    = ECode::Specifiers; | 		result->Type    = ECode::Specifiers; | ||||||
| 		result->Content = string_make( g_allocator, "" ); |  | ||||||
|  | 		string crafted = string_make( arena_allocator( & str_arena ), "" ); | ||||||
|  |  | ||||||
| 		va_list va; | 		va_list va; | ||||||
| 		va_start(va, num); | 		va_start(va, num); | ||||||
| @@ -888,26 +988,42 @@ namespace gen | |||||||
| 			switch ( type ) | 			switch ( type ) | ||||||
| 			{ | 			{ | ||||||
| 				case ESpecifier::Alignas: | 				case ESpecifier::Alignas: | ||||||
| 					result->Content = string_append_fmt( result->Content, "%s(%d)", ESpecifier::to_str(type), va_arg(va, u32) ); | 					crafted = string_append_fmt( result->Content, "%s(%d)", ESpecifier::to_str(type), va_arg(va, u32) ); | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 				default: | 				default: | ||||||
| 					const char* str = ESpecifier::to_str(type); | 					const char* str = ESpecifier::to_str(type); | ||||||
|  |  | ||||||
| 					result->Content = string_append_fmt( result->Content, "%s", str ); | 					crafted = string_append_fmt( result->Content, "%s", str ); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		while ( --num, num ); | 		while ( --num, num ); | ||||||
| 		va_end(va); | 		va_end(va); | ||||||
|  |  | ||||||
|  | 		result->Content = cached_string( crafted, string_length( crafted ) ); | ||||||
|  |  | ||||||
|  | 		arena_free( & str_arena ); | ||||||
|  |  | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_struct( char const* name, Code body, Code parent, Code specifiers ) | 	Code def_struct( u32 length, char const* name, Code body, Code parent, Code specifiers ) | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace ECode; | ||||||
|  |  | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( name == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: name is null" ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if ( specifiers && specifiers->Type != Specifiers ) | 		if ( specifiers && specifiers->Type != Specifiers ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_struct: specifiers was not a `Specifiers` type" ); | 			log_failure( "gen::def_struct: specifiers was not a `Specifiers` type" ); | ||||||
| @@ -929,7 +1045,7 @@ namespace gen | |||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Type = Struct; | 		result->Type = Struct; | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = cached_string( name, length ); | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
| @@ -987,8 +1103,20 @@ namespace gen | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_variable( Code type, char const* name, Code value, Code specifiers ) | 	Code def_variable( Code type, u32 length, char const* name, Code value, Code specifiers ) | ||||||
| 	{ | 	{ | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( name == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: name is null" ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if ( specifiers && specifiers->Type != ECode::Specifiers ) | 		if ( specifiers && specifiers->Type != ECode::Specifiers ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::def_variable: specifiers was not a `Specifiers` type" ); | 			log_failure( "gen::def_variable: specifiers was not a `Specifiers` type" ); | ||||||
| @@ -1009,7 +1137,7 @@ namespace gen | |||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = cached_string( name, length ); | ||||||
| 		result->Type = ECode::Variable; | 		result->Type = ECode::Variable; | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
| @@ -1025,21 +1153,45 @@ namespace gen | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_type( char const* name,  Code specifiers ) | 	Code def_type( u32 length, char const* name,  Code specifiers ) | ||||||
| 	{ | 	{ | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( name == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: name is null" ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = cached_string( name, length ); | ||||||
| 		result->Type = ECode::Typename; | 		result->Type = ECode::Typename; | ||||||
|  |  | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_using( char const* name, Code type ) | 	Code def_using( u32 length, char const* name, Code type ) | ||||||
| 	{ | 	{ | ||||||
|  | 		if ( length <= 0 ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: Invalid name length provided - %d", length ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( name == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure( "gen::def_function: name is null" ); | ||||||
|  | 			return Code::Invalid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = cached_string( name, length ); | ||||||
| 		result->Type = ECode::Using; | 		result->Type = ECode::Using; | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
| @@ -1295,7 +1447,7 @@ namespace gen | |||||||
|  |  | ||||||
| 		Code | 		Code | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = cached_string( name, name_length ); | ||||||
| 		result->Type = ECode::Function; | 		result->Type = ECode::Function; | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|   | |||||||
							
								
								
									
										444
									
								
								project/gen.hpp
									
									
									
									
									
								
							
							
						
						
									
										444
									
								
								project/gen.hpp
									
									
									
									
									
								
							| @@ -18,6 +18,22 @@ | |||||||
| 	* Modern C++ (STL library) features | 	* Modern C++ (STL library) features | ||||||
| 	* Modern C++ RTTI                   : This is kinda covered with the last point, but just wanted to emphasize. | 	* Modern C++ RTTI                   : This is kinda covered with the last point, but just wanted to emphasize. | ||||||
|  |  | ||||||
|  | 	Exceptions brought in from "Modern C++": | ||||||
|  | 		Specifiers: | ||||||
|  | 		* consteval | ||||||
|  | 		* constinit | ||||||
|  | 		* explicit | ||||||
|  | 		* export | ||||||
|  | 		* noexcept | ||||||
|  | 		* import | ||||||
|  | 		* final | ||||||
|  | 		* module | ||||||
|  | 		* override | ||||||
|  | 		* && | ||||||
|  | 		* virtual | ||||||
|  |  | ||||||
|  | 	These features are in as they are just specifiers and aren't hard to implement seralization or validation. | ||||||
|  |  | ||||||
| 	The AST is managed by the library and provided the user via its interface prodedures. | 	The AST is managed by the library and provided the user via its interface prodedures. | ||||||
|  |  | ||||||
| 	Notes: | 	Notes: | ||||||
| @@ -60,6 +76,7 @@ | |||||||
| 	* def_class | 	* def_class | ||||||
| 	* def_enum | 	* def_enum | ||||||
| 	* def_enum_class | 	* def_enum_class | ||||||
|  | 	* def_friend | ||||||
| 	* def_function | 	* def_function | ||||||
| 	* def_namespace | 	* def_namespace | ||||||
| 	* def_operator | 	* def_operator | ||||||
| @@ -113,6 +130,7 @@ | |||||||
|  |  | ||||||
| 	* parse_class | 	* parse_class | ||||||
| 	* parse_enum | 	* parse_enum | ||||||
|  | 	* parse_friend | ||||||
| 	* parse_function | 	* parse_function | ||||||
| 	* parse_global_body | 	* parse_global_body | ||||||
| 	* parse_namespace | 	* parse_namespace | ||||||
| @@ -173,6 +191,8 @@ | |||||||
| #define GEN_DEFINE_DSL | #define GEN_DEFINE_DSL | ||||||
| #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| #define GEN_USE_FATAL | #define GEN_USE_FATAL | ||||||
|  | #define GEN_FEATURE_EDITOR | ||||||
|  | #define GEN_FEATURE_SCANNER | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef gen_time | #ifdef gen_time | ||||||
| @@ -192,37 +212,42 @@ namespace gen | |||||||
|  |  | ||||||
| 	namespace ECode | 	namespace ECode | ||||||
| 	{ | 	{ | ||||||
| 		enum Type : u8 | #		define Define_Types       \ | ||||||
| 		{ | 		Entry( Untyped )          \ | ||||||
| 			Invalid, | 		Entry( Access_Public )    \ | ||||||
| 			Untyped, | 		Entry( Access_Private )   \ | ||||||
| 			Access_Public, | 		Entry( Access_Protected ) \ | ||||||
| 			Access_Private, | 		Entry( Class )            \ | ||||||
| 			Access_Protected, | 		Entry( Class_FwdDecl )    \ | ||||||
| 			Class, | 		Entry( Class_Body )       \ | ||||||
| 			Class_FwdDecl, | 		Entry( Enum )             \ | ||||||
| 			Class_Body, | 		Entry( Enum_FwdDecl )     \ | ||||||
| 			Enum, | 		Entry( Enum_Body )        \ | ||||||
| 			Enum_FwdDecl, | 		Entry( Friend )           \ | ||||||
| 			Enum_Body, | 		Entry( Global_Body )      \ | ||||||
| 			Friend, | 		Entry( Namespace )        \ | ||||||
| 			Global_Body, | 		Entry( Namespace_Body )   \ | ||||||
| 			Namespace, | 		Entry( Parameters )       \ | ||||||
| 			Namespace_Body, | 		Entry( Function )         \ | ||||||
| 			Parameters, | 		Entry( Function_FwdDecl ) \ | ||||||
| 			Function, | 		Entry( Function_Body )    \ | ||||||
| 			Function_FwdDecl, | 		Entry( Specifiers )       \ | ||||||
| 			Function_Body, | 		Entry( Struct )           \ | ||||||
| 			Specifiers, | 		Entry( Struct_FwdDecl )   \ | ||||||
| 			Struct, | 		Entry( Struct_Body )      \ | ||||||
| 			Struct_FwdDecl, | 		Entry( Variable )         \ | ||||||
| 			Struct_Body, | 		Entry( Typedef )          \ | ||||||
| 			Variable, | 		Entry( Typename )         \ | ||||||
| 			Typedef, | 		Entry( Using ) | ||||||
| 			Typename, |  | ||||||
| 			Using, |  | ||||||
|  |  | ||||||
| 			Num_Types | 		enum Type : u32 | ||||||
|  | 		{ | ||||||
|  | #			define Entry( Type ) Type, | ||||||
|  | 			Define_Types | ||||||
|  | #			undef Entry | ||||||
|  |  | ||||||
|  | 			Num_Types, | ||||||
|  | 			Invalid | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		inline | 		inline | ||||||
| @@ -230,49 +255,72 @@ namespace gen | |||||||
| 		{ | 		{ | ||||||
| 			static | 			static | ||||||
| 			char const* lookup[Num_Types] = { | 			char const* lookup[Num_Types] = { | ||||||
| 				"Invalid", | #				define Entry( Type ) txt( Type ), | ||||||
| 				"Untyped", | 				Define_Types | ||||||
| 				"Access_Public", | #				undef Entry | ||||||
| 				"Access_Private", |  | ||||||
| 				"Access_Protected", |  | ||||||
| 				"Class", |  | ||||||
| 				"Class_FwdDecl", |  | ||||||
| 				"Class_Body", |  | ||||||
| 				"Enum", |  | ||||||
| 				"Enum_FwdDecl", |  | ||||||
| 				"Enum_Body", |  | ||||||
| 				"Function", |  | ||||||
| 				"Function_FwdDecl", |  | ||||||
| 				"Function_Body", |  | ||||||
| 				"Global_Body", |  | ||||||
| 				"Namespace", |  | ||||||
| 				"Namespace_Body", |  | ||||||
| 				"Parameters", |  | ||||||
| 				"Specifiers", |  | ||||||
| 				"Struct", |  | ||||||
| 				"Struct_Body", |  | ||||||
| 				"Variable", |  | ||||||
| 				"Typedef", |  | ||||||
| 				"Typename", |  | ||||||
| 				"Using", |  | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 			return lookup[ type ]; | 			return lookup[ type ]; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | #		undef Define_Types | ||||||
| 	} | 	} | ||||||
| 	using CodeT = ECode::Type; | 	using CodeT = ECode::Type; | ||||||
|  |  | ||||||
| 	namespace EOperator | 	namespace EOperator | ||||||
| 	{ | 	{ | ||||||
| 		enum Type : u8 | #		define Define_Operators          \ | ||||||
| 		{ | 			Entry( Assign, =  )          \ | ||||||
| 			Add, | 			Entry( Assign_Add, += )      \ | ||||||
| 			Subtract, | 			Entry( Assign_Subtract, -= ) \ | ||||||
| 			Multiply, | 			Entry( Assgin_Multiply, *= ) \ | ||||||
| 			Divide, | 			Entry( Assgin_Divide, /= )   \ | ||||||
| 			Modulo, | 			Entry( Assgin_Modulo, %= )   \ | ||||||
|  | 			Entry( Assgin_BAnd, &= )     \ | ||||||
|  | 			Entry( Assgin_BOr, &= )      \ | ||||||
|  | 			Entry( Assign_BXOr, ^= )     \ | ||||||
|  | 			Entry( Assign_LShift, <<= )  \ | ||||||
|  | 			Entry( Assign_RShift, >>= )  \ | ||||||
|  | 			Entry( Increment, ++ )       \ | ||||||
|  | 			Entry( Decrement, -- )       \ | ||||||
|  | 			Entry( Unary_Plus, + )       \ | ||||||
|  | 			Entry( Unary_Minus, - )      \ | ||||||
|  | 			Entry( Add, + )              \ | ||||||
|  | 			Entry( Subtract, - )         \ | ||||||
|  | 			Entry( Multiply, * )         \ | ||||||
|  | 			Entry( Divide, / )           \ | ||||||
|  | 			Entry( Modulo, % )           \ | ||||||
|  | 			Entry( BNot, ~ )             \ | ||||||
|  | 			Entry( BAnd, & )             \ | ||||||
|  | 			Entry( BOr, | )              \ | ||||||
|  | 			Entry( BXOr, ^ )             \ | ||||||
|  | 			Entry( LShift, << )          \ | ||||||
|  | 			Entry( RShift, >> )          \ | ||||||
|  | 			Entry( LNot, ! )             \ | ||||||
|  | 			Entry( LAnd, && )            \ | ||||||
|  | 			Entry( LOr, || )             \ | ||||||
|  | 			Entry( Equals, == )          \ | ||||||
|  | 			Entry( NotEquals, != )       \ | ||||||
|  | 			Entry( Lesser, < )           \ | ||||||
|  | 			Entry( Greater, > )          \ | ||||||
|  | 			Entry( LesserEqual, <= )     \ | ||||||
|  | 			Entry( GreaterEqual, >= )    \ | ||||||
|  | 			Entry( Subscript, [] )       \ | ||||||
|  | 			Entry( Indirection, * )      \ | ||||||
|  | 			Entry( AddressOf, & )        \ | ||||||
|  | 			Entry( MemberOfPointer, -> ) \ | ||||||
|  | 			Entry( PtrToMemOfPtr, ->* )  \ | ||||||
|  | 			Entry( FunctionCall, () ) | ||||||
|  |  | ||||||
| 			Num_Ops | 		enum Type : u32 | ||||||
|  | 		{ | ||||||
|  | #			define Entry( Type, Token ) Type, | ||||||
|  | 			Define_Operators | ||||||
|  | #			undef Entry | ||||||
|  | 			Comma, | ||||||
|  |  | ||||||
|  | 			Num_Ops, | ||||||
|  | 			Invalid | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		inline | 		inline | ||||||
| @@ -280,41 +328,74 @@ namespace gen | |||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			char const* lookup[ Num_Ops ] = { | 			char const* lookup[ Num_Ops ] = { | ||||||
| 				"+", | #				define Entry( Type, Token ) txt(Token), | ||||||
| 				"-", | 				Define_Operators | ||||||
| 				"*", | #				undef Entry | ||||||
| 				"/", | 				"," | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 			return lookup[ op ]; | 			return lookup[ op ]; | ||||||
| 		} | 		} | ||||||
|  | #		undef Define_Operators | ||||||
| 	} | 	} | ||||||
| 	using OperatorT = EOperator::Type; | 	using OperatorT = EOperator::Type; | ||||||
|  |  | ||||||
| 	namespace ESpecifier | 	namespace ESpecifier | ||||||
| 	{ | 	{ | ||||||
| 		enum Type : u8 | #		if defined(ZPL_SYSTEM_WINDOWS) | ||||||
|  | #			define API_Export_Code __declspec(dllexport) | ||||||
|  | #			define API_Import_Code __declspec(dllimport) | ||||||
|  | #		elif defined(ZPL_SYSTEM_MACOS) | ||||||
|  | #			define API_Export_Code __attribute__ ((visibility ("default"))) | ||||||
|  | #			define API_Import_Code __attribute__ ((visibility ("default"))) | ||||||
|  | #		endif | ||||||
|  |  | ||||||
|  | #		if defined(ZPL_MODULE_THREADING) | ||||||
|  | #			define Thread_Local_Code thread_local | ||||||
|  | #		else | ||||||
|  | #			define Thread_Local_Code "NOT DEFINED" | ||||||
|  | #		endif | ||||||
|  |  | ||||||
|  | 		// Entry( Explicit, explicit )           \ | ||||||
|  |  | ||||||
|  | 		#define Define_Specifiers                \ | ||||||
|  | 		Entry( API_Import, API_Export_Code )     \ | ||||||
|  | 		Entry( API_Export, API_Import_Code )     \ | ||||||
|  | 		Entry( Attribute, "You cannot stringize an attribute this way" ) \ | ||||||
|  | 		Entry( Alignas, alignas )                \ | ||||||
|  | 		Entry( Const, const )                    \ | ||||||
|  | 		Entry( C_Linkage, extern "C" )           \ | ||||||
|  | 		Entry( Consteval, consteval )            \ | ||||||
|  | 		Entry( Constexpr, constexpr )            \ | ||||||
|  | 		Entry( Constinit, constinit )            \ | ||||||
|  | 		Entry( Export, export )                  \ | ||||||
|  | 		Entry( External_Linkage, extern )        \ | ||||||
|  | 		Entry( Import, import )                  \ | ||||||
|  | 		Entry( Inline, inline )                  \ | ||||||
|  | 		Entry( Internal_Linkage, static )        \ | ||||||
|  | 		Entry( Final, final )                    \ | ||||||
|  | 		Entry( Local_Persist, static )           \ | ||||||
|  | 		Entry( Module, module )                  \ | ||||||
|  | 		Entry( Mutable, mutable )                \ | ||||||
|  | 		Entry( NoExcept, noexcept )              \ | ||||||
|  | 		Entry( Override, override )              \ | ||||||
|  | 		Entry( Pointer, * )                      \ | ||||||
|  | 		Entry( Reference, & )                    \ | ||||||
|  | 		Entry( Register, register )              \ | ||||||
|  | 		Entry( RValue, && )                      \ | ||||||
|  | 		Entry( Static_Member, static  )          \ | ||||||
|  | 		Entry( Thread_Local, Thread_Local_Code ) \ | ||||||
|  | 		Entry( Virtual, virtual )                \ | ||||||
|  | 		Entry( Volatile, volatile ) | ||||||
|  |  | ||||||
|  | 		enum Type : u32 | ||||||
| 		{ | 		{ | ||||||
| 			Attribute, | #			define Entry( Specifier, Code ) Specifier, | ||||||
| 			Alignas, | 			Define_Specifiers | ||||||
| 			Constexpr, | #			undef Entry | ||||||
| 			Const, |  | ||||||
| 			Inline, |  | ||||||
| 			Pointer, |  | ||||||
| 			Reference, |  | ||||||
| 			RValue, |  | ||||||
|  |  | ||||||
| 			C_Linkage, |  | ||||||
| 			API_Import, |  | ||||||
| 			API_Export, |  | ||||||
| 			External_Linkage, |  | ||||||
| 			Internal_Linkage, |  | ||||||
| 			Static_Member, |  | ||||||
| 			Local_Persist, |  | ||||||
| 			Thread_Local, |  | ||||||
|  |  | ||||||
| 			Invalid, |  | ||||||
| 			Num_Specifiers, | 			Num_Specifiers, | ||||||
|  | 			Invalid, | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		// Specifier to string | 		// Specifier to string | ||||||
| @@ -323,29 +404,9 @@ namespace gen | |||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			char const* lookup[ Num_Specifiers ] = { | 			char const* lookup[ Num_Specifiers ] = { | ||||||
| 				"alignas", | #				define Entry( Spec_, Code_ ) txt(Code_), | ||||||
| 				"constexpr", | 				Define_Specifiers | ||||||
| 				"const", | #				undef Entry | ||||||
| 				"inline", |  | ||||||
| 				"*", |  | ||||||
| 				"&", |  | ||||||
| 				"&&", |  | ||||||
|  |  | ||||||
| 				"extern \"C\"", |  | ||||||
|  |  | ||||||
| #			if defined(ZPL_SYSTEM_WINDOWS) |  | ||||||
| 				"__declspec(dllexport)", |  | ||||||
| 				"__declspec(dllimport)", |  | ||||||
| #			elif defined(ZPL_SYSTEM_MACOS) |  | ||||||
| 				"__attribute__ ((visibility (\"default\")))", |  | ||||||
| 				"__attribute__ ((visibility (\"default\")))", |  | ||||||
| #			endif |  | ||||||
|  |  | ||||||
| 				"extern", |  | ||||||
| 				"static", |  | ||||||
| 				"static", |  | ||||||
| 				"static", |  | ||||||
| 				"thread_local" |  | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 			return lookup[ specifier ]; | 			return lookup[ specifier ]; | ||||||
| @@ -394,11 +455,13 @@ namespace gen | |||||||
| 		forceinline | 		forceinline | ||||||
| 		void add_entry( AST* other ) | 		void add_entry( AST* other ) | ||||||
| 		{ | 		{ | ||||||
| 			array_append( Entries, other ); | 			Code to_add = other->Parent ? | ||||||
|  | 				other->duplicate() : other; | ||||||
|  |  | ||||||
| 			other->Parent = this; | 			array_append( Entries, to_add ); | ||||||
|  |  | ||||||
|  | 			to_add->Parent = this; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| 		AST* body() | 		AST* body() | ||||||
| 		{ | 		{ | ||||||
| @@ -408,6 +471,8 @@ namespace gen | |||||||
| 		forceinline | 		forceinline | ||||||
| 		bool check(); | 		bool check(); | ||||||
|  |  | ||||||
|  | 		Code duplicate(); | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| 		bool has_entries() const | 		bool has_entries() const | ||||||
| 		{ | 		{ | ||||||
| @@ -440,6 +505,27 @@ namespace gen | |||||||
| 			return Type != ECode::Invalid; | 			return Type != ECode::Invalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		char const* debug_str() const | ||||||
|  | 		{ | ||||||
|  | 			char const* fmt = txt( | ||||||
|  | 				\nCode Debug: | ||||||
|  | 				\nType    : %s | ||||||
|  | 				\nReadonly: %s | ||||||
|  | 				\nParent  : %s | ||||||
|  | 				\nName    : %s | ||||||
|  | 				\nComment : %s | ||||||
|  | 			); | ||||||
|  |  | ||||||
|  | 			bprintf( fmt | ||||||
|  | 			,	type_str() | ||||||
|  | 			,	Readonly ? "true"       : "false" | ||||||
|  | 			,	Parent   ? Parent->Name : "" | ||||||
|  | 			,	Name     ? Name         : "" | ||||||
|  | 			,	Comment  ? Comment      : "" | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| 		char const* type_str() const | 		char const* type_str() const | ||||||
| 		{ | 		{ | ||||||
| @@ -449,16 +535,18 @@ namespace gen | |||||||
| 		string to_string() const; | 		string to_string() const; | ||||||
| 	#pragma endregion Member Procedures | 	#pragma endregion Member Procedures | ||||||
|  |  | ||||||
| 	#define Using_Code_POD          \ | 	#define Using_Code_POD               \ | ||||||
| 		CodeT             Type;     \ | 		AST*              Parent;        \ | ||||||
| 		bool              Readonly; \ | 		ro_string         Name;          \ | ||||||
| 		AST*              Parent;   \ | 		ro_string         Comment;       \ | ||||||
| 		string            Name;     \ | 		union {                          \ | ||||||
| 		string            Comment;  \ | 			array(AST*)   Entries;       \ | ||||||
| 		union {                     \ | 			ro_string     Content;       \ | ||||||
| 			array(AST*)   Entries;  \ | 		};                               \ | ||||||
| 			string        Content;  \ | 		CodeT             Type;          \ | ||||||
| 		}; | 		OperatorT         Op;            \ | ||||||
|  | 		bool              Readonly;      \ | ||||||
|  | 		u8                _64_Align[23]; | ||||||
|  |  | ||||||
| 		Using_Code_POD; | 		Using_Code_POD; | ||||||
| 	}; | 	}; | ||||||
| @@ -468,6 +556,9 @@ namespace gen | |||||||
| 		Using_Code_POD; | 		Using_Code_POD; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | 	ct u32 sizeof_AST = sizeof(AST); | ||||||
|  | 	ct u32 sizeof_CODE = sizeof(CodePOD); | ||||||
|  |  | ||||||
| 	// Its intended for the AST to have equivalent size to its POD. | 	// Its intended for the AST to have equivalent size to its POD. | ||||||
| 	// All extra functionality within the AST namespace should just be syntatic sugar. | 	// All extra functionality within the AST namespace should just be syntatic sugar. | ||||||
| 	static_assert( sizeof(AST) == sizeof(CodePOD), "ERROR: AST IS NOT POD" ); | 	static_assert( sizeof(AST) == sizeof(CodePOD), "ERROR: AST IS NOT POD" ); | ||||||
| @@ -594,6 +685,8 @@ namespace gen | |||||||
| 	*/ | 	*/ | ||||||
| 	ZPL_TABLE_DECLARE( ZPL_EXTERN, StringTable, str_tbl_, string ); | 	ZPL_TABLE_DECLARE( ZPL_EXTERN, StringTable, str_tbl_, string ); | ||||||
|  |  | ||||||
|  | 	using ro_string = char const*; | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 		Type registy: Used to store Typename ASTs. Types are registered by their string literal value. | 		Type registy: Used to store Typename ASTs. Types are registered by their string literal value. | ||||||
|  |  | ||||||
| @@ -615,6 +708,19 @@ namespace gen | |||||||
| 	// And rather get rid of current code asts instead of growing the pool memory. | 	// And rather get rid of current code asts instead of growing the pool memory. | ||||||
| 	void clear_code_pool(); | 	void clear_code_pool(); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 		Used internally to retrive or make string allocations. | ||||||
|  | 		Strings are stored in a series of string arenas of fixed size (SizePer_StringArena) | ||||||
|  | 	*/ | ||||||
|  | 	ro_string cached_string( char const* cstr, s32 length ); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 		This provides a fresh Code AST struct. | ||||||
|  | 		The gen interface use this as their method from getting a new AST object from the CodePool. | ||||||
|  | 		Use this if you want to make your own API for formatting the supported Code Types. | ||||||
|  | 	*/ | ||||||
|  | 	Code make_code(); | ||||||
|  |  | ||||||
| 	// Set these before calling gen's init() procedure. | 	// Set these before calling gen's init() procedure. | ||||||
|  |  | ||||||
| 	void set_init_reserve_code_pool   ( sw size ); | 	void set_init_reserve_code_pool   ( sw size ); | ||||||
| @@ -632,6 +738,7 @@ namespace gen | |||||||
| 	Code def_class          ( s32 length, char const* name, Code parent = NoCode,                         Code specifiers = NoCode, Code body = NoCode ); | 	Code def_class          ( s32 length, char const* name, Code parent = NoCode,                         Code specifiers = NoCode, Code body = NoCode ); | ||||||
| 	Code def_enum           (             char const* name, Code type   = NoCode,                                                   Code body = NoCode); | 	Code def_enum           (             char const* name, Code type   = NoCode,                                                   Code body = NoCode); | ||||||
| 	Code def_enum           ( s32 length, char const* name, Code type   = NoCode,                                                   Code body = NoCode ); | 	Code def_enum           ( s32 length, char const* name, Code type   = NoCode,                                                   Code body = NoCode ); | ||||||
|  | 	Code def_friend         ( Code symbol ); | ||||||
| 	Code def_function       (             char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); | 	Code def_function       (             char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); | ||||||
| 	Code def_function       ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); | 	Code def_function       ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); | ||||||
| 	Code def_namespace      (             char const* name,                                                                         Code body ); | 	Code def_namespace      (             char const* name,                                                                         Code body ); | ||||||
| @@ -695,6 +802,7 @@ namespace gen | |||||||
| #	pragma region Parsing | #	pragma region Parsing | ||||||
| 	Code parse_class      ( s32 length, char const* class_def     ); | 	Code parse_class      ( s32 length, char const* class_def     ); | ||||||
| 	Code parse_enum       ( s32 length, char const* enum_def      ); | 	Code parse_enum       ( s32 length, char const* enum_def      ); | ||||||
|  | 	Code parse_friend     ( s32 length, char const* friend_def    ); | ||||||
| 	Code parse_function   ( s32 length, char const* fn_def        ); | 	Code parse_function   ( s32 length, char const* fn_def        ); | ||||||
| 	Code parse_global_body( s32 length, char const* body_def      ); | 	Code parse_global_body( s32 length, char const* body_def      ); | ||||||
| 	Code parse_namespace  ( s32 length, char const* namespace_def ); | 	Code parse_namespace  ( s32 length, char const* namespace_def ); | ||||||
| @@ -705,8 +813,9 @@ namespace gen | |||||||
| 	Code parse_typedef    ( s32 length, char const* typedef_def   ); | 	Code parse_typedef    ( s32 length, char const* typedef_def   ); | ||||||
| 	Code parse_using      ( s32 length, char const* using_def     ); | 	Code parse_using      ( s32 length, char const* using_def     ); | ||||||
|  |  | ||||||
| 	s32 parse_classes   ( s32 length, char const* class_defs,     Code* out_classes ); | 	s32 parse_classes   ( s32 length, char const* class_defs,     Code* out_class_codes ); | ||||||
| 	s32 parse_enums     ( s32 length, char const* enum_defs,      Code* out_enums ); | 	s32 parse_enums     ( s32 length, char const* enum_defs,      Code* out_enum_codes ); | ||||||
|  | 	s32 parse_friends   ( s32 length, char const* friend_defs,    Code* out_friend_codes ); | ||||||
| 	s32 parse_functions ( s32 length, char const* fn_defs,        Code* out_fn_codes ); | 	s32 parse_functions ( s32 length, char const* fn_defs,        Code* out_fn_codes ); | ||||||
| 	s32 parse_namespaces( s32 length, char const* namespace_defs, Code* out_namespaces_codes ); | 	s32 parse_namespaces( s32 length, char const* namespace_defs, Code* out_namespaces_codes ); | ||||||
| 	s32 parse_operators ( s32 length, char const* operator_defs,  Code* out_operator_codes ); | 	s32 parse_operators ( s32 length, char const* operator_defs,  Code* out_operator_codes ); | ||||||
| @@ -740,25 +849,10 @@ namespace gen | |||||||
|  |  | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	struct AddPolicy |  | ||||||
| 	{ |  | ||||||
| 		// Not sure yet |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	struct ReplacePolicy |  | ||||||
| 	{ |  | ||||||
|  |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	struct RemovePolicy |  | ||||||
| 	{ |  | ||||||
|  |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	struct SymbolInfo | 	struct SymbolInfo | ||||||
| 	{ | 	{ | ||||||
| 		char const* File; | 		ro_string File; | ||||||
| 		Code        Signature; | 		Code      Signature; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	struct Editor | 	struct Editor | ||||||
| @@ -770,27 +864,75 @@ namespace gen | |||||||
| 			Remove | 			Remove | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		struct RequestEntry | 		struct SymbolData | ||||||
| 		{ | 		{ | ||||||
| 			RequestType Type; |  | ||||||
| 			SymbolInfo  Info; |  | ||||||
| 			Policy      Policy; | 			Policy      Policy; | ||||||
|  | 			SymbolInfo  Info; | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|  | 		struct RequestEntry | ||||||
|  | 		{ | ||||||
|  | 			union { | ||||||
|  | 				SymbolData Symbol; | ||||||
|  | 				string     Specification; | ||||||
|  | 			}; | ||||||
|  | 			RequestType    Type; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
| 		zpl_file            File; | 		struct Receipt | ||||||
|  | 		{ | ||||||
|  | 			ro_string File; | ||||||
|  | 			Code      Found; | ||||||
|  | 			Code      Written; | ||||||
|  | 			bool      Result; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		static allocator Allocator; | ||||||
|  |  | ||||||
|  | 		static void set_allocator( allocator mem_allocator ); | ||||||
|  |  | ||||||
|  | 		array(zpl_file)     Files; | ||||||
| 		string              Buffer; | 		string              Buffer; | ||||||
| 		array(RequestEntry) Requestss ; | 		array(RequestEntry) Requests; | ||||||
|  |  | ||||||
| 		void add( SymbolInfo definition,  AddPolicy policy, Code to_inject ); | 		void add    ( SymbolInfo definition,  Policy policy, Code to_inject ); | ||||||
|  | 		void replace( SymbolInfo definition,  Policy policy, Code to_replace); | ||||||
| 		void replace( SymbolInfo definiton, ReplacePolicy policy, Code to_replace); | 		void remove ( SymbolInfo definition,  Policy policy, Code to_remove ); | ||||||
|  |  | ||||||
| 		void remove( SymbolInfo definition, RemovePolicy policy, Code to_remove ); |  | ||||||
|  |  | ||||||
| #	ifdef GEN_USE_REFACTOR_LIBRARY | #	ifdef GEN_USE_REFACTOR_LIBRARY | ||||||
| 		void refactor( char const* specification ); | 		void refactor( char const* specification ); | ||||||
| #	endif | #	endif | ||||||
|  |  | ||||||
|  | 		bool process_requests( array(Receipt) out_receipts ); | ||||||
|  | 	}; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef GEN_FEATURE_SCANNER | ||||||
|  | 	struct Scanner | ||||||
|  | 	{ | ||||||
|  | 		struct RequestEntry | ||||||
|  | 		{ | ||||||
|  | 			SymbolInfo Info; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		struct Receipt | ||||||
|  | 		{ | ||||||
|  | 			ro_string File; | ||||||
|  | 			Code      Defintion; | ||||||
|  | 			bool      Result; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		allocator Allocator; | ||||||
|  |  | ||||||
|  | 		static void set_allocator( allocator mem_allocator ); | ||||||
|  |  | ||||||
|  | 		array(zpl_file)     Files; | ||||||
|  | 		string              Buffer; | ||||||
|  | 		array(RequestEntry) Requests; | ||||||
|  |  | ||||||
|  | 		void add( SymbolInfo signature, Policy policy ); | ||||||
|  |  | ||||||
|  | 		bool process_requests( array(Receipt) out_receipts ); | ||||||
| 	}; | 	}; | ||||||
| #endif | #endif | ||||||
| #pragma endregion Gen Interface | #pragma endregion Gen Interface | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user