mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	WIP: Design is almost done, impl this weekend.
This commit is contained in:
		
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -7,6 +7,7 @@ | |||||||
| 		"utility": "cpp", | 		"utility": "cpp", | ||||||
| 		"xtr1common": "cpp", | 		"xtr1common": "cpp", | ||||||
| 		"xutility": "cpp", | 		"xutility": "cpp", | ||||||
| 		"initializer_list": "cpp" | 		"initializer_list": "cpp", | ||||||
|  | 		"table.h": "c" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
							
								
								
									
										44
									
								
								Readme.md
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								Readme.md
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| An attempt at simple staged metaprogramming for c/c++. | An attempt at simple staged metaprogramming for c/c++. | ||||||
|  |  | ||||||
| This library is intended for small-to midsize projects. | This library is intended for small-to midsized projects. | ||||||
|  |  | ||||||
| ### TOC | ### TOC | ||||||
|  |  | ||||||
| @@ -174,20 +174,27 @@ The construction will fail and return InvalidCode otherwise. | |||||||
|  |  | ||||||
| Interface : | Interface : | ||||||
|  |  | ||||||
| * def_forward_decl |  | ||||||
| * def_class | * def_class | ||||||
|  | * def_class_body | ||||||
|  | * def_class_fwd | ||||||
|  | * def_enum | ||||||
|  | * def_enum_class | ||||||
|  | * def_enum_body | ||||||
| * def_global_body | * def_global_body | ||||||
| * def_proc |  | ||||||
| * def_proc_body |  | ||||||
| * def_namespace | * def_namespace | ||||||
| * def_namespace_body | * def_namespace_body | ||||||
|  | * def_operator | ||||||
|  | * def_operator_fwd | ||||||
| * def_param | * def_param | ||||||
| * def_params | * def_params | ||||||
| * def_operator | * def_proc | ||||||
|  | * def_proc_body | ||||||
|  | * def_proc_fwd | ||||||
| * def_specifier | * def_specifier | ||||||
| * def_specifiers | * def_specifiers | ||||||
| * def_struct | * def_struct | ||||||
| * def_struct_body | * def_struct_body | ||||||
|  | * def_struct_fwd | ||||||
| * def_variable | * def_variable | ||||||
| * def_type | * def_type | ||||||
| * def_using | * def_using | ||||||
| @@ -206,19 +213,20 @@ Code ASTs may be explictly validated at anytime using Code's check() member func | |||||||
|  |  | ||||||
| Interface : | Interface : | ||||||
|  |  | ||||||
| * make_forward_decl |  | ||||||
| * make_class | * make_class | ||||||
|  | * make_enum | ||||||
|  | * make_enum_class | ||||||
|  | * make_fwd | ||||||
| * make_global_body | * make_global_body | ||||||
| * make_proc |  | ||||||
| * make_namespace | * make_namespace | ||||||
| * make_params |  | ||||||
| * make_operator | * make_operator | ||||||
|  | * make_params | ||||||
|  | * make_proc | ||||||
| * make_specifiers | * make_specifiers | ||||||
| * make_struct | * make_struct | ||||||
| * make_variable | * make_variable | ||||||
| * make_type | * make_type | ||||||
| * make_using | * make_using | ||||||
| * make_using_namespace |  | ||||||
|  |  | ||||||
| ### Parse construction | ### Parse construction | ||||||
|  |  | ||||||
| @@ -226,19 +234,29 @@ A string provided to the API is parsed for the intended language construct. | |||||||
|  |  | ||||||
| Interface : | Interface : | ||||||
|  |  | ||||||
| * parse_forward_decl |  | ||||||
| * parse_class | * parse_class | ||||||
| * parse_glboal_body | * parse_classes | ||||||
| * parse_proc | * parse_class_fwd | ||||||
|  | * parse_classes_fwd | ||||||
|  | * parse_enum | ||||||
|  | * parse_enums | ||||||
|  | * parse_global_body | ||||||
| * parse_namespace | * parse_namespace | ||||||
|  | * parse_namespaces | ||||||
| * parse_params | * parse_params | ||||||
|  | * parse_proc | ||||||
|  | * parse_procs | ||||||
| * parse_operator | * parse_operator | ||||||
|  | * parse_operators | ||||||
| * parse_specifiers | * parse_specifiers | ||||||
| * parse_struct | * parse_struct | ||||||
|  | * parse_strucs | ||||||
| * parse_variable | * parse_variable | ||||||
|  | * parse_variables | ||||||
| * parse_type | * parse_type | ||||||
|  | * parse_types | ||||||
| * parse_using | * parse_using | ||||||
| * parse_using | * parse_usings | ||||||
|  |  | ||||||
| The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. | The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. | ||||||
| This includes the assignmetn of variables; due to the library not yet supporting c/c++ expression parsing. | This includes the assignmetn of variables; due to the library not yet supporting c/c++ expression parsing. | ||||||
|   | |||||||
| @@ -124,5 +124,7 @@ sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_lis | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	tokmap_clear( & tok_map ); | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -73,17 +73,17 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define bit( Value_ )                      ( 1 << Value_ ) | #define bit( Value_ )                      ( 1 << Value_ ) | ||||||
| #define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ ) | #define bitfield_is_equal( Field_, Mask_ ) ( ( (Mask_) & (Field_) ) == (Mask_) ) | ||||||
| #define ct                                 constexpr | #define ct                                 constexpr | ||||||
| #define forceinline                        ZPL_ALWAYS_INLINE | #define forceinline                        ZPL_ALWAYS_INLINE | ||||||
| #define print_nl( _)                       zpl_printf("\n") | #define print_nl( _)                       zpl_printf("\n") | ||||||
| #define ccast( Type_, Value_ )             * const_cast< Type_* >( & Value_ ) | #define ccast( Type_, Value_ )             * const_cast< Type_* >( & (Value_) ) | ||||||
| #define scast( Type_, Value_ )			   static_cast< Type_ >( Value_ ) | #define scast( Type_, Value_ )			   static_cast< Type_ >( Value_ ) | ||||||
| #define rcast( Type_, Value_ )			   reinterpret_cast< Type_ >( Value_ ) | #define rcast( Type_, Value_ )			   reinterpret_cast< Type_ >( Value_ ) | ||||||
| #define pcast( Type_, Value_ )             ( * (Type_*)( & Value_ ) ) | #define pcast( Type_, Value_ )             ( * (Type_*)( & (Value_) ) ) | ||||||
| #define txt_impl( Value_ )                 #Value_ | #define txt_impl( Value_ )                 #Value_ | ||||||
| #define txt( Value_ )                      txt_impl( Value_ ) | #define txt( Value_ )                      txt_impl( Value_ ) | ||||||
| #define txt_with_length( Value_ )		   txt_impl( Value_ ), sizeof( txt_impl( Value_) ) | #define txt_with_length( Value_ )		   txt_impl( Value_ ), sizeof( txt_impl( Value_ ) ) | ||||||
|  |  | ||||||
| #define do_once()      \ | #define do_once()      \ | ||||||
| do                     \ | do                     \ | ||||||
| @@ -131,6 +131,8 @@ namespace Memory | |||||||
| 	void cleanup(); | 	void cleanup(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_list va ); | ||||||
|  |  | ||||||
| inline | inline | ||||||
| char const* token_fmt( char const* fmt, sw num_tokens, ... ) | char const* token_fmt( char const* fmt, sw num_tokens, ... ) | ||||||
| { | { | ||||||
| @@ -185,3 +187,4 @@ sw fatal(char const *fmt, ...) | |||||||
| 	return -1; | 	return -1; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										411
									
								
								project/gen.cpp
									
									
									
									
									
								
							
							
						
						
									
										411
									
								
								project/gen.cpp
									
									
									
									
									
								
							| @@ -4,40 +4,57 @@ | |||||||
| #ifdef gen_time | #ifdef gen_time | ||||||
| namespace gen | namespace gen | ||||||
| { | { | ||||||
|  | 	ZPL_TABLE_DEFINE( StringTable, str_tbl_,   string ); | ||||||
|  | 	ZPL_TABLE_DEFINE( TypeTable,   type_tbl_ , Code   ); | ||||||
|  |  | ||||||
| 	namespace StaticData | 	namespace StaticData | ||||||
| 	{ | 	{ | ||||||
| 		static array(CodePOD) CodePool = nullptr; | 		static array(CodePOD) CodePool = nullptr; | ||||||
|  |  | ||||||
|  | 		static array(arena) StringArenas =  nullptr; | ||||||
|  |  | ||||||
|  | 		static StringTable    StringMap; | ||||||
|  | 		static TypeTable      TypeMap; | ||||||
|  |  | ||||||
|  | 		static sw InitSize_CodePool       = megabytes(64); | ||||||
|  | 		static sw InitSize_StringArena    = megabytes(32); | ||||||
|  | 		static sw InitSize_StringTable    = megabytes(4); | ||||||
|  | 		static sw InitSize_TypeTable      = megabytes(4); | ||||||
|  |  | ||||||
|  | 		static allocator Allocator_CodePool    = zpl_heap(); | ||||||
|  | 		static allocator Allocator_StringArena = zpl_heap(); | ||||||
|  | 		static allocator Allocator_StringTable = zpl_heap(); | ||||||
|  | 		static allocator Allocator_TypeTable   = zpl_heap(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #pragma region CONSTANTS | #pragma region CONSTANTS | ||||||
| #	ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #	ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| 	const Code t_void; | 	Code t_void; | ||||||
|  |  | ||||||
| 	const Code t_bool; | 	Code t_bool; | ||||||
| 	const Code t_char; | 	Code t_char; | ||||||
| 	const Code t_char_wide; | 	Code t_char_wide; | ||||||
|  |  | ||||||
| 	const Code t_s8; | 	Code t_s8; | ||||||
| 	const Code t_s16; | 	Code t_s16; | ||||||
| 	const Code t_s32; | 	Code t_s32; | ||||||
| 	const Code t_s64; | 	Code t_s64; | ||||||
|  |  | ||||||
| 	const Code t_u8; | 	Code t_u8; | ||||||
| 	const Code t_u16; | 	Code t_u16; | ||||||
| 	const Code t_u32; | 	Code t_u32; | ||||||
| 	const Code t_u64; | 	Code t_u64; | ||||||
|  |  | ||||||
| 	const Code t_sw; | 	Code t_sw; | ||||||
| 	const Code t_uw; | 	Code t_uw; | ||||||
|  |  | ||||||
| 	const Code t_f32; | 	Code t_f32; | ||||||
| 	const Code t_f64; | 	Code t_f64; | ||||||
|  |  | ||||||
| 	const Code spec_constexpr; |  | ||||||
| 	const Code spec_inline; |  | ||||||
| #	endif | #	endif | ||||||
| #pragma endregion CONSTANTS |  | ||||||
|  |  | ||||||
|  | 	Code spec_constexpr; | ||||||
|  | 	Code spec_inline; | ||||||
|  | #pragma endregion CONSTANTS | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 		Used internally to retireve a Code object form the CodePool. | 		Used internally to retireve a Code object form the CodePool. | ||||||
| @@ -66,10 +83,9 @@ namespace gen | |||||||
| 		t_bool_write = ccast( Code, t_void ); | 		t_bool_write = ccast( Code, t_void ); | ||||||
| 		t_bool_write = def_type( txt(void) ); | 		t_bool_write = def_type( txt(void) ); | ||||||
|  |  | ||||||
| 	#	define def_constant_code_type( Type_ )        \ | 	#	define def_constant_code_type( Type_ ) \ | ||||||
| 		Code&                                         \ | 		Code&                                  \ | ||||||
| 		t_##Type_##_write = ccast( Code, t_##Type_ ); \ | 		t_##Type_ = def_type( txt(Type_) )      | ||||||
| 		t_##Type_##_write = def_type( txt(Type_) )    \ |  | ||||||
|  |  | ||||||
| 		def_constant_code_type( bool ); | 		def_constant_code_type( bool ); | ||||||
| 		def_constant_code_type( char ); | 		def_constant_code_type( char ); | ||||||
| @@ -109,80 +125,92 @@ namespace gen | |||||||
| 	#endif | 	#endif | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code decl_type( Code type, char const* name, Code specifiers ) | 	void clear_code_pool() | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		array_clear( StaticData::CodePool ); | ||||||
|  |  | ||||||
| 		if ( type->Type != Specifiers ) | 		sw size = array_capacity( StaticData::CodePool ); | ||||||
| 		{ |  | ||||||
| 			log_failure( "gen::decl_type: type is not a Typename"); |  | ||||||
| 			return InvalidCode; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( type->Type != Typename ) | 		zpl_memset( StaticData::CodePool, 0, size ); | ||||||
| 		{ |  | ||||||
| 			log_failure( "gen::decl_type: specifiers is not a 'Specfiers' type"); |  | ||||||
| 			return InvalidCode; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Code  |  | ||||||
| 		result       = make_code(); |  | ||||||
| 		result->Type = Decl_Type; |  | ||||||
| 		result->Name = string_make( g_allocator, name ); |  | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); |  | ||||||
| 		result->add( specifiers ); |  | ||||||
| 		result->add( type ); |  | ||||||
| 		result.lock(); |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code decl_proc( char const* name | 	allocator get_string_allocator( s32 str_length ) | ||||||
| 		, Code specifiers |  | ||||||
| 		, Code params |  | ||||||
| 		, Code ret_type |  | ||||||
| 	) |  | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace StaticData; | ||||||
|  |  | ||||||
| 		if ( specifiers->Type != Specifiers ) | 		if ( StringArenas->total_allocated + str_length > StringArenas->total_size ) | ||||||
| 		{ | 		{ | ||||||
| 			log_failure( "gen::decl_fn: specifiers was not a `Specifiers` type" ); | 			arena new_arena; | ||||||
| 			return InvalidCode; | 			arena_init_from_allocator( & new_arena, Allocator_StringArena, InitSize_StringArena ); | ||||||
|  |  | ||||||
|  | 			array_append( StringArenas, new_arena ); | ||||||
|  |  | ||||||
|  | 			return arena_allocator( StringArenas ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( params->Type != Parameters ) | 		return arena_allocator( StringArenas ); | ||||||
| 		{ |  | ||||||
| 			log_failure( "gen::decl_fn: params was not a `Parameters` type" ); |  | ||||||
| 			return InvalidCode; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( ret_type->Type != Typename ) |  | ||||||
| 		{ |  | ||||||
| 			log_failure( "gen::decl_fn: ret_type was not a Typename" ); |  | ||||||
| 			return InvalidCode; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Code |  | ||||||
| 		result       = make_code(); |  | ||||||
| 		result->Type = Decl_Function; |  | ||||||
| 		result->Name = string_make( g_allocator, name ); |  | ||||||
| 		 |  | ||||||
| 		array_init( result->Entries, g_allocator ); |  | ||||||
|  |  | ||||||
| 		if ( specifiers ) |  | ||||||
| 			result->add( specifiers ); |  | ||||||
|  |  | ||||||
| 		result->add( ret_type ); |  | ||||||
|  |  | ||||||
| 		if ( params ) |  | ||||||
| 			result->add( params ); |  | ||||||
|  |  | ||||||
| 		result.lock(); |  | ||||||
| 		return result; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Will either make or retrive a code string. | ||||||
|  | 	string code_string( char const* cstr, s32 length ) | ||||||
|  | 	{ | ||||||
|  | 		s32 hash_length = length > kilobytes(1) ? kilobytes(1) : length; | ||||||
|  |  | ||||||
|  | 		u32 key = crc32( cstr, hash_length ); | ||||||
|  |  | ||||||
|  | 		string* result = str_tbl_get( & StaticData::StringMap, key ); | ||||||
|  |  | ||||||
|  | 		if ( result ) | ||||||
|  | 		{ | ||||||
|  | 			return * result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		str_tbl_set( & StaticData::StringMap, key, * result ); | ||||||
|  |  | ||||||
|  | 		return * result; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_init_reserve_code_pool( sw size ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::InitSize_CodePool = size; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_init_reserve_string_arena( sw size ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::InitSize_StringArena = size; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_init_reserve_string_table( sw size ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::InitSize_StringTable = size; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_init_reserve_type_table( sw size ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::InitSize_TypeTable = size; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_allocator_code_pool( allocator pool_allocator ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::Allocator_CodePool = pool_allocator; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_allocator_string_arena( allocator string_allocator ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::Allocator_StringArena = string_allocator; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_allocator_string_table( allocator string_allocator ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::Allocator_StringArena = string_allocator; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void set_allocator_type_table( allocator type_reg_allocator ) | ||||||
|  | 	{ | ||||||
|  | 		StaticData::Allocator_TypeTable = type_reg_allocator; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #	pragma region Upfront Constructors | ||||||
| 	Code def_params( s32 num, ... ) | 	Code def_params( s32 num, ... ) | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		using namespace ECode; | ||||||
| @@ -271,7 +299,7 @@ namespace gen | |||||||
|  |  | ||||||
| 		switch ( body->Type ) | 		switch ( body->Type ) | ||||||
| 		{ | 		{ | ||||||
| 			case Function_Body: | 			case Proc_Body: | ||||||
| 			case Untyped: | 			case Untyped: | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| @@ -285,7 +313,7 @@ namespace gen | |||||||
| 		Code  | 		Code  | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = string_make( g_allocator, name ); | ||||||
| 		result->Type = Function; | 		result->Type = Proc; | ||||||
| 		 | 		 | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
| @@ -331,8 +359,7 @@ namespace gen | |||||||
|  |  | ||||||
| 			switch ( entry->Type ) | 			switch ( entry->Type ) | ||||||
| 			{ | 			{ | ||||||
| 				case Decl_Function: | 				case Proc_Forward: | ||||||
| 				case Decl_Type: |  | ||||||
| 				case Namespace: | 				case Namespace: | ||||||
| 				case Namespace_Body: | 				case Namespace_Body: | ||||||
| 				case Parameters: | 				case Parameters: | ||||||
| @@ -387,8 +414,7 @@ namespace gen | |||||||
|  |  | ||||||
| 			switch ( entry->Type ) | 			switch ( entry->Type ) | ||||||
| 			{ | 			{ | ||||||
| 				case Decl_Function: | 				case Proc_Forward: | ||||||
| 				case Decl_Type: |  | ||||||
| 				case Namespace: | 				case Namespace: | ||||||
| 				case Namespace_Body: | 				case Namespace_Body: | ||||||
| 				case Parameters: | 				case Parameters: | ||||||
| @@ -630,7 +656,7 @@ namespace gen | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code def_type( char const* name ) | 	Code def_type( char const* name,  Code specifiers ) | ||||||
| 	{ | 	{ | ||||||
| 		Code  | 		Code  | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| @@ -654,57 +680,9 @@ namespace gen | |||||||
|  |  | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  | #	pragma endregion Upfront Constructors | ||||||
|  |  | ||||||
| 	Code untyped_str(char const* fmt) | #	pragma region Incremetnal Constructors | ||||||
| 	{ |  | ||||||
| 		Code  |  | ||||||
| 		result       = make_code(); |  | ||||||
| 		result->Name = string_make( g_allocator, fmt ); |  | ||||||
| 		result->Type = ECode::Untyped; |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Code untyped_fmt(char const* fmt, ...) |  | ||||||
| 	{ |  | ||||||
| 		local_persist thread_local  |  | ||||||
| 		char buf[ZPL_PRINTF_MAXLEN] = { 0 }; |  | ||||||
|  |  | ||||||
| 		va_list va; |  | ||||||
| 		va_start(va, fmt); |  | ||||||
| 		zpl_snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va); |  | ||||||
| 		va_end(va); |  | ||||||
|           |  | ||||||
| 		Code  |  | ||||||
| 		result          = make_code(); |  | ||||||
| 		result->Name    = string_make( g_allocator, fmt ); |  | ||||||
| 		result->Type    = ECode::Untyped; |  | ||||||
| 		result->Content = string_make( g_allocator, buf ); |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... ) |  | ||||||
| 	{ |  | ||||||
| 		local_persist thread_local  |  | ||||||
| 		char buf[ZPL_PRINTF_MAXLEN] = { 0 }; |  | ||||||
|  |  | ||||||
| 		va_list va; |  | ||||||
| 		va_start(va, fmt); |  | ||||||
| 		token_fmt_va(buf, ZPL_PRINTF_MAXLEN, fmt, num_tokens, va); |  | ||||||
| 		va_end(va); |  | ||||||
|  |  | ||||||
| 		Code |  | ||||||
| 		result           = make_code(); |  | ||||||
| 		result->Name     = string_make( g_allocator, fmt ); |  | ||||||
| 		result->Type     = ECode::Untyped; |  | ||||||
| 		result->Content  = string_make( g_allocator, buf ); |  | ||||||
|  |  | ||||||
| 		result.lock(); |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Code make_proc( char const* name | 	Code make_proc( char const* name | ||||||
| 		, Code specifiers | 		, Code specifiers | ||||||
| 		, Code params | 		, Code params | ||||||
| @@ -734,7 +712,7 @@ namespace gen | |||||||
| 		Code  | 		Code  | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = string_make( g_allocator, name ); | ||||||
| 		result->Type = Function; | 		result->Type = Proc; | ||||||
| 		 | 		 | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
| @@ -788,12 +766,12 @@ namespace gen | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code make_unit( char const* name ) | 	Code make_global_body( char const* name = "", s32 num = 0, ... ) | ||||||
| 	{ | 	{ | ||||||
| 		Code | 		Code | ||||||
| 		result = make_code(); | 		result = make_code(); | ||||||
| 		result->Type = ECode::Unit; | 		result->Type = ECode::Global_Body; | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = string_make( g_allocator, ""); | ||||||
|  |  | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
| @@ -802,7 +780,9 @@ namespace gen | |||||||
|  |  | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  | #	pragma endregion Incremetnal Constructions | ||||||
|  |  | ||||||
|  | #	pragma region Parsing Constructors | ||||||
| 	Code parse_proc( char const* def, s32 length ) | 	Code parse_proc( char const* def, s32 length ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( def == nullptr ) | 		if ( def == nullptr ) | ||||||
| @@ -856,7 +836,7 @@ namespace gen | |||||||
| 			while ( left && char_is_space( * scanner ) ) \ | 			while ( left && char_is_space( * scanner ) ) \ | ||||||
| 			{                                            \ | 			{                                            \ | ||||||
| 				left--;                                  \ | 				left--;                                  \ | ||||||
| 				scanner++ ; | 				scanner++ ;                              \ | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			#define Get | 			#define Get | ||||||
| @@ -947,7 +927,7 @@ namespace gen | |||||||
| 		Code  | 		Code  | ||||||
| 		result       = make_code(); | 		result       = make_code(); | ||||||
| 		result->Name = string_make( g_allocator, name ); | 		result->Name = string_make( g_allocator, name ); | ||||||
| 		result->Type = ECode::Function; | 		result->Type = ECode::Proc; | ||||||
| 		 | 		 | ||||||
| 		array_init( result->Entries, g_allocator ); | 		array_init( result->Entries, g_allocator ); | ||||||
|  |  | ||||||
| @@ -985,8 +965,124 @@ namespace gen | |||||||
|  |  | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  | #	pragma endregion Parsing Constructors | ||||||
|  |  | ||||||
|  | #	pragma region Untyped Constructors | ||||||
|  | 	Code untyped_str(char const* fmt) | ||||||
|  | 	{ | ||||||
|  | 		Code  | ||||||
|  | 		result          = make_code(); | ||||||
|  | 		result->Name    = string_make( g_allocator, fmt ); | ||||||
|  | 		result->Type    = ECode::Untyped; | ||||||
|  | 		result->Content = result->Name; | ||||||
|  |  | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Code untyped_fmt(char const* fmt, ...) | ||||||
|  | 	{ | ||||||
|  | 		local_persist thread_local  | ||||||
|  | 		char buf[ZPL_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		zpl_snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va); | ||||||
|  | 		va_end(va); | ||||||
|  |           | ||||||
|  | 		Code  | ||||||
|  | 		result          = make_code(); | ||||||
|  | 		result->Name    = string_make( g_allocator, fmt ); | ||||||
|  | 		result->Type    = ECode::Untyped; | ||||||
|  | 		result->Content = string_make( g_allocator, buf ); | ||||||
|  |  | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... ) | ||||||
|  | 	{ | ||||||
|  | 		local_persist thread_local  | ||||||
|  | 		char buf[ZPL_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		token_fmt_va(buf, ZPL_PRINTF_MAXLEN, fmt, num_tokens, va); | ||||||
|  | 		va_end(va); | ||||||
|  |  | ||||||
|  | 		Code | ||||||
|  | 		result           = make_code(); | ||||||
|  | 		result->Name     = string_make( g_allocator, fmt ); | ||||||
|  | 		result->Type     = ECode::Untyped; | ||||||
|  | 		result->Content  = string_make( g_allocator, buf ); | ||||||
|  |  | ||||||
|  | 		result.lock(); | ||||||
|  |  | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  | #	pragma endregion Untyped Constructors | ||||||
|  |  | ||||||
|  | #	pragma region AST | ||||||
|  | 	bool AST::add( AST* other ) | ||||||
|  | 	{ | ||||||
|  | 		switch ( Type ) | ||||||
|  | 		{ | ||||||
|  | 			using namespace ECode; | ||||||
|  |  | ||||||
|  | 			case Untyped: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Global_Body: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Proc: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Proc_Body: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Proc_Forward: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Namespace: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Namespace_Body: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Parameters: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Specifiers: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Struct: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Struct_Body: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Variable: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Typedef: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Typename: | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case Using: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		array_append( Entries, other ); | ||||||
|  |  | ||||||
|  | 		other->Parent = this; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bool AST::check() | ||||||
|  | 	{ | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	string AST::to_string() const | 	string AST::to_string() const | ||||||
| 	{ | 	{ | ||||||
| @@ -1007,7 +1103,7 @@ namespace gen | |||||||
| 				result = string_append_length( result, Content, string_length(Content) ); | 				result = string_append_length( result, Content, string_length(Content) ); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 			case Decl_Function: | 			case Proc_Forward: | ||||||
| 			{ | 			{ | ||||||
| 				u32 index = 0; | 				u32 index = 0; | ||||||
| 				u32 left  = array_count( Entries ); | 				u32 left  = array_count( Entries ); | ||||||
| @@ -1040,14 +1136,7 @@ namespace gen | |||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 			case Decl_Type: | 			case Proc: | ||||||
| 				if ( Entries[0]->Type == Specifiers ) |  | ||||||
| 					result = string_append_fmt( result, "%s\n", Entries[0]->to_string()); |  | ||||||
|  |  | ||||||
| 				result = string_append_fmt( result, "%s %s;\n", Entries[1]->to_string(), Name ); |  | ||||||
| 			break; |  | ||||||
|  |  | ||||||
| 			case Function: |  | ||||||
| 			{ | 			{ | ||||||
| 				u32 index = 0; | 				u32 index = 0; | ||||||
| 				u32 left  = array_count( Entries ); | 				u32 left  = array_count( Entries ); | ||||||
| @@ -1080,7 +1169,7 @@ namespace gen | |||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 			case Function_Body: | 			case Proc_Body: | ||||||
| 				fatal("NOT SUPPORTED YET"); | 				fatal("NOT SUPPORTED YET"); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| @@ -1138,9 +1227,10 @@ namespace gen | |||||||
|  |  | ||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  | #	pragma endregion AST | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #	pragma region Builder | ||||||
| 	void Builder::print( Code code ) | 	void Builder::print( Code code ) | ||||||
| 	{ | 	{ | ||||||
| 		Buffer = string_append_fmt( Buffer, "%s\n\n", code->to_string() ); | 		Buffer = string_append_fmt( Buffer, "%s\n\n", code->to_string() ); | ||||||
| @@ -1171,5 +1261,6 @@ namespace gen | |||||||
| 		// file_seek( & File, 0 ); | 		// file_seek( & File, 0 ); | ||||||
| 		file_close( & File ); | 		file_close( & File ); | ||||||
| 	} | 	} | ||||||
|  | #	pragma endregion Builder | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										574
									
								
								project/gen.hpp
									
									
									
									
									
								
							
							
						
						
									
										574
									
								
								project/gen.hpp
									
									
									
									
									
								
							| @@ -13,17 +13,14 @@ | |||||||
| 	* Expression validation             : Execution expressions are defined using the untyped string API.  | 	* Expression validation             : Execution expressions are defined using the untyped string API.  | ||||||
| 	                                      There is no parse API for validating expression (possibly will add in the future) | 	                                      There is no parse API for validating expression (possibly will add in the future) | ||||||
| 	* Complete file parser DSL          : This isn't like the unreal header tool.  | 	* Complete file parser DSL          : This isn't like the unreal header tool.  | ||||||
| 	                                      Code injection to file or based off a file contents is not supported by the api.  | 	                                      Code injection to file or based off a file contents is not supported by the api. However nothing is stopping you using the library for that purpose. | ||||||
| 										  However nothing is stopping you using the library for that purpose. |  | ||||||
| 	* Modern c++ (STL library) features | 	* Modern c++ (STL library) features | ||||||
|  |  | ||||||
| 	As mentioned in [Usage](#Usage), the user is provided Code objects by calling the interface procedures to generate them or find existing matches. |  | ||||||
|  |  | ||||||
| 	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: | ||||||
|  |  | ||||||
| 	* The allocator definitions used are exposed to the user incase they want to dictate memory usage* | 	* The allocator definitions used are exposed to the user incase they want to dictate memory usage | ||||||
| 	* ASTs are wrapped for the user in a Code struct which essentially a warpper for a AST* type.   | 	* ASTs are wrapped for the user in a Code struct which essentially a warpper for a AST* type.   | ||||||
| 	* Both AST and Code have member symbols but their data layout is enforced to be POD types. | 	* Both AST and Code have member symbols but their data layout is enforced to be POD types. | ||||||
|  |  | ||||||
| @@ -58,22 +55,30 @@ | |||||||
|  |  | ||||||
| 	Interface : | 	Interface : | ||||||
|  |  | ||||||
| 	* def_forward_decl |  | ||||||
| 	* def_class | 	* def_class | ||||||
|  | 	* def_class_body | ||||||
|  | 	* def_class_fwd | ||||||
|  | 	* def_enum | ||||||
|  | 	* def_enum_class | ||||||
|  | 	* def_enum_body | ||||||
| 	* def_global_body | 	* def_global_body | ||||||
| 	* def_proc |  | ||||||
| 	* def_proc_body |  | ||||||
| 	* def_namespace | 	* def_namespace | ||||||
| 	* def_namespace_body | 	* def_namespace_body | ||||||
|  | 	* def_operator | ||||||
|  | 	* def_operator_fwd | ||||||
| 	* def_param | 	* def_param | ||||||
| 	* def_params | 	* def_params | ||||||
| 	* def_operator | 	* def_proc | ||||||
|  | 	* def_proc_body | ||||||
|  | 	* def_proc_fwd | ||||||
| 	* def_specifier | 	* def_specifier | ||||||
| 	* def_specifiers | 	* def_specifiers | ||||||
| 	* def_struct | 	* def_struct | ||||||
| 	* def_struct_body | 	* def_struct_body | ||||||
|  | 	* def_struct_fwd | ||||||
| 	* def_variable | 	* def_variable | ||||||
| 	* def_type | 	* def_type | ||||||
|  | 	* def_typedef | ||||||
| 	* def_using | 	* def_using | ||||||
| 	* def_using_namespace | 	* def_using_namespace | ||||||
|  |  | ||||||
| @@ -82,27 +87,27 @@ | |||||||
| 	A Code ast is provided but only completed upfront if all components are provided. | 	A Code ast is provided but only completed upfront if all components are provided. | ||||||
| 	Components are then added using the AST API for adding ASTs: | 	Components are then added using the AST API for adding ASTs: | ||||||
|  |  | ||||||
| 	* code.add( AST* )         // Adds AST with validation. | 	* code.add( AST* )                     // Adds AST with validation. | ||||||
| 	* code.add_entry( AST* )   // Adds AST entry without validation. | 	* code.add_entry( AST* )               // Adds AST entry without validation. | ||||||
| 	* code.add_content( AST* ) // Adds AST string content without validation. |  | ||||||
|  |  | ||||||
| 	Code ASTs may be explictly validated at anytime using Code's check() member function. | 	Code ASTs may be explictly validated at anytime using Code's check() member function. | ||||||
|  |  | ||||||
| 	Interface : | 	Interface : | ||||||
|  |  | ||||||
| 	* make_forward_decl |  | ||||||
| 	* make_class | 	* make_class | ||||||
|  | 	* make_enum | ||||||
|  | 	* make_enum_class | ||||||
| 	* make_global_body | 	* make_global_body | ||||||
| 	* make_proc |  | ||||||
| 	* make_namespace | 	* make_namespace | ||||||
| 	* make_params |  | ||||||
| 	* make_operator | 	* make_operator | ||||||
|  | 	* make_params | ||||||
|  | 	* make_proc | ||||||
| 	* make_specifiers | 	* make_specifiers | ||||||
| 	* make_struct | 	* make_struct | ||||||
| 	* make_variable | 	* make_variable | ||||||
| 	* make_type | 	* make_type | ||||||
|  | 	* make_typedef | ||||||
| 	* make_using | 	* make_using | ||||||
| 	* make_using_namespace |  | ||||||
|  |  | ||||||
| 	### Parse construction | 	### Parse construction | ||||||
|  |  | ||||||
| @@ -110,23 +115,33 @@ | |||||||
|  |  | ||||||
| 	Interface : | 	Interface : | ||||||
|  |  | ||||||
| 	* parse_forward_decl |  | ||||||
| 	* parse_class | 	* parse_class | ||||||
| 	* parse_glboal_body | 	* parse_classes | ||||||
| 	* parse_proc | 	* parse_enum | ||||||
|  | 	* parse_enums | ||||||
|  | 	* parse_global_body | ||||||
| 	* parse_namespace | 	* parse_namespace | ||||||
| 	* parse_params | 	* parse_namespaces | ||||||
| 	* parse_operator | 	* parse_operator | ||||||
| 	* parse_specifiers | 	* parse_operators | ||||||
|  | 	* parse_proc | ||||||
|  | 	* parse_procs | ||||||
| 	* parse_struct | 	* parse_struct | ||||||
|  | 	* parse_strucs | ||||||
| 	* parse_variable | 	* parse_variable | ||||||
|  | 	* parse_variables | ||||||
| 	* parse_type | 	* parse_type | ||||||
|  | 	* parse_typedef | ||||||
|  | 	* parse_typedefs | ||||||
| 	* parse_using | 	* parse_using | ||||||
| 	* parse_using | 	* parse_usings | ||||||
|  |  | ||||||
| 	The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. | 	The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. | ||||||
| 	This includes the assignmetn of variables; due to the library not yet supporting c/c++ expression parsing. | 	This includes the assignmetn of variables; due to the library not yet supporting c/c++ expression parsing. | ||||||
|  |  | ||||||
|  | 	The plural variants provide an array of codes, its up to the user to add them to a body AST  | ||||||
|  | 	(they are not auto-added to a body) | ||||||
|  |  | ||||||
| 	### Untyped constructions | 	### Untyped constructions | ||||||
|  |  | ||||||
| 	Code ASTs are constructed using unvalidated strings. | 	Code ASTs are constructed using unvalidated strings. | ||||||
| @@ -158,7 +173,7 @@ | |||||||
| // #define GEN_DEFINE_DSL | // #define GEN_DEFINE_DSL | ||||||
| #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| // #define GEN_BAN_CPP_TEMPLATES | // #define GEN_BAN_CPP_TEMPLATES | ||||||
| // #define GEN_USE_FATAL | #define GEN_USE_FATAL | ||||||
|  |  | ||||||
| #ifdef gen_time | #ifdef gen_time | ||||||
| namespace gen | namespace gen | ||||||
| @@ -179,41 +194,52 @@ namespace gen | |||||||
| 	{ | 	{ | ||||||
| 		enum Type : u8 | 		enum Type : u8 | ||||||
| 		{ | 		{ | ||||||
| 			Invalid,        // Used only with improperly created Code nodes | 			Invalid,         | ||||||
| 			Untyped,        // User provided raw string | 			Untyped,         | ||||||
| 			Decl_Function,  // <specifier> <type> <name> ( <params> ) | 			Access_Public, | ||||||
| 			Decl_Type,      // <type> <name>; | 			Access_Private, | ||||||
| 			Function,       // <type> <name>( <parameters> ) | 			Access_Protected, | ||||||
| 			Function_Body,  // { <body> } | 			Class,           | ||||||
| 			Namespace,      // Define a namespace | 			Enum,            | ||||||
| 			Namespace_Body, // { <body> }  | 			Enum_Body,       | ||||||
| 			Parameters,     // <type> <param> ... | 			Global_Body,     | ||||||
| 			Specifiers,     // Used with functions, structs, variables | 			Namespace,       | ||||||
| 			Struct,         // struct <specifier> <name> <parent> | 			Namespace_Body,  | ||||||
| 			Struct_Body,    // {<body> } | 			Parameters,      | ||||||
| 			Variable,       // <type> <name> | 			Proc,            | ||||||
| 			Typedef,        // typedef <type> <alias> | 			Proc_Body,       | ||||||
| 			Typename,       // Typename, used with other types | 			Proc_Forward,    | ||||||
| 			Using,          // using <name> = <type> | 			Specifiers,      | ||||||
| 			Unit,           // Represents a file. | 			Struct,          | ||||||
|  | 			Struct_Body,     | ||||||
|  | 			Variable,        | ||||||
|  | 			Typedef,         | ||||||
|  | 			Typename,        | ||||||
|  | 			Using,           | ||||||
|  |  | ||||||
| 			Num_Types | 			Num_Types | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		inline | 		local_persist | ||||||
| 		char const* str( Type type ) | 		char const* str( Type type ) | ||||||
| 		{ | 		{ | ||||||
| 			static  | 			static  | ||||||
| 			char const* lookup[Num_Types] = { | 			char const* lookup[Num_Types] = { | ||||||
| 				"Invalid", | 				"Invalid", | ||||||
| 				"Untyped", | 				"Untyped", | ||||||
| 				"Decl_Function", | 				"Access_Public", | ||||||
| 				"Decl_Type", | 				"Access_Private", | ||||||
| 				"Function", | 				"Access_Protected", | ||||||
| 				"Function_Body", | 				"Class", | ||||||
|  | 				"Enum", | ||||||
|  | 				"Enum_Body", | ||||||
|  | 				"Global_Body", | ||||||
| 				"Namespace", | 				"Namespace", | ||||||
| 				"Namespace_Body", | 				"Namespace_Body", | ||||||
| 				"Parameters", | 				"Parameters", | ||||||
|  | 				"Proc", | ||||||
|  | 				"Proc_Body", | ||||||
|  | 				"Proc_Forward", | ||||||
| 				"Specifiers", | 				"Specifiers", | ||||||
| 				"Struct", | 				"Struct", | ||||||
| 				"Struct_Body", | 				"Struct_Body", | ||||||
| @@ -221,7 +247,6 @@ namespace gen | |||||||
| 				"Typedef", | 				"Typedef", | ||||||
| 				"Typename", | 				"Typename", | ||||||
| 				"Using", | 				"Using", | ||||||
| 				"Unit", |  | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 			return lookup[ type ]; | 			return lookup[ type ]; | ||||||
| @@ -245,7 +270,7 @@ namespace gen | |||||||
| 		inline  | 		inline  | ||||||
| 		char const* str( Type op ) | 		char const* str( Type op ) | ||||||
| 		{ | 		{ | ||||||
| 			static  | 			local_persist | ||||||
| 			char const* lookup[ Num_Ops ] = { | 			char const* lookup[ Num_Ops ] = { | ||||||
| 				"+", | 				"+", | ||||||
| 				"-", | 				"-", | ||||||
| @@ -262,43 +287,48 @@ namespace gen | |||||||
| 	{ | 	{ | ||||||
| 		enum Type : u8 | 		enum Type : u8 | ||||||
| 		{ | 		{ | ||||||
| 			Attribute,          // [ <attributes ] | 			Attribute,           | ||||||
| 			Alignas,            // alignas(#) | 			Alignas,             | ||||||
| 			Constexpr,          // constexpr | 			Constexpr,           | ||||||
| 			Const,              // const | 			Const,               | ||||||
| 			Inline,             // inline | 			Inline,              | ||||||
| 			RValue,             //  | 			Pointer,             | ||||||
|  | 			Reference,           | ||||||
|  | 			RValue,              | ||||||
|  |  | ||||||
| 			C_Linkage,          // extern "C" | 			C_Linkage,           | ||||||
| 			API_Import,         // Vendor specific way dynamic import symbol | 			API_Import,          | ||||||
| 			API_Export,         // Vendor specific way to dynamic export | 			API_Export,          | ||||||
| 			External_Linkage,   // extern | 			External_Linkage,    | ||||||
| 			Internal_Linkage,   // static (within unit file) | 			Internal_Linkage,    | ||||||
| 			Static_Member,      // static (within sturct/class) | 			Static_Member,       | ||||||
| 			Local_Persist,      // static (within function) | 			Local_Persist,       | ||||||
| 			Thread_Local,       // thread_local | 			Thread_Local,        | ||||||
|  |  | ||||||
|  | 			Invalid, | ||||||
| 			Num_Specifiers, | 			Num_Specifiers, | ||||||
| 			Invalid |  | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		// Specifier to string | 		// Specifier to string | ||||||
| 		inline | 		inline | ||||||
| 		char const* to_str( Type specifier ) | 		char const* to_str( Type specifier ) | ||||||
| 		{ | 		{ | ||||||
| 			static  | 			local_persist | ||||||
| 			char const* lookup[ Num_Specifiers ] = { | 			char const* lookup[ Num_Specifiers ] = { | ||||||
| 				"alignas", | 				"alignas", | ||||||
| 				"constexpr", | 				"constexpr", | ||||||
| 				"const", | 				"const", | ||||||
| 				"inline", | 				"inline", | ||||||
|  | 				"*", | ||||||
|  | 				"&", | ||||||
|  | 				"&&", | ||||||
|  |  | ||||||
| 				"extern \"C\"", | 				"extern \"C\"", | ||||||
|  |  | ||||||
| 			#if defined(ZPL_SYSTEM_WINDOWS) && 0// API_Import and API_Export strings | 			#if defined(ZPL_SYSTEM_WINDOWS) | ||||||
| 				"__declspec(dllexport)", | 				"__declspec(dllexport)", | ||||||
| 				"__declspec(dllimport)", | 				"__declspec(dllimport)", | ||||||
| 			#elif defined(ZPL_SYSTEM_MACOS) || 1 | 			#elif defined(ZPL_SYSTEM_MACOS) | ||||||
| 				"__attribute__ ((visibility (\"default\")))", | 				"__attribute__ ((visibility (\"default\")))", | ||||||
| 				"__attribute__ ((visibility (\"default\")))", | 				"__attribute__ ((visibility (\"default\")))", | ||||||
| 			#endif | 			#endif | ||||||
| @@ -315,14 +345,14 @@ namespace gen | |||||||
| 		 | 		 | ||||||
| 		Type to_type( char const* str, s32 length ) | 		Type to_type( char const* str, s32 length ) | ||||||
| 		{ | 		{ | ||||||
| 			static  | 			local_persist | ||||||
| 			u32 keymap[ Num_Specifiers ]; | 			u32 keymap[ Num_Specifiers ]; | ||||||
| 			do_once_start | 			do_once_start | ||||||
| 				for ( u32 index = 0; index < Num_Specifiers; index++ ) | 				for ( u32 index = 0; index < Num_Specifiers; index++ ) | ||||||
| 				{ | 				{ | ||||||
| 					char const* enum_str = to_str( (Type)index ); | 					char const* enum_str = to_str( (Type)index ); | ||||||
|  |  | ||||||
| 					keymap[index] = crc32( enum_str, strnlen(enum_str, 42) ); | 					keymap[index] = crc32( enum_str, zpl_strnlen(enum_str, 42) ); | ||||||
| 				} | 				} | ||||||
| 			do_once_end | 			do_once_end | ||||||
|  |  | ||||||
| @@ -339,6 +369,7 @@ namespace gen | |||||||
| 	} | 	} | ||||||
| 	using SpecifierT = ESpecifier::Type; | 	using SpecifierT = ESpecifier::Type; | ||||||
|  |  | ||||||
|  | #pragma region Data Structures | ||||||
| 	// TODO: If perf needs it, convert layout an SOA format. | 	// TODO: If perf needs it, convert layout an SOA format. | ||||||
| 	/*  | 	/*  | ||||||
| 		Simple AST POD with functionality to seralize into C++ syntax. | 		Simple AST POD with functionality to seralize into C++ syntax. | ||||||
| @@ -349,32 +380,46 @@ namespace gen | |||||||
| 	*/ | 	*/ | ||||||
| 	struct AST | 	struct AST | ||||||
| 	{ | 	{ | ||||||
| 	#pragma region Member API | 	#pragma region Member Procedures | ||||||
|  | 		bool add( AST* other ); | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| 		void add( AST* other ) | 		void add_entry( AST* other ) | ||||||
| 		{ | 		{ | ||||||
| 			array_append( Entries, other ); | 			array_append( Entries, other ); | ||||||
|  |  | ||||||
| 			other->Parent = this; | 			other->Parent = this; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		AST* body() | ||||||
|  | 		{ | ||||||
|  | 			return Entries[0]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		bool check(); | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| 		bool has_entries() const | 		bool has_entries() const | ||||||
| 		{ | 		{ | ||||||
| 			static bool lookup[ ECode::Num_Types] = { | 			static bool lookup[ ECode::Num_Types] = { | ||||||
| 				false, // Invalid | 				false, // Invalid | ||||||
| 				false, // Untyped | 				false, // Untyped | ||||||
| 				true,  // Decl_Function | 				false, | ||||||
| 				true,  // Decl_Type | 				false, | ||||||
| 				true,  // Function | 				false, | ||||||
|  | 				true,  // Global_Body | ||||||
| 				true,  // Parameters | 				true,  // Parameters | ||||||
|  | 				true,  // Proc | ||||||
|  | 				true,  // Proc_Body | ||||||
|  | 				true,  // Proc_Forward | ||||||
| 				false, // Specifies | 				false, // Specifies | ||||||
| 				true,  // Struct | 				true,  // Struct | ||||||
| 				true,  // Struct_Body | 				true,  // Struct_Body | ||||||
| 				true,  // Variable | 				true,  // Variable | ||||||
| 				true,  // Typedef | 				true,  // Typedef | ||||||
| 				true,  // Typename | 				true,  // Typename | ||||||
| 				true,  // Using |  | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 			return lookup[Type]; | 			return lookup[Type]; | ||||||
| @@ -394,7 +439,7 @@ namespace gen | |||||||
|  |  | ||||||
| 		string to_string() const; | 		string to_string() const; | ||||||
|  |  | ||||||
| 	#pragma endregion Member API | 	#pragma endregion Member Procedures | ||||||
|  |  | ||||||
| 	#define Using_Code_POD          \ | 	#define Using_Code_POD          \ | ||||||
| 		CodeT             Type;     \ | 		CodeT             Type;     \ | ||||||
| @@ -434,20 +479,32 @@ namespace gen | |||||||
| 		Code body() | 		Code body() | ||||||
| 		{ | 		{ | ||||||
| 			if ( ast->Type == ECode::Invalid ) | 			if ( ast->Type == ECode::Invalid ) | ||||||
| 				fatal("Code::body: Type is invalid, cannot get"); | 			{ | ||||||
|  | 				log_failure("Code::body: Type is invalid, cannot get"); | ||||||
|  | 				return InvalidCode; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			if ( ast->Entries == nullptr || array_count(ast->Entries) == 0 ) | 			if ( ast->Entries == nullptr || array_count(ast->Entries) == 0 ) | ||||||
| 				fatal("Code::body: Entries of ast not properly setup."); | 			{ | ||||||
|  | 				log_failure("Code::body: Entries of ast not properly setup."); | ||||||
|  | 				return InvalidCode; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			return pcast( Code, ast->Entries[0]); | 		#ifdef GEN_ENFORCE_READONLY_AST  | ||||||
|  | 			if ( ast->Readonly ) | ||||||
|  | 			{ | ||||||
|  | 				log_failure("Attempted to a body AST from a readonly AST!");			 | ||||||
|  | 				return InvalidCode; | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  |  | ||||||
|  | 			return * (Code*)( ast->body() ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| 		void lock() | 		void lock() | ||||||
| 		{ | 		{ | ||||||
| 		#ifdef GEN_ENFORCE_READONLY_AST |  | ||||||
| 			ast->Readonly = true; | 			ast->Readonly = true; | ||||||
| 		#endif |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		forceinline | 		forceinline | ||||||
| @@ -468,6 +525,20 @@ namespace gen | |||||||
| 		 | 		 | ||||||
| 		Code& operator =( Code other ) | 		Code& operator =( Code other ) | ||||||
| 		{ | 		{ | ||||||
|  | 			if ( ast == nullptr ) | ||||||
|  | 			{ | ||||||
|  | 				log_failure("Attempt to set with a null AST!"); | ||||||
|  | 				return *this; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		#ifdef GEN_ENFORCE_READONLY_AST  | ||||||
|  | 			if ( ast->Readonly ) | ||||||
|  | 			{ | ||||||
|  | 				log_failure("Attempted to set a readonly AST!");			 | ||||||
|  | 				return *this; | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  |  | ||||||
| 			ast = other.ast; | 			ast = other.ast; | ||||||
|  |  | ||||||
| 			return *this; | 			return *this; | ||||||
| @@ -476,12 +547,18 @@ namespace gen | |||||||
| 		forceinline | 		forceinline | ||||||
| 		AST* operator ->()  | 		AST* operator ->()  | ||||||
| 		{ | 		{ | ||||||
| 		#ifdef GEN_ENFORCE_READONLY_AST  |  | ||||||
| 			if ( ast == nullptr ) | 			if ( ast == nullptr ) | ||||||
| 				fatal("Attempt to dereference a nullptr!"); | 			{ | ||||||
|  | 				log_failure("Attempt to dereference a nullptr!"); | ||||||
|  | 				return nullptr; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		#ifdef GEN_ENFORCE_READONLY_AST  | ||||||
| 			if ( ast->Readonly ) | 			if ( ast->Readonly ) | ||||||
| 				fatal("Attempted to access a member from a readonly ast!");			 | 			{ | ||||||
|  | 				log_failure("Attempted to access a member from a readonly AST!");			 | ||||||
|  | 				return nullptr; | ||||||
|  | 			} | ||||||
| 		#endif | 		#endif | ||||||
|  |  | ||||||
| 			return ast; | 			return ast; | ||||||
| @@ -495,6 +572,10 @@ namespace gen | |||||||
| 	// Used internally for the most part to identify invaidly generated code. | 	// Used internally for the most part to identify invaidly generated code. | ||||||
| 	extern const Code InvalidCode; | 	extern const Code InvalidCode; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	*/ | ||||||
|  | 	ZPL_TABLE_DECLARE( ZPL_EXTERN, StringTable, str_tbl_, string ); | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 		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. | ||||||
|  |  | ||||||
| @@ -502,47 +583,56 @@ namespace gen | |||||||
| 		Strings made with the Typename ASTs are stored in thier own arena allocator. | 		Strings made with the Typename ASTs are stored in thier own arena allocator. | ||||||
| 		TODO: Implement and replace usage of def_type. | 		TODO: Implement and replace usage of def_type. | ||||||
| 	*/ | 	*/ | ||||||
| 	ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeRegistry, type_reg_, Code ); | 	ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeTable, type_tbl_, Code ); | ||||||
|  | #pragma endregion Data Structures | ||||||
|  |  | ||||||
| #pragma region gen API | #pragma region Gen Interface | ||||||
| 	/* | 	/* | ||||||
| 		Initialize the library. | 		Initialize the library. | ||||||
| 		This currently just initializes the CodePool. | 		This currently just initializes the CodePool. | ||||||
| 	*/	 | 	*/	 | ||||||
| 	void init(); | 	void init(); | ||||||
|  |  | ||||||
| 	#pragma region Upfront | 	// Use this only if you know you generated the code you needed to a file | ||||||
| 	/* | 	// And rather get rid of current code asts instead of growing the pool memory. | ||||||
| 		Foward Declare a type: | 	void clear_code_pool(); | ||||||
| 		<specifiers> <type> <name>; |  | ||||||
| 	*/ |  | ||||||
| 	Code def_fwd_type( Code type, char const* name, Code specifiers = UnusedCode ); |  | ||||||
|  |  | ||||||
| 	/* | 	// Set these before calling gen's init() procedure. | ||||||
| 		Foward Declare a function: |  | ||||||
| 		<specifiers> <name> ( <params> ); | 	void set_init_reserve_code_pool   ( sw size ); | ||||||
| 	*/ | 	void set_init_reserve_string_arena( sw size ); | ||||||
| 	Code def_fwd_proc( char const* name | 	void set_init_reserve_string_table( sw size ); | ||||||
|  | 	void set_init_reserve_type_table  ( sw size ); | ||||||
|  |  | ||||||
|  | 	void set_allocator_code_pool   ( allocator pool_allocator ); | ||||||
|  | 	void set_allocator_string_arena( allocator string_allocator ); | ||||||
|  | 	void set_allocator_string_table( allocator string_allocator ); | ||||||
|  | 	void set_allocator_type_table  ( allocator type_reg_allocator ); | ||||||
|  |  | ||||||
|  | #	pragma region Upfront | ||||||
|  | 	Code def_class     ( char const* name, Code body, Code parent = UnusedCode, Code specifiers = UnusedCode ); | ||||||
|  | 	Code def_class_body( s32 num, ... ); | ||||||
|  | 	Code def_class_fwd ( char const* name ); | ||||||
|  |  | ||||||
|  | 	Code def_enum( char const* name, Code type, Code body ); | ||||||
|  |  | ||||||
|  | 	Code def_global_body( s32 num, ... ); | ||||||
|  |  | ||||||
|  | 	Code def_namespace     ( char const* name, Code body ); | ||||||
|  | 	Code def_namespace_body( s32 num, ... ); | ||||||
|  |  | ||||||
|  | 	Code def_operator( OperatorT op | ||||||
| 		, Code specifiers | 		, Code specifiers | ||||||
| 		, Code params | 		, Code params | ||||||
| 		, Code ret_type | 		, Code ret_type | ||||||
|  | 		, Code body  | ||||||
| 	); | 	); | ||||||
|  | 	Code def_operator_fwd( OperatorT op, Code specifiers, Code params, Code ret_type ); | ||||||
|  |  | ||||||
| 	/* | 	Code def_param( Code type, char const* name ); | ||||||
| 		Define an expression: | 	Code def_params( s32 num, ... ); | ||||||
| 		< c/c++ expression > | 	Code def_params( s32 num, Code* params ); | ||||||
|  |  | ||||||
| 		TODO: Evalute if you want to validiate at the execution layer during gen_time (dosen't seem necessary) |  | ||||||
| 	*/ |  | ||||||
| 	// Code def_expression( Code value ); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a function: |  | ||||||
| 		<specifiers> <name> ( <params> ) |  | ||||||
| 		{ |  | ||||||
| 			<body> |  | ||||||
| 		} |  | ||||||
| 	*/ |  | ||||||
| 	Code def_proc( char const* name | 	Code def_proc( char const* name | ||||||
| 		, Code specifiers | 		, Code specifiers | ||||||
| 		, Code params | 		, Code params | ||||||
| @@ -550,197 +640,101 @@ namespace gen | |||||||
| 		, Code body  | 		, Code body  | ||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a fucntion body: |  | ||||||
| 		{ |  | ||||||
| 			<entry> |  | ||||||
|  |  | ||||||
| 			... |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		There will be an empty line separation between entires |  | ||||||
| 	*/ |  | ||||||
| 	Code def_proc_body( s32 num, ... ); | 	Code def_proc_body( s32 num, ... ); | ||||||
| 	Code def_proc_body( s32 num, Code* codes ); | 	Code def_proc_body( s32 num, Code* codes ); | ||||||
|  |  | ||||||
| 	/* | 	Code def_proc_fwd( char const* name | ||||||
| 		Define a namespace; | 		, Code specifiers | ||||||
| 		namespace <name> | 		, Code params | ||||||
| 		{ | 		, Code ret_type | ||||||
| 			<body> | 	); | ||||||
| 		} |  | ||||||
| 	*/ |  | ||||||
| 	Code def_namespace( char const* name, Code body ); |  | ||||||
|  |  | ||||||
| 	/* | 	Code def_specifier( SpecifierT* specifier ); | ||||||
| 		Define a namespace body: |  | ||||||
| 		{ |  | ||||||
| 			<entry> |  | ||||||
|  |  | ||||||
| 			... |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		There will be an empty line separation between entires |  | ||||||
| 	*/ |  | ||||||
| 	Code def_namespace_body( s32 num, ... ); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a set of parameters for a function: |  | ||||||
| 		<name> <type>, ... |  | ||||||
| 	*/ |  | ||||||
| 	Code def_params( s32 num, ... ); |  | ||||||
| 	Code def_params( s32 num, char const** params ); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define an operator definition. |  | ||||||
| 	*/ |  | ||||||
| 	Code def_operator( OperatorT op, Code specifiers, Code params, Code ret_type, Code body ); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a set of specifiers for a function, struct, type, or varaible |  | ||||||
|  |  | ||||||
| 		Note: 		 |  | ||||||
| 		If alignas is specified the procedure expects the next argument to be the alignment value. |  | ||||||
| 		If attribute is specified the procedure expects the next argument to be its content as a string. |  | ||||||
| 	*/ |  | ||||||
| 	Code def_specifiers( s32 num , ... ); | 	Code def_specifiers( s32 num , ... ); | ||||||
| 	Code def_specifiers( s32 num, SpecifierT* specs ); | 	Code def_specifiers( s32 num, SpecifierT* specs ); | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a struct: |  | ||||||
| 		struct <specifiers> <name> : <parent> |  | ||||||
| 		{ |  | ||||||
| 			<body> |  | ||||||
| 		} |  | ||||||
| 	*/ |  | ||||||
| 	Code def_struct( char const* name, Code body, Code parent = UnusedCode, Code specifiers = UnusedCode ); | 	Code def_struct( char const* name, Code body, Code parent = UnusedCode, Code specifiers = UnusedCode ); | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a struct's body: |  | ||||||
| 		{ |  | ||||||
| 			<entry> |  | ||||||
|  |  | ||||||
| 			... |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		There will be an empty line separation between entires |  | ||||||
| 	*/ |  | ||||||
| 	Code def_struct_body( s32 num, ... ); | 	Code def_struct_body( s32 num, ... ); | ||||||
| 	Code def_struct_body( s32 num, Code* codes ); | 	Code def_struct_body( s32 num, Code* codes ); | ||||||
|  |  | ||||||
| 	/* | 	Code def_sturct_fwd(); | ||||||
| 		Define a variable: |  | ||||||
| 		<specifiers> <type> <name> = <value>; |  | ||||||
| 	*/ |  | ||||||
| 	Code def_variable( Code type, char const* name, Code value = UnusedCode, Code specifiers = UnusedCode ); | 	Code def_variable( Code type, char const* name, Code value = UnusedCode, Code specifiers = UnusedCode ); | ||||||
|  |  | ||||||
| 	/* | 	Code def_type( char const* name, Code specifiers = UnusedCode ); | ||||||
| 		Define a typename AST value. |  | ||||||
| 		Useless by itself, its intended to be used in conjunction with other Code. |  | ||||||
|  |  | ||||||
| 	Planned - Not yet Implemented: | 	Code def_using          ( char const* name, Code type ); | ||||||
| 		Typename Codes are not held in the CodePool, instead they are stored in a  |  | ||||||
| 		type registry (hastable where the key is a crc hash of the name string). |  | ||||||
|  |  | ||||||
| 		If a key exists the existing code value will be provided. |  | ||||||
| 	*/ |  | ||||||
| 	Code def_type( char const* name ); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a using typedef: |  | ||||||
| 		using <name> = <type>; |  | ||||||
| 	*/ |  | ||||||
| 	Code def_using( char const* name, Code type ); |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a using namespace: |  | ||||||
| 		using namespace <name>; |  | ||||||
|  |  | ||||||
| 		Can only be used in either a  |  | ||||||
| 	*/ |  | ||||||
| 	Code def_using_namespace( char const* name ); | 	Code def_using_namespace( char const* name ); | ||||||
| 	#pragma endregion Upfront | #	pragma endregion Upfront | ||||||
|  |  | ||||||
| 	#pragma region Incremental | #	pragma region Incremental | ||||||
| 	/* | 	Code make_class( char const* name, Code parent = UnusedCode, Code specifiers = UnusedCode ); | ||||||
| 		Provides an incomplete procedure AST but sets the intended type. |  | ||||||
| 		Any adds will be type checked. | 	Code make_enum      ( char const* name, Code type = UnusedCode, Code body = UnusedCode ); | ||||||
|  | 	Code make_enum_class( char const* name, Code type = UnusedCode, Code body = UnusedCode ); | ||||||
|  |  | ||||||
|  | 	Code make_global_body( char const* name = "", s32 num = 0, ... ); | ||||||
|  | 	 | ||||||
|  | 	Code make_namespace( char const* name ); | ||||||
|  |  | ||||||
|  | 	Code make_operator( OperatorT op | ||||||
|  | 		, Code specifiers = UnusedCode | ||||||
|  | 		, Code params = UnusedCode | ||||||
|  | 		, Code ret_type = UnusedCode | ||||||
|  | 		, Code body  = UnusedCode | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	Code make_params( s32 num, ... ); | ||||||
|  |  | ||||||
| 		Body is automatically made. Use body() to retrieve. |  | ||||||
| 	*/ |  | ||||||
| 	Code make_proc( char const* name | 	Code make_proc( char const* name | ||||||
| 		, Code specifiers = UnusedCode | 		, Code specifiers = UnusedCode | ||||||
| 		, Code params = UnusedCode | 		, Code params = UnusedCode | ||||||
| 		, Code ret_type = UnusedCode | 		, Code ret_type = UnusedCode | ||||||
| 	); | 	); | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 		Provides an incomplete struct AST but sets the intended type. |  | ||||||
| 		Any adds will be type checked. |  | ||||||
|  |  | ||||||
| 		Body is automatically made. Use body() to retrieve. | 	Code make_specifiers( s32 num , ... ); | ||||||
| 	*/ | 	Code make_specifiers( s32 num, SpecifierT* specs ); | ||||||
|  | 	 | ||||||
| 	Code make_struct( char const* name, Code parent = UnusedCode, Code specifiers = UnusedCode ); | 	Code make_struct( char const* name, Code parent = UnusedCode, Code specifiers = UnusedCode ); | ||||||
|  |  | ||||||
| /* | 	Code make_variable( char const* name, Code type = UnusedCode, Code value = UnusedCode, Code specifiers = UnusedCode ); | ||||||
| 	Creates a unit file. |  | ||||||
|  |  | ||||||
| 	These represent an encapsulation of a generated file | 	Code make_type( char const* name, Code specifiers = UnusedCode ); | ||||||
| 	Used this if you need to pass around a group of Code entires at file scope level. |  | ||||||
|  |  | ||||||
| 	The name provided is the name of the file. | 	Code make_using( char const* name, Code type = UnusedCode, Code specifiers = UnusedCode ); | ||||||
| */ | #	pragma endregion Incremental | ||||||
| Code make_file_body( char const* name ); |  | ||||||
| 	#pragma endregion Incremental |  | ||||||
|  |  | ||||||
| 	/* | #	pragma region Parsing | ||||||
| 	*/ | 	Code parse_class( char const* class_def, s32 length ); | ||||||
| 	Code parse_variable( char const* var_def, s32 length ); | 	s32 parse_classes( char const* class_defs, s32 length, Code* out_classes ); | ||||||
|  |  | ||||||
| 	/* | 	Code parse_enum( char const* enum_def, s32 length); | ||||||
| 	*/ | 	s32 parse_enums( char const* enum_defs, s32 length, Code* out_enums ); | ||||||
| 	Code parse_using( char const* using_def, s32 length ); |  | ||||||
|  |  | ||||||
| 	/* | 	Code parse_global_body( char const* body_def, s32 length ); | ||||||
|  |  | ||||||
| 	*/ |  | ||||||
| 	Code parse_operator( char const* operator_def, s32 length ); | 	Code parse_operator( char const* operator_def, s32 length ); | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a procedure by parsing a string. |  | ||||||
|  |  | ||||||
| 		Note: This parser only supports the language features the library supports |  | ||||||
| 		Any other features used and the lex or parse operation will fail. |  | ||||||
|  |  | ||||||
| 		This is not a full-on c/c++ parser, it literally only grabs  |  | ||||||
| 		what it needs to reconstruct the Code AST for seralization in the  |  | ||||||
| 		builder, nothing else. |  | ||||||
| 	*/ |  | ||||||
| 	Code parse_proc( char const* proc_def, s32 length ); | 	Code parse_proc( char const* proc_def, s32 length ); | ||||||
|  | 	s32 parse_procs( char const* proc_defs, s32 length, Code* out_procs ); | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 		Define a struct by parsing a string. |  | ||||||
|  |  | ||||||
| 		Note: This parser only supports the language features the library supports |  | ||||||
| 		Any other features used and the lex or parse operation will fail. |  | ||||||
|  |  | ||||||
| 		This is not a full-on c/c++ parser, it literally only grabs  |  | ||||||
| 		what it needs to reconstruct the Code AST for seralization in the  |  | ||||||
| 		builder, nothing else. |  | ||||||
| 	*/ |  | ||||||
| 	Code parse_struct( char const* struct_def, s32 length ); | 	Code parse_struct( char const* struct_def, s32 length ); | ||||||
|  | 	s32 parse_structs( char const* struct_defs, s32 length, Code* out_struct_codes ); | ||||||
|  |  | ||||||
| 	/* | 	Code parse_variable( char const* var_def, s32 length ); | ||||||
| 	 | 	s32 parse_variables( char const* vars_def, s32 length, Code* out_var_codes ); | ||||||
| 	*/ |  | ||||||
| 	s32 parse_vars( char const* vars_def, s32 length, Code* out_vars_codes ); |  | ||||||
|  |  | ||||||
| 	/* | 	Code parse_type( char const* type_def, s32 length ); | ||||||
|  |  | ||||||
| 	*/ | 	Code parse_typedef( char const* typedef_def, s32 length ); | ||||||
| 	s32 parse_usings( char const* usings_def, s32 length, Code* out_usings_codes ); | 	s32 parse_typedef( char const* typedef_def, s32 length, Code* out_typedef_codes ); | ||||||
|  |  | ||||||
| 	#pragma region Untyped text | 	Code parse_using ( char const* using_def, s32 length ); | ||||||
|  | 	s32 parse_usings( char const* usings_def, s32 length, Code* out_using_codes ); | ||||||
|  | #	pragma endregion Parsing | ||||||
|  |  | ||||||
|  | #	pragma region Untyped text | ||||||
| 	/* | 	/* | ||||||
| 		Define an untyped code string. | 		Define an untyped code string. | ||||||
|  |  | ||||||
| @@ -779,7 +773,7 @@ Code make_file_body( char const* name ); | |||||||
| 		Consider this an a preprocessor define. | 		Consider this an a preprocessor define. | ||||||
| 	*/ | 	*/ | ||||||
| 	Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... ); | 	Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... ); | ||||||
| 	#pragma endregion Untyped text | #	pragma endregion Untyped text | ||||||
|  |  | ||||||
| 	/*  | 	/*  | ||||||
| 		Used to generate the files. | 		Used to generate the files. | ||||||
| @@ -806,7 +800,7 @@ Code make_file_body( char const* name ); | |||||||
| 		bool open( char const* path ); | 		bool open( char const* path ); | ||||||
| 		void write(); | 		void write(); | ||||||
| 	}; | 	}; | ||||||
| #pragma endregion gen API | #pragma endregion Gen Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| #pragma region MACROS | #pragma region MACROS | ||||||
| @@ -839,7 +833,7 @@ Code make_file_body( char const* name ); | |||||||
| #	define using_type( Name_, Type_ )		 Code Name_     = gen::def_using( #Name_, t_##Type_ ) | #	define using_type( Name_, Type_ )		 Code Name_     = gen::def_using( #Name_, t_##Type_ ) | ||||||
| #	define variable( Type_, Name_, ... )     Code Name_     = gen::def_variable( t_##Type_, #Name_, __VA_ARGS__ ) | #	define variable( Type_, Name_, ... )     Code Name_     = gen::def_variable( t_##Type_, #Name_, __VA_ARGS__ ) | ||||||
|  |  | ||||||
| #   define untyped( Value_ )                      gen::untyped_str( txt(Value_) ) | #   define untyped( Value_ )                      gen::untyped_str( txt_with_length(Value_) ) | ||||||
| #	define code_token( Fmt_, ... )                gen::untyped_token_fmt( Fmt_, VA_NARGS( __VA_ARGS__), __VA_ARGS__ ) | #	define code_token( Fmt_, ... )                gen::untyped_token_fmt( Fmt_, VA_NARGS( __VA_ARGS__), __VA_ARGS__ ) | ||||||
| #	define code_fmt( Fmt_, ... )                  gen::untyped_fmt( Fmt_, __VA_ARGS__ ) | #	define code_fmt( Fmt_, ... )                  gen::untyped_fmt( Fmt_, __VA_ARGS__ ) | ||||||
| #	define specifiers( ... )                      gen::def_specifiers( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | #	define specifiers( ... )                      gen::def_specifiers( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | ||||||
| @@ -849,19 +843,24 @@ Code make_file_body( char const* name ); | |||||||
| #	define var( Type_, Name_, ... )               gen::def_variable( Type_, #Name_, __VA_ARGS__ ) | #	define var( Type_, Name_, ... )               gen::def_variable( Type_, #Name_, __VA_ARGS__ ) | ||||||
|  |  | ||||||
| #   define make( Type_, Name_, ... )                                Code Name_ = make_##Type_( #Name_, __VA_ARGS__ ); | #   define make( Type_, Name_, ... )                                Code Name_ = make_##Type_( #Name_, __VA_ARGS__ ); | ||||||
|  | #	define enum( Name_, Type_, Body_ )                                      gen::def_enum( #Name_, t_##Type_, Body_ ) | ||||||
| #	define proc( Name_, Specifiers_, RetType_, Parameters_, Body_ ) Name_ = gen::def_proc( #Name_, Specifiers_, Parameters_, RetType_, Body_ ) | #	define proc( Name_, Specifiers_, RetType_, Parameters_, Body_ ) Name_ = gen::def_proc( #Name_, Specifiers_, Parameters_, RetType_, Body_ ) | ||||||
| #	define proc_body( ... )                                                 gen::def_proc_body( VA_NARGS( __VA_ARS__ ), __VA_ARGS__ ) | #	define proc_body( ... )                                                 gen::def_proc_body( VA_NARGS( __VA_ARS__ ), __VA_ARGS__ ) | ||||||
| #	define params( ... )                                                    gen::def_params( VA_NARGS( __VA_ARGS__ ) / 2, __VA_ARGS__ ) | #	define params( ... )                                                    gen::def_params( VA_NARGS( __VA_ARGS__ ) / 2, __VA_ARGS__ ) | ||||||
| #	define struct( Name_, Parent_, Specifiers_, Body_ )             Name_ = gen::def_struct( #Name_, Body_, Parent_, Specifiers_ ) | #	define struct( Name_, Parent_, Specifiers_, Body_ )             Name_ = gen::def_struct( #Name_, Body_, Parent_, Specifiers_ ) | ||||||
| #	define struct_body( ... )                                               gen::def_struct_body( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | #	define struct_body( ... )                                               gen::def_struct_body( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | ||||||
|  |  | ||||||
| #	define add_var( Type_, Name_, ... ) add( gen::def_variable( t_##Type_, #Name_, __VA_ARGS__ ) ) | #	define add_var( Value_ )     add( gen::parse_variable( txt_with_length(Value_)) ) | ||||||
| #	define add_untyped( Value_ )        add( gen::untyped_str( txt( Value ) ) ) | #	define add_untyped( Value_ ) add( gen::untyped_str( txt_with_length( Value_ ) ) ) | ||||||
| #	define add_ret_type( ... ) | #	define add_type( Value_ )    add( gen::parse_type( txt_with_length(Value_)) ) | ||||||
| #	define add_params( ... ) | #	define add_params( Value_ )  add( gen::parse_params( txt_with_length(Value_) )) | ||||||
|  |  | ||||||
|  | #	define enum_code( Def_ )   gen::parse_enum( txt( Def_ ), sizeof( txt( Def_ )) ) | ||||||
|  | #	define global_code( Def_ ) gen::parse_global_body( txt_with_length( Def_ )) | ||||||
|  | #	define namespace_code( Def_ ) gen::parse_namespace( txt(Def_), sizeof( txt(Def_)) ) | ||||||
| #	define proc_code( Def_ )   gen::parse_proc( txt( Def_ ), sizeof( txt( Def_ )) ) | #	define proc_code( Def_ )   gen::parse_proc( txt( Def_ ), sizeof( txt( Def_ )) ) | ||||||
| #	define struct_code( Def_ ) gen::parse_struct( txt( Def_ ), sizeof( txt( Def_ )) ) | #	define struct_code( Def_ ) gen::parse_struct( txt( Def_ ), sizeof( txt( Def_ )) ) | ||||||
|  | #	define variable_code( Def_ ) gen::parse_variable( txt_with_length( Def_ ) ) | ||||||
| #endif | #endif | ||||||
| #pragma endregion MACROS | #pragma endregion MACROS | ||||||
|  |  | ||||||
| @@ -873,31 +872,38 @@ namespace gen | |||||||
| 	// These are not set until gen::init is called. | 	// These are not set until gen::init is called. | ||||||
| 	// This just preloads a bunch of Code types into the code pool. | 	// This just preloads a bunch of Code types into the code pool. | ||||||
|  |  | ||||||
| 	extern const Code t_void; | 	extern Code t_void; | ||||||
|  |  | ||||||
| 	extern const Code t_bool; | 	extern Code t_bool; | ||||||
| 	extern const Code t_char; | 	extern Code t_char; | ||||||
| 	extern const Code t_wchar_t; | 	extern Code t_wchar_t; | ||||||
|  |  | ||||||
| 	extern const Code t_s8; | 	extern Code t_s8; | ||||||
| 	extern const Code t_s16; | 	extern Code t_s16; | ||||||
| 	extern const Code t_s32; | 	extern Code t_s32; | ||||||
| 	extern const Code t_s64; | 	extern Code t_s64; | ||||||
|  |  | ||||||
| 	extern const Code t_u8; | 	extern Code t_u8; | ||||||
| 	extern const Code t_u16; | 	extern Code t_u16; | ||||||
| 	extern const Code t_u32; | 	extern Code t_u32; | ||||||
| 	extern const Code t_u64; | 	extern Code t_u64; | ||||||
|  |  | ||||||
| 	extern const Code t_sw; | 	extern Code t_sw; | ||||||
| 	extern const Code t_uw; | 	extern Code t_uw; | ||||||
|  |  | ||||||
| 	extern const Code t_f32; | 	extern Code t_f32; | ||||||
| 	extern const Code t_f64; | 	extern Code t_f64; | ||||||
|  |  | ||||||
| 	extern const Code spec_constexpr; | 	extern Code spec_constexpr; | ||||||
| 	extern const Code spec_inline; | 	extern Code spec_inline; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | namespace gen | ||||||
|  | { | ||||||
|  | 	extern Code access_public; | ||||||
|  | 	extern Code access_protected; | ||||||
|  | 	extern Code access_private; | ||||||
|  | } | ||||||
| #pragma endregion CONSTANTS | #pragma endregion CONSTANTS | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										543
									
								
								project/gen.singleheader.c99.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										543
									
								
								project/gen.singleheader.c99.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,543 @@ | |||||||
|  | /* | ||||||
|  | 	Will generate a c99 compliant version of the gen library | ||||||
|  |  | ||||||
|  | 	Note: This is done this way to test usage of library. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | #define GEN_DEFINE_DSL | ||||||
|  | #include "gen.cpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | ct char const* Header_Comment =  | ||||||
|  | R"(/* | ||||||
|  | 	genc: A simple staged metaprogramming library for C99. | ||||||
|  | 	 | ||||||
|  | 	This library is intended for small-to midsize projects. | ||||||
|  |  | ||||||
|  | 	AST type checking supports only a small subset of c++.  | ||||||
|  | 	See the 'ECode' namespace and 'gen API' region to see what is supported. | ||||||
|  |  | ||||||
|  | 	### *WHAT IS NOT PROVIDED* | ||||||
|  |  | ||||||
|  | 	* Macro or template generation      : This library is to avoid those, adding support for them adds unnecessary complexity.  | ||||||
|  | 	                                      If you desire define them outside the gen_time scopes.  | ||||||
|  | 	* Expression validation             : Execution expressions are defined using the untyped string API.  | ||||||
|  | 	                                      There is no parse API for validating expression (possibly will add in the future) | ||||||
|  | 	* Complete file parser DSL          : This isn't like the unreal header tool.  | ||||||
|  | 	                                      Code injection to file or based off a file contents is not supported by the api. However nothing is stopping you using the library for that purpose. | ||||||
|  | 	* Modern c++ (STL library) features | ||||||
|  |  | ||||||
|  | 	The AST is managed by the library and provided the user via its interface prodedures. | ||||||
|  |  | ||||||
|  | 	Notes: | ||||||
|  |  | ||||||
|  | 	* The allocator definitions used are exposed to the user incase they want to dictate memory usage | ||||||
|  | 	* ASTs are wrapped for the user in a Code struct which essentially a warpper for a AST* type.   | ||||||
|  | 	* Both AST and Code have member symbols but their data layout is enforced to be POD types. | ||||||
|  |  | ||||||
|  | 	Data layout of AST struct: | ||||||
|  |  | ||||||
|  | 	genc_CodeT             Type;     | ||||||
|  | 	bool                   Readonly; | ||||||
|  | 	genc_AST*              Parent;   | ||||||
|  | 	genc_string            Name ;     | ||||||
|  | 	genc_string            Comment;  | ||||||
|  | 	union {                     | ||||||
|  | 		array(genc_AST*)   Entries; | ||||||
|  | 		genc_string        Content; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	*`CodeT` is a typedef for `ECode::Type` which is the type of the enum.* | ||||||
|  |  | ||||||
|  | 	ASTs can be set to readonly by calling Code's lock() member function. | ||||||
|  | 	Adding comments is always available even if the AST is set to readonly.   | ||||||
|  |  | ||||||
|  | 	### There are four sets of interfaces for Code AST generation the library provides | ||||||
|  |  | ||||||
|  | 	* Upfront | ||||||
|  | 	* Incremental | ||||||
|  | 	* Parsing | ||||||
|  | 	* Untyped | ||||||
|  |  | ||||||
|  | 	### Upfront Construction | ||||||
|  |  | ||||||
|  | 	All component ASTs must be previously constructed, and provided on creation of the code AST. | ||||||
|  | 	The construction will fail and return InvalidCode otherwise. | ||||||
|  |  | ||||||
|  | 	Interface : | ||||||
|  |  | ||||||
|  | 	* genc_def_class | ||||||
|  | 	* genc_def_class_body | ||||||
|  | 	* genc_def_class_fwd | ||||||
|  | 	* genc_def_enum | ||||||
|  | 	* genc_def_enum_class | ||||||
|  | 	* genc_def_enum_body | ||||||
|  | 	* genc_def_global_body | ||||||
|  | 	* genc_def_namespace | ||||||
|  | 	* genc_def_namespace_body | ||||||
|  | 	* genc_def_operator | ||||||
|  | 	* genc_def_param | ||||||
|  | 	* genc_def_params | ||||||
|  | 	* genc_def_proc | ||||||
|  | 	* genc_def_proc_body | ||||||
|  | 	* genc_def_proc_fwd | ||||||
|  | 	* genc_def_operator_fwd | ||||||
|  | 	* genc_def_specifier | ||||||
|  | 	* genc_def_specifiers | ||||||
|  | 	* genc_def_struct | ||||||
|  | 	* genc_def_struct_body | ||||||
|  | 	* genc_def_struct_fwd | ||||||
|  | 	* genc_def_variable | ||||||
|  | 	* genc_def_type | ||||||
|  | 	* genc_def_using | ||||||
|  | 	* genc_def_using_namespace | ||||||
|  |  | ||||||
|  | 	### Incremental construction | ||||||
|  |  | ||||||
|  | 	A Code ast is provided but only completed upfront if all components are provided. | ||||||
|  | 	Components are then added using the AST API for adding ASTs: | ||||||
|  |  | ||||||
|  | 	* genc_code_add( AST*, AST* other )                     // Adds AST with validation. | ||||||
|  | 	* genc_code_add_entry( AST*, AST* other )               // Adds AST entry without validation. | ||||||
|  |  | ||||||
|  | 	Code ASTs may be explictly validated at anytime using Code's check() member function. | ||||||
|  |  | ||||||
|  | 	Interface : | ||||||
|  |  | ||||||
|  | 	* genc_make_class | ||||||
|  | 	* genc_make_enum | ||||||
|  | 	* genc_make_enum_class | ||||||
|  | 	* genc_make_fwd | ||||||
|  | 	* genc_make_global_body | ||||||
|  | 	* genc_make_namespace | ||||||
|  | 	* genc_make_operator | ||||||
|  | 	* genc_make_params | ||||||
|  | 	* genc_make_proc | ||||||
|  | 	* genc_make_specifiers | ||||||
|  | 	* genc_make_struct | ||||||
|  | 	* genc_make_variable | ||||||
|  | 	* genc_make_type | ||||||
|  | 	* genc_make_using | ||||||
|  |  | ||||||
|  | 	### Parse construction | ||||||
|  |  | ||||||
|  | 	A string provided to the API is parsed for the intended language construct. | ||||||
|  |  | ||||||
|  | 	Interface : | ||||||
|  |  | ||||||
|  | 	* genc_parse_class | ||||||
|  | 	* genc_parse_classes | ||||||
|  | 	* genc_parse_class_fwd | ||||||
|  | 	* genc_parse_classes_fwd | ||||||
|  | 	* genc_parse_enum | ||||||
|  | 	* genc_parse_enums | ||||||
|  | 	* genc_parse_global_body | ||||||
|  | 	* genc_parse_namespace | ||||||
|  | 	* genc_parse_namespaces | ||||||
|  | 	* genc_parse_params | ||||||
|  | 	* genc_parse_proc | ||||||
|  | 	* genc_parse_procs | ||||||
|  | 	* genc_parse_operator | ||||||
|  | 	* genc_parse_operators | ||||||
|  | 	* genc_parse_specifiers | ||||||
|  | 	* genc_parse_struct | ||||||
|  | 	* genc_parse_strucs | ||||||
|  | 	* genc_parse_variable | ||||||
|  | 	* genc_parse_variables | ||||||
|  | 	* genc_parse_type | ||||||
|  | 	* genc_parse_types | ||||||
|  | 	* genc_parse_using | ||||||
|  | 	* genc_parse_usings | ||||||
|  |  | ||||||
|  | 	The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. | ||||||
|  | 	This includes the assignmetn of variables; due to the library not yet supporting c/c++ expression parsing. | ||||||
|  |  | ||||||
|  | 	The plural variants provide an array of codes, its up to the user to add them to a body AST  | ||||||
|  | 	(they are not auto-added to a body) | ||||||
|  |  | ||||||
|  | 	### Untyped constructions | ||||||
|  |  | ||||||
|  | 	Code ASTs are constructed using unvalidated strings. | ||||||
|  |  | ||||||
|  | 	Interface : | ||||||
|  |  | ||||||
|  | 	* genc_untyped_str | ||||||
|  | 	* genc_untyped_fmt | ||||||
|  | 	* genc_untyped_token_fmt | ||||||
|  |  | ||||||
|  | 	During serialization any untyped Code AST is has its string value directly injected inline of  | ||||||
|  | 	whatever context the content existed as an entry within. | ||||||
|  | 	Even though thse are not validated from somewhat correct c/c++ syntax or components, it doesn't mean that | ||||||
|  | 	Untyped code can be added as any component of a Code AST: | ||||||
|  |  | ||||||
|  | 	* Untyped code cannot have children, thus there cannot be recursive injection this way. | ||||||
|  | 	* Untyped code can only be a child of a parent of body AST, or for values of an assignment. | ||||||
|  |  | ||||||
|  | 	These restrictions help prevent abuse of untyped code to some extent. | ||||||
|  | */ | ||||||
|  | )"; | ||||||
|  |  | ||||||
|  | Code IfDef_GENC_IMPLEMENTATION; | ||||||
|  | Code EndIf_GENC_IMPLEMENTATION; | ||||||
|  |  | ||||||
|  | Code make_log_failure() | ||||||
|  | { | ||||||
|  | 	Code result = make_global_body(); | ||||||
|  | 	{ | ||||||
|  | 		result->add( untyped_str( | ||||||
|  | 			R"(#ifdef GEN_USE_FATAL)" | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		result->add( proc_code( | ||||||
|  | 			inline | ||||||
|  | 			sw genc_log_failure(char const *fmt, ...)  | ||||||
|  | 			{ | ||||||
|  | 				if ( genc_global_ShouldShowDebug == false ) | ||||||
|  | 					return 0; | ||||||
|  |  | ||||||
|  | 				sw res; | ||||||
|  | 				va_list va; | ||||||
|  | 				 | ||||||
|  | 				va_start(va, fmt); | ||||||
|  | 				res = zpl_printf_va(fmt, va); | ||||||
|  | 				va_end(va); | ||||||
|  | 				 | ||||||
|  | 				return res; | ||||||
|  | 			} | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		result->add( untyped_str( | ||||||
|  | 			R"(#else)" | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		result->add( parse_proc( | ||||||
|  | R"(inline | ||||||
|  | sw genc_log_failure(char const *fmt, ...)  | ||||||
|  | { | ||||||
|  | 	local_persist thread_local  | ||||||
|  | 	char buf[ZPL_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 	va_list va; | ||||||
|  |  | ||||||
|  | #if Build_Debug | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	zpl_snprintf_va(buf, ZPL_PRINTF_MAXLEN, fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	assert_crash(buf); | ||||||
|  | 	return -1; | ||||||
|  | #else | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	zpl_printf_err_va( fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	zpl_exit(1); | ||||||
|  | 	return -1; | ||||||
|  | #endif | ||||||
|  | })" | ||||||
|  | 		,	372 | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		result->add( untyped_str( | ||||||
|  | 			R"(#endif)" | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		result->check(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_ECode() | ||||||
|  | { | ||||||
|  | 	Code ECode = make_global_body(); | ||||||
|  | 	{ | ||||||
|  | 		ECode->add( parse_enum( | ||||||
|  | R"(enum genc_ECode | ||||||
|  | { | ||||||
|  | 	Invalid, | ||||||
|  | 	Untyped, | ||||||
|  | 	Enum, | ||||||
|  | 	Enum_Body, | ||||||
|  | 	Global_Body, | ||||||
|  | 	Parameters, | ||||||
|  | 	Proc,            | ||||||
|  | 	Proc_Body,       | ||||||
|  | 	Proc_Forward,    | ||||||
|  | 	Specifiers,      | ||||||
|  | 	Struct,          | ||||||
|  | 	Struct_Body,     | ||||||
|  | 	Variable,        | ||||||
|  | 	Typedef,         | ||||||
|  | 	Typename,   | ||||||
|  |  | ||||||
|  | 	Num_Types | ||||||
|  | }; | ||||||
|  | typedef u32 genc_CodeT;)" + 1 | ||||||
|  | 		,	280 | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		ECode->add( proc_code( | ||||||
|  | 			inline | ||||||
|  | 			char const* genc_ecode_to_str( Type type ) | ||||||
|  | 			{ | ||||||
|  | 				genc_local_persist | ||||||
|  | 				char const* lookup[Num_Types] = { | ||||||
|  | 					"Invalid", | ||||||
|  | 					"Untyped", | ||||||
|  | 					"Access_Public", | ||||||
|  | 					"Access_Private", | ||||||
|  | 					"Access_Protected", | ||||||
|  | 					"Class", | ||||||
|  | 					"Enum", | ||||||
|  | 					"Enum_Body", | ||||||
|  | 					"Global_Body", | ||||||
|  | 					"Namespace", | ||||||
|  | 					"Namespace_Body", | ||||||
|  | 					"Parameters", | ||||||
|  | 					"Proc", | ||||||
|  | 					"Proc_Body", | ||||||
|  | 					"Proc_Forward", | ||||||
|  | 					"Specifiers", | ||||||
|  | 					"Struct", | ||||||
|  | 					"Struct_Body", | ||||||
|  | 					"Variable", | ||||||
|  | 					"Typedef", | ||||||
|  | 					"Typename", | ||||||
|  | 					"Using", | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				return lookup[ type ]; | ||||||
|  | 			} | ||||||
|  | 		)); | ||||||
|  |  | ||||||
|  | 		ECode->check(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ECode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_EOperator() | ||||||
|  | { | ||||||
|  | 	Code eoperator = make_global_body(); | ||||||
|  |  | ||||||
|  | 	return eoperator; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_ESpecifier() | ||||||
|  | { | ||||||
|  | 	Code especifier = make_global_body(); | ||||||
|  |  | ||||||
|  | 	return especifier; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_Code() | ||||||
|  | { | ||||||
|  | 	Code code = make_global_body(); | ||||||
|  |  | ||||||
|  | 	code->add( struct_code( | ||||||
|  | 		struct genc_AST | ||||||
|  | 		{ | ||||||
|  | 			genc_CodeT             Type;     | ||||||
|  | 			bool                   Readonly; | ||||||
|  | 			genc_AST*              Parent;   | ||||||
|  | 			genc_string            Name;     | ||||||
|  | 			genc_string            Comment;  | ||||||
|  | 			union {                     | ||||||
|  | 				array(genc_AST*)   Entries; | ||||||
|  | 				genc_string        Content; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 		typedef struct genc_AST genc_AST; | ||||||
|  | 		typedef genc_AST* Code; | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	code->add( proc_code( | ||||||
|  | 		bool genc_ast_add( genc_Code other ); | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	code->add( proc_code(  | ||||||
|  | 		genc_forceinline | ||||||
|  | 		void genc_ast_add_entry( genc_Code self,  genc_Code other ) | ||||||
|  | 		{ | ||||||
|  | 			genc_array_append( self->Entries, other ); | ||||||
|  |  | ||||||
|  | 			other->Parent = self; | ||||||
|  | 		} | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	code->add( untyped_str( | ||||||
|  | 		R"(#define genc_code_body( AST_ ) AST->Entries[0])", 47 | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	code->add( proc_code(  | ||||||
|  | 		genc_forceinline | ||||||
|  | 		bool genc_code_has_entries( Code self ) const | ||||||
|  | 		{ | ||||||
|  | 			genc_local_persist  | ||||||
|  | 			bool lookup[ genc_ECode::Num_Types] = { | ||||||
|  | 				false, // Invalid | ||||||
|  | 				false, // Untyped | ||||||
|  | 				true,  // Global_Body | ||||||
|  | 				true,  // Parameters | ||||||
|  | 				true,  // Proc | ||||||
|  | 				true,  // Proc_Body | ||||||
|  | 				true,  // Proc_Foward | ||||||
|  | 				false, // Specifies | ||||||
|  | 				true,  // Struct | ||||||
|  | 				true,  // Struct_Body | ||||||
|  | 				true,  // Variable | ||||||
|  | 				true,  // Typedef | ||||||
|  | 				true,  // Typename | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			return lookup[self->Type]; | ||||||
|  | 		} | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	code->check(); | ||||||
|  |  | ||||||
|  | 	return code; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_static_Data() | ||||||
|  | { | ||||||
|  | 	Code  | ||||||
|  | 	data = make_global_body(); | ||||||
|  | 	data->add( IfDef_GENC_IMPLEMENTATION ); | ||||||
|  | 	data->add( global_code( | ||||||
|  | 		static genc_array(genc_AST) genc_CodePool = nullptr; | ||||||
|  |  | ||||||
|  | 		static genc_array(genc_arena) genc_StringArenas =  nullptr; | ||||||
|  |  | ||||||
|  | 		static genc_StringTable    genc_StringMap; | ||||||
|  | 		static genc_TypeTable      genc_TypeMap; | ||||||
|  |  | ||||||
|  | 		static sw genc_InitSize_CodePool       = genc_megabytes(64); | ||||||
|  | 		static sw genc_InitSize_StringArena    = genc_megabytes(32); | ||||||
|  | 		static sw genc_InitSize_StringTable    = genc_megabytes(4); | ||||||
|  | 		static sw genc_InitSize_TypeTable      = genc_megabytes(4); | ||||||
|  |  | ||||||
|  | 		static allocator genc_Allocator_CodePool    = zpl_heap(); | ||||||
|  | 		static allocator genc_Allocator_StringArena = zpl_heap(); | ||||||
|  | 		static allocator genc_Allocator_StringTable = zpl_heap(); | ||||||
|  | 		static allocator genc_Allocator_TypeTable   = zpl_heap(); | ||||||
|  | 	)); | ||||||
|  | 	data->add( untyped_str( R"(#ifdef GENC_DEFINE_LIBRARY_CODE_CONSTANTS)")); | ||||||
|  | 	data->add( global_code( | ||||||
|  | 		Code t_void; | ||||||
|  |  | ||||||
|  | 		Code t_bool; | ||||||
|  | 		Code t_char; | ||||||
|  | 		Code t_char_wide; | ||||||
|  |  | ||||||
|  | 		Code t_s8; | ||||||
|  | 		Code t_s16; | ||||||
|  | 		Code t_s32; | ||||||
|  | 		Code t_s64; | ||||||
|  |  | ||||||
|  | 		Code t_u8; | ||||||
|  | 		Code t_u16; | ||||||
|  | 		Code t_u32; | ||||||
|  | 		Code t_u64; | ||||||
|  |  | ||||||
|  | 		Code t_sw; | ||||||
|  | 		Code t_uw; | ||||||
|  |  | ||||||
|  | 		Code t_f32; | ||||||
|  | 		Code t_f64; | ||||||
|  | 	)); | ||||||
|  | 	data->add( untyped_str( R"(#endif)")); | ||||||
|  | 	data->add( global_code( | ||||||
|  | 		Code spec_inline; | ||||||
|  | 		Code spec_const; | ||||||
|  | 	)); | ||||||
|  | 	data->add( EndIf_GENC_IMPLEMENTATION ); | ||||||
|  |  | ||||||
|  | 	return data; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_make_code() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_init() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_mem_config_interface() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_internal_funcs() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_upfront() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_incremental() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_parsing() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_untyped() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code make_interface() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int gen_main() | ||||||
|  | { | ||||||
|  | 	Memory::setup(); | ||||||
|  | 	gen::init(); | ||||||
|  | 	 | ||||||
|  | 	IfDef_GENC_IMPLEMENTATION = untyped( | ||||||
|  | 		R"(#ifdef GENC_IMPLEMENTATION)" | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	EndIf_GENC_IMPLEMENTATION = untyped( | ||||||
|  | 		R"(#endif // GENC_IMPLEMENTATION)" | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	Code header_comment = untyped_str( Header_Comment, sizeof( Header_Comment ) ); | ||||||
|  | 	Code log_failure    = make_log_failure(); | ||||||
|  |  | ||||||
|  | 	Code ecode          = make_ECode(); | ||||||
|  | 	Code eoperator      = make_EOperator(); | ||||||
|  | 	Code especifier     = make_ESpecifier(); | ||||||
|  | 	Code code           = make_Code(); | ||||||
|  | 	 | ||||||
|  | 	Builder | ||||||
|  | 	builder; | ||||||
|  | 	builder.open( "genc.h" ); | ||||||
|  |  | ||||||
|  | 	builder.print( header_comment ); | ||||||
|  | 	builder.print( log_failure ); | ||||||
|  | 	builder.print( ecode ); | ||||||
|  | 	builder.print( eoperator ); | ||||||
|  | 	builder.print( especifier ); | ||||||
|  | 	builder.print( code ); | ||||||
|  |  | ||||||
|  | 	builder.write(); | ||||||
|  |  | ||||||
|  | 	Memory::cleanup(); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										55
									
								
								project/gen.singleheader.c99.data
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								project/gen.singleheader.c99.data
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | # HEADER COMMENT | ||||||
|  | 1, 166 | ||||||
|  |  | ||||||
|  | # CODE TYPES | ||||||
|  | Invalid | ||||||
|  | Untyped         | ||||||
|  | Enum            | ||||||
|  | Enum_Body | ||||||
|  | Global_Body | ||||||
|  | Parameters | ||||||
|  | Proc       | ||||||
|  | Proc_Body | ||||||
|  | Proc_Forward | ||||||
|  | Specifiers     | ||||||
|  | Struct       | ||||||
|  | Struct_Body | ||||||
|  | Variable      | ||||||
|  | Typedef         | ||||||
|  | Typename | ||||||
|  | Using     | ||||||
|  |  | ||||||
|  | # CODE_HAS_ENTRIES | ||||||
|  |  | ||||||
|  | # SPECIFIER_TYPES | ||||||
|  | Attribute | ||||||
|  | Alignas           | ||||||
|  | Constexpr | ||||||
|  | Const           | ||||||
|  | Inline | ||||||
|  | Pointer | ||||||
|  | API_Import         | ||||||
|  | API_Export         | ||||||
|  | External_Linkage | ||||||
|  | Internal_Linkage   | ||||||
|  | Local_Persist | ||||||
|  | Thread_Local       | ||||||
|  | Invalid | ||||||
|  |  | ||||||
|  | # SPECIFIER_STRINGS | ||||||
|  | "alignas", | ||||||
|  | "const", | ||||||
|  | "inline", | ||||||
|  | "*", | ||||||
|  | #if defined(ZPL_SYSTEM_WINDOWS) | ||||||
|  | "__declspec(dllexport)", | ||||||
|  | "__declspec(dllimport)", | ||||||
|  | #elif defined(ZPL_SYSTEM_MACOS) | ||||||
|  | "__attribute__ ((visibility (\"default\")))", | ||||||
|  | "__attribute__ ((visibility (\"default\")))", | ||||||
|  | #endif | ||||||
|  | "extern", | ||||||
|  | "static", | ||||||
|  | "static", | ||||||
|  | "thread_local" | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								project/gen.singleheader.c99.refactor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								project/gen.singleheader.c99.refactor
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | __VERSION 1 | ||||||
|  |  | ||||||
|  | word AST,  genc_AST | ||||||
|  | word Code, genc_Code | ||||||
|  |  | ||||||
|  | word ECode,      genc_ECode | ||||||
|  | word EOperator,  genc_EOperator | ||||||
|  | word ESpecifier, genc_ESpecifier | ||||||
|  | word CodeT,      genc_CodeT | ||||||
|  |  | ||||||
|  | word string, genc_string | ||||||
|  | word init,   genc_init | ||||||
|  |  | ||||||
|  | namespace def_,           genc_def_ | ||||||
|  | namespace make_,          genc_make_ | ||||||
|  | namespace parse_,         genc_parse_ | ||||||
|  | namespace untyped_,       genc_untyped_ | ||||||
|  | namespace set_init_,      genc_set_init_ | ||||||
|  | namespace set_allocator_, genc_set_allocator_ | ||||||
|  |  | ||||||
|  | word clean_code_pool, genc_clean_code_pool | ||||||
|  |  | ||||||
|  | word Builder, genc_Builder | ||||||
|  |  | ||||||
|  | word CodePool,     genc_CodePool | ||||||
|  | word StringArenas, genc_StringArenas | ||||||
|  | word CodePOD,      genc_AST | ||||||
|  | word StringMap,    genc_StringMap | ||||||
|  | word TypeMap,      genc_TypeMap | ||||||
|  |  | ||||||
|  | namespace InitSize_,  genc_InitSize_ | ||||||
|  | namespace Allocator_, genc_Allocator_ | ||||||
|  |  | ||||||
|  | namespace spec_, genc_spec | ||||||
							
								
								
									
										0
									
								
								project/gen.singleheader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								project/gen.singleheader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										4
									
								
								singleheader/genc.refactor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								singleheader/genc.refactor
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | // Removes the genc_ namespace if desired | ||||||
|  |  | ||||||
|  | namespace genc_ | ||||||
|  |  | ||||||
| @@ -16,7 +16,7 @@ | |||||||
| 	#ifndef GEN_DEFINE_DSL | 	#ifndef GEN_DEFINE_DSL | ||||||
| 		using namespace gen; | 		using namespace gen; | ||||||
|  |  | ||||||
| 		Code t_allocator = def_type( txt(allocator) ); | 		Code t_allocator = def_type( txt(allocator)  ); | ||||||
|  |  | ||||||
| 		Code header; | 		Code header; | ||||||
| 		{ | 		{ | ||||||
| @@ -64,7 +64,6 @@ | |||||||
| 		return ArrayBase; | 		return ArrayBase; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#define gen_array( Type_ ) gen__array( #Type_, sizeof(Type_), a_base ) |  | ||||||
| 	Code gen__array( char const* type_str, s32 type_size, Code parent ) | 	Code gen__array( char const* type_str, s32 type_size, Code parent ) | ||||||
| 	{ | 	{ | ||||||
| 	#ifndef GEN_DEFINE_DSL | 	#ifndef GEN_DEFINE_DSL | ||||||
| @@ -155,6 +154,7 @@ | |||||||
| 			Code append = make_proc( "append" ); | 			Code append = make_proc( "append" ); | ||||||
| 			{ | 			{ | ||||||
| 				append->add( def_params( 1, type, "value") ); | 				append->add( def_params( 1, type, "value") ); | ||||||
|  | 				append->add( t_bool ); | ||||||
|  |  | ||||||
| 				Code  | 				Code  | ||||||
| 				body = append.body(); | 				body = append.body(); | ||||||
| @@ -172,6 +172,8 @@ | |||||||
| 					 | 					 | ||||||
| 					return true; | 					return true; | ||||||
| 				))); | 				))); | ||||||
|  |  | ||||||
|  | 				append->check(); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			Code back; | 			Code back; | ||||||
| @@ -295,7 +297,7 @@ | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			Code set_capacity = parse_proc( txt_with_length( | 			Code set_capacity = parse_proc( txt_with_length( | ||||||
| 				bool set_capacity( new_capacity ) | 				bool set_capacity( sw new_capacity ) | ||||||
| 				{ | 				{ | ||||||
| 					Header& header = get_header(); | 					Header& header = get_header(); | ||||||
|  |  | ||||||
| @@ -305,7 +307,7 @@ | |||||||
| 					if ( capacity < header.Num ) | 					if ( capacity < header.Num ) | ||||||
| 						header.Num = capacity; | 						header.Num = capacity; | ||||||
|  |  | ||||||
| 					uw      size       = sizeof(Header) + sizeof(Type) * capacity; | 					sw      size       = sizeof(Header) + sizeof(Type) * capacity; | ||||||
| 					Header* new_header = rcast( Header* alloc( header.Allocator, size )); | 					Header* new_header = rcast( Header* alloc( header.Allocator, size )); | ||||||
|  |  | ||||||
| 					if ( new_header == nullptr ) | 					if ( new_header == nullptr ) | ||||||
| @@ -591,18 +593,58 @@ | |||||||
| 		return array_def; | 		return array_def; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	struct ArrayRequest | ||||||
|  | 	{ | ||||||
|  | 		char const* Name; | ||||||
|  | 		sw          Size; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	array(ArrayRequest) UserArrayGenQueue; | ||||||
|  |  | ||||||
|  | 	#define gen_array( Type_ ) add_gen_array_request( #Type_, sizeof(Type_) ) | ||||||
|  |  | ||||||
|  | 	void add_gen_array_request( const char* type_str, sw type_size ) | ||||||
|  | 	{ | ||||||
|  | 		ArrayRequest request = { type_str, type_size }; | ||||||
|  |  | ||||||
|  | 		array_append( UserArrayGenQueue, request ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	u32 gen_array_file() | 	u32 gen_array_file() | ||||||
| 	{ | 	{ | ||||||
| 		Code a_base = gen__array_base(); | 		Code a_base = gen__array_base(); | ||||||
|  |  | ||||||
| 		Code a_u32  = gen_array( u32 ); | 		add_gen_array_request( "u32", sizeof(u32) ); | ||||||
| 		Code a_cstr = gen_array( char const* ); | 		gen_array( char const* ); | ||||||
|  |  | ||||||
|  | 		array(Code) array_asts; | ||||||
|  | 		array_init( array_asts, g_allocator ); | ||||||
|  |  | ||||||
|  | 		sw left  = array_count( UserArrayGenQueue ); | ||||||
|  | 		sw index = 0; | ||||||
|  | 		while( left -- ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayRequest request = UserArrayGenQueue[index]; | ||||||
|  |  | ||||||
|  | 			Code result = gen__array( request.Name, request.Size, a_base ); | ||||||
|  |  | ||||||
|  | 			array_append( array_asts, result ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		Builder | 		Builder | ||||||
| 		arraygen; | 		arraygen; | ||||||
| 		arraygen.open( "Array.gen.hpp" ); | 		arraygen.open( "Array.gen.hpp" ); | ||||||
| 		arraygen.print( a_u32 ); |  | ||||||
| 		arraygen.print( a_cstr ); | 		left  = array_count( array_asts ); | ||||||
|  | 		index = 0; | ||||||
|  |  | ||||||
|  | 		while( left-- ) | ||||||
|  | 		{ | ||||||
|  | 			Code code = array_asts[index]; | ||||||
|  |  | ||||||
|  | 			arraygen.print( code ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		arraygen.write(); | 		arraygen.write(); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								test/c99/meson.build
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								test/c99/meson.build
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | project( 'test', 'c', default_options : ['buildtype=debug'] ) | ||||||
|  |  | ||||||
|  | # add_global_arguments('-E', language : 'cpp') | ||||||
|  |  | ||||||
|  | includes = include_directories(  | ||||||
|  |   [  | ||||||
|  |     '../gen', | ||||||
|  |     '../../singleheader'  | ||||||
|  |   ]) | ||||||
|  |  | ||||||
|  | # get_sources = files('./get_sources.ps1') | ||||||
|  | # sources     = files(run_command('powershell', get_sources, check: true).stdout().strip().split('\n')) | ||||||
|  |  | ||||||
|  | sources = [ 'test.c99.c' ] | ||||||
|  |  | ||||||
|  | if get_option('buildtype').startswith('debug') | ||||||
|  |  | ||||||
|  |   add_project_arguments('-DBuild_Debug', language : ['c' ]) | ||||||
|  |  | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | executable( 'test_c99', sources, include_directories : includes ) | ||||||
							
								
								
									
										79
									
								
								test/c99/table.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								test/c99/table.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | #include "gen.h" | ||||||
|  |  | ||||||
|  | #define Table( Type_ ) Table_##Type_ | ||||||
|  |  | ||||||
|  | typedef u64(*)(void*) HashingFn; | ||||||
|  |  | ||||||
|  | #if gen_time | ||||||
|  | #	define gen_table( Type_, HashingFn_ ) gen_request_table( #Type_, sizeof(Type_), HashingFn_ )  | ||||||
|  |  | ||||||
|  | 	u64 table_default_hash_fn( void* address ) | ||||||
|  | 	{ | ||||||
|  | 		return crc32( address, 4 ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	Code gen_table_code( char const* type_str, sw type_size, HashingFn hash_fn ) | ||||||
|  | 	{ | ||||||
|  | 		Code table; | ||||||
|  |  | ||||||
|  | 		return table; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	struct TableRequest | ||||||
|  | 	{ | ||||||
|  | 		char const* Type; | ||||||
|  | 		sw          Size; | ||||||
|  | 		HashingFn   HashFn; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	array(TableRequest) TableRequests; | ||||||
|  |  | ||||||
|  | 	void gen_request_table( const char* type_str, sw type_size, HashingFn hash_fn ) | ||||||
|  | 	{ | ||||||
|  | 		TableRequest request = { type_str, type_size, hash_fn }; | ||||||
|  |  | ||||||
|  | 		array_append( TableRequests, request ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	u32 gen_table_file() | ||||||
|  | 	{ | ||||||
|  | 		gen_table( u32 ); | ||||||
|  | 		gen_table( char const* ); | ||||||
|  |  | ||||||
|  | 		array(Code) array_asts; | ||||||
|  | 		array_init( array_asts, g_allocator ); | ||||||
|  |  | ||||||
|  | 		sw left  = array_count( TableRequests ); | ||||||
|  | 		sw index = 0; | ||||||
|  | 		while( left -- ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayRequest request = TableRequests[index]; | ||||||
|  |  | ||||||
|  | 			Code result = gen_table_code( request.Name, request.Size, request.HashFn ); | ||||||
|  |  | ||||||
|  | 			array_append( array_asts, result ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		arraygen; | ||||||
|  | 		arraygen.open( "table.gen.h" ); | ||||||
|  |  | ||||||
|  | 		left  = array_count( array_asts ); | ||||||
|  | 		index = 0; | ||||||
|  |  | ||||||
|  | 		while( left-- ) | ||||||
|  | 		{ | ||||||
|  | 			Code code = array_asts[index]; | ||||||
|  |  | ||||||
|  | 			arraygen.print( code ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		arraygen.write(); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef gen_time | ||||||
|  | #	include "table.gen.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
							
								
								
									
										40
									
								
								test/c99/test.c99.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								test/c99/test.c99.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | #define GENC_IMPLEMENTATION | ||||||
|  | #include "genc.h" | ||||||
|  | #include "table.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct Test | ||||||
|  | { | ||||||
|  | 	u64 A; | ||||||
|  | 	u64 B; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if gen_time | ||||||
|  |  | ||||||
|  |  | ||||||
|  | u64 hash_struct( void* test ) | ||||||
|  | { | ||||||
|  | 	return crc32( ((Test)test).A, sizeof(u64) ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int gen_main() | ||||||
|  | { | ||||||
|  | 	gen_table( Test, & hash_struct ) | ||||||
|  |  | ||||||
|  | 	gen_table_file(); | ||||||
|  | }	 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if runtime | ||||||
|  | int main() | ||||||
|  | { | ||||||
|  | 	Table(Test) test_table; | ||||||
|  |  | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  | #endif | ||||||
| @@ -25,7 +25,7 @@ | |||||||
| 	#ifndef GEN_DEFINE_DSL | 	#ifndef GEN_DEFINE_DSL | ||||||
| 		string name = string_sprintf( g_allocator, (char*)sprintf_buf, ZPL_PRINTF_MAXLEN, "square", type ); | 		string name = string_sprintf( g_allocator, (char*)sprintf_buf, ZPL_PRINTF_MAXLEN, "square", type ); | ||||||
|  |  | ||||||
| 		#if 1 | 		#if 0 | ||||||
| 		Code square; | 		Code square; | ||||||
| 		{ | 		{ | ||||||
| 			Code params     = def_params( 1, integral_type, "value" ); | 			Code params     = def_params( 1, integral_type, "value" ); | ||||||
| @@ -43,9 +43,9 @@ | |||||||
| 				return value * value; | 				return value * value; | ||||||
| 			} | 			} | ||||||
| 		); | 		); | ||||||
| 		char const* gen_code = token_fmt( tmpl, 1, type ); | 		char const* gen_code = token_fmt( tmpl, 1, "type", type ); | ||||||
|  |  | ||||||
| 		Code square = parse_proc(gen_code); | 		Code square = parse_proc(gen_code, strlen(gen_code)); | ||||||
| 		#endif | 		#endif | ||||||
|  |  | ||||||
| 	#else  | 	#else  | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								test/test.singleheader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/test.singleheader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								thirdparty/zpl.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								thirdparty/zpl.h
									
									
									
									
										vendored
									
									
								
							| @@ -5095,8 +5095,8 @@ License: | |||||||
|           |           | ||||||
|          typedef struct string_header { |          typedef struct string_header { | ||||||
|              allocator allocator; |              allocator allocator; | ||||||
|              sw length; |  | ||||||
|              sw capacity; |              sw capacity; | ||||||
|  |              sw length; | ||||||
|          } string_header; |          } string_header; | ||||||
|           |           | ||||||
|          #define ZPL_STRING_HEADER(str) (zpl_cast(ZPL_NS string_header *)(str) - 1) |          #define ZPL_STRING_HEADER(str) (zpl_cast(ZPL_NS string_header *)(str) - 1) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user