mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 22:40:54 -07:00 
			
		
		
		
	Updated AST::to_string to latest api changes with modules and attributes.
This commit is contained in:
		| @@ -89,7 +89,6 @@ using zpl::string_length; | ||||
| using zpl::string_make; | ||||
| using zpl::str_len; | ||||
|  | ||||
|  | ||||
| #if __clang__ | ||||
| #	pragma clang diagnostic pop | ||||
| #endif | ||||
| @@ -146,17 +145,17 @@ using zpl::str_len; | ||||
|  | ||||
| #define macro_expand( Expanded_ ) Expanded_ | ||||
|  | ||||
| #define bit( Value_ )                      ( 1 << Value_ ) | ||||
| #define bitfield_is_equal( Field_, Mask_ ) ( ( (Mask_) & (Field_) ) == (Mask_) ) | ||||
| #define forceinline                        ZPL_ALWAYS_INLINE | ||||
| #define print_nl( _)                       zpl_printf("\n") | ||||
| #define ccast( Type_, Value_ )             * const_cast< Type_* >( & (Value_) ) | ||||
| #define scast( Type_, Value_ )			   static_cast< Type_ >( Value_ ) | ||||
| #define rcast( Type_, Value_ )			   reinterpret_cast< Type_ >( Value_ ) | ||||
| #define pcast( Type_, Value_ )             ( * (Type_*)( & (Value_) ) ) | ||||
| #define txt_impl( Value_ )                 #Value_ | ||||
| #define txt( Value_ )                      txt_impl( Value_ ) | ||||
| #define txt_n_len( Value_ )		           sizeof( txt_impl( Value_ ) ), txt_impl( Value_ ) | ||||
| #define bit( Value_ )                             ( 1 << Value_ ) | ||||
| #define bitfield_is_equal( Type_, Field_, Mask_ ) ( (Type_(Mask_) & Type_(Field_)) == Type_(Mask_) ) | ||||
| #define forceinline                               ZPL_ALWAYS_INLINE | ||||
| #define print_nl( _)                              zpl_printf("\n") | ||||
| #define ccast( Type_, Value_ )                    * const_cast< Type_* >( & (Value_) ) | ||||
| #define scast( Type_, Value_ )			          static_cast< Type_ >( Value_ ) | ||||
| #define rcast( Type_, Value_ )			          reinterpret_cast< Type_ >( Value_ ) | ||||
| #define pcast( Type_, Value_ )                    ( * (Type_*)( & (Value_) ) ) | ||||
| #define txt_impl( Value_ )                        #Value_ | ||||
| #define txt( Value_ )                             txt_impl( Value_ ) | ||||
| #define txt_n_len( Value_ )		                  sizeof( txt_impl( Value_ ) ), txt_impl( Value_ ) | ||||
| #define do_once()      \ | ||||
| do                     \ | ||||
| {                      \ | ||||
| @@ -184,6 +183,94 @@ while(0); | ||||
| constexpr | ||||
| char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED"; | ||||
|  | ||||
|  | ||||
| #pragma region Memory | ||||
| #pragma endregion Memory | ||||
|  | ||||
| #pragma region String | ||||
| #if 0 | ||||
| 	struct String | ||||
| 	{ | ||||
| 		struct Header | ||||
| 		{ | ||||
| 			AllocatorInfo Allocator; | ||||
| 			sw            Length; | ||||
| 			sw            Capacity; | ||||
| 		}; | ||||
|  | ||||
| 		static String make ( AllocatorInfo allocator, char const* str ) | ||||
| 		{ | ||||
| 			sw length = str ? str_len( str ) : 0; | ||||
| 			return make_length( allocator, str, length ); | ||||
| 		} | ||||
|  | ||||
| 		static String make_reserve( AllocatorInfo allocator, sw capacity ) | ||||
| 		{ | ||||
| 			constexpr sw header_size = sizeof( Header ); | ||||
|  | ||||
| 			s32   alloc_size = header_size + capacity + 1; | ||||
| 			void* allocation = alloc( allocator, alloc_size ); | ||||
|  | ||||
| 			if ( allocation == nullptr ) | ||||
| 				return { nullptr }; | ||||
|  | ||||
| 			mem_set( allocation, 0, alloc_size ); | ||||
|  | ||||
| 			Header* | ||||
| 			header            = rcast(Header*, allocation); | ||||
| 			header->Allocator = allocator; | ||||
| 			header->Capacity  = capacity; | ||||
| 			header->Length    = 0; | ||||
|  | ||||
| 			String result = { (char*)allocation + header_size }; | ||||
| 			return result; | ||||
| 		} | ||||
|  | ||||
| 		static String make_length( AllocatorInfo allocator, char const* str, sw length ); | ||||
|  | ||||
| 		static String fmt    ( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... ); | ||||
| 		static String fmt_buf( AllocatorInfo allocator, char const* fmt, ... ); | ||||
|  | ||||
| 		static String join( AllocatorInfo allocator, char const** parts, sw num_parts, char const* glue ); | ||||
|  | ||||
| 		static bool are_equal( String lhs, String rhs ); | ||||
|  | ||||
| 		void append( char c ); | ||||
| 		void append( char const* str ); | ||||
| 		void append( char const* str, sw length ); | ||||
| 		void append( const String other ); | ||||
| 		void append( char const* fmt, ... ); | ||||
| 		void append( const String other ); | ||||
|  | ||||
| 		sw avail_space(); | ||||
| 		sw capacity(); | ||||
|  | ||||
| 		void clear(); | ||||
|  | ||||
| 		String duplicate( AllocatorInfo allocator ); | ||||
|  | ||||
| 		void free(); | ||||
|  | ||||
| 		Header& header(); | ||||
|  | ||||
| 		sw length(); | ||||
|  | ||||
| 		void trim( char const* cut_set ); | ||||
| 		void trim_space(); | ||||
|  | ||||
|  | ||||
| 		char* Data = nullptr; | ||||
| 	}; | ||||
|  | ||||
| 	struct String_POD | ||||
| 	{ | ||||
| 		char* Data; | ||||
| 	}; | ||||
| 	static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | ||||
| #endif | ||||
| #pragma endregion String | ||||
|  | ||||
|  | ||||
| namespace Memory | ||||
| { | ||||
| 	constexpr uw Initial_Reserve = megabytes(10); | ||||
|   | ||||
							
								
								
									
										434
									
								
								project/gen.cpp
									
									
									
									
									
								
							
							
						
						
									
										434
									
								
								project/gen.cpp
									
									
									
									
									
								
							| @@ -126,7 +126,7 @@ namespace gen | ||||
| #	define AST_BODY_NAMESPACE_UNALLOWED_TYPES      AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||
| #	define AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||
|  | ||||
| #	define AST_BODY_STRUCT_UNALLOWED_TYPES AST_BODY_CLASS_UNALLOWED_TYPES | ||||
| #	define AST_BODY_STRUCT_UNALLOWED_TYPES         AST_BODY_CLASS_UNALLOWED_TYPES | ||||
| #pragma endregion AST Body Case Macros | ||||
|  | ||||
| #pragma region AST | ||||
| @@ -488,8 +488,31 @@ namespace gen | ||||
|  | ||||
| 	String AST::to_string() | ||||
| 	{ | ||||
| 	#	define ProcessModuleFlags() \ | ||||
| 		if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export ))  \ | ||||
| 			result = string_append_fmt( result, "export " );             \ | ||||
|                                                                          \ | ||||
| 		if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Import ))  \ | ||||
| 			result = string_append_fmt( result, "import " );             \ | ||||
|                                                                          \ | ||||
| 		if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Private )) \ | ||||
| 			result = string_append_fmt( result, "private " ); | ||||
|  | ||||
| 		String result = string_make( g_allocator, "" ); | ||||
|  | ||||
| 		// Scope indentation. | ||||
| 		char indent_str[128] = {0};   // Should be more than enough... | ||||
| 		s32  tab_count       = 0; | ||||
| 		{ | ||||
| 			AST* curr_parent = Parent; | ||||
|  | ||||
| 			while ( Parent ) | ||||
| 			{ | ||||
| 				indent_str[tab_count] = '\t'; | ||||
| 				tab_count++; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch ( Type ) | ||||
| 		{ | ||||
| 			using namespace ECode; | ||||
| @@ -504,6 +527,8 @@ namespace gen | ||||
|  | ||||
| 			case Comment: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				static char line[MaxCommentLineLength]; | ||||
|  | ||||
| 				s32 left  = string_length( ccast(String, Content) ); | ||||
| @@ -526,141 +551,219 @@ namespace gen | ||||
| 			case Access_Private: | ||||
| 			case Access_Protected: | ||||
| 			case Access_Public: | ||||
| 				result = string_append_length( result, Name, string_length( ccast(String, Name)) ) ; | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
| 				result = string_append_length( result, Name, string_length( ccast(String, Name)) ); | ||||
| 			break; | ||||
|  | ||||
| 			case Attributes: | ||||
| 				result = string_append_fmt( result, "%s", Content ); | ||||
| 				result = string_append_length( result, Content, string_length( ccast(String, Content)) ); | ||||
|  | ||||
| 			case Class: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				result = string_append_fmt( result, "class"); | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "class "); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, " %s", Entries[idx]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, " %s", Name ); | ||||
| 				result = string_append_length( result, Name, string_length( ccast(String, Name)) ); | ||||
|  | ||||
| 				if ( parent() ) | ||||
| 					result = string_append_fmt( result, " : %s", parent()->to_string() ); | ||||
| 				AST* parent = Entries[idx]; | ||||
|  | ||||
| 				result = string_append_fmt( result, "\n{\n%s\n};\n", body()->to_string() ); | ||||
| 				if ( parent ) | ||||
| 				{ | ||||
| 					char const* access_level = to_str( ParentAccess ); | ||||
|  | ||||
| 					result = string_append_fmt( result, ": %s %s\n%s{\n" | ||||
| 						, access_level | ||||
| 						, parent | ||||
| 						, indent_str | ||||
| 					); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "%s\n%s};\n", body()->to_string(), indent_str ); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Class_Fwd: | ||||
| 			{ | ||||
| 				result = string_append_fmt( result, "class"); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, " %s", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, " %s;", Name ); | ||||
| 				result = string_append_fmt( result, "class %s;", Name ); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Enum: | ||||
| 				if ( underlying_type() ) | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				string_append_length( result, "enum ", 5); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "enum %s : %s\n{\n%s\n};\n" | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Typename) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s : %s\n%s{\n" | ||||
| 						, Name | ||||
| 						, underlying_type()->to_string() | ||||
| 						, body()->to_string() | ||||
| 						, Entries[idx]->to_string() | ||||
| 						, indent_str | ||||
| 					); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "enum %s\n{\n%s\n};\n" | ||||
| 					result = string_append_fmt( result, "%s\n%s{\n" | ||||
| 						, Name | ||||
| 						, body()->to_string() | ||||
| 						, indent_str | ||||
| 					); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "%s\n%s};" | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			break; | ||||
|  | ||||
| 			case Enum_Fwd: | ||||
| 				result = string_append_fmt( result, "enum %s : %s;\n", Name, underlying_type()->to_string() ); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "enum %s : %s;\n", Name, Entries[1]->to_string() ); | ||||
| 			break; | ||||
|  | ||||
| 			case Enum_Class: | ||||
| 				if ( underlying_type() ) | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "enum class " ); | ||||
|  | ||||
| 				s32 idx = 0; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "enum class %s : %s\n{\n%s\n};\n" | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Typename ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, ": %s\n%s{\n" | ||||
| 						, Name | ||||
| 						, underlying_type()->to_string() | ||||
| 						, body()->to_string() | ||||
| 						, Entries[idx]->to_string() | ||||
| 						, indent_str | ||||
| 					); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "enum class %s\n{\n%s\n};\n" | ||||
| 					result = string_append_fmt( result, "%s\n%s{\n" | ||||
| 						, Name | ||||
| 						, body()->to_string() | ||||
| 						, indent_str | ||||
| 					); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "%s\n%s};" | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			break; | ||||
|  | ||||
| 			case Enum_Class_Fwd: | ||||
| 				result = string_append_fmt( result, "enum class %s : %s;\n", Name, underlying_type()->to_string() ); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "enum class " ); | ||||
|  | ||||
| 				s32 idx = 0; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, ": %s;\n", Name, Entries[idx]->to_string() ); | ||||
| 			break; | ||||
|  | ||||
| 			case Execution: | ||||
| 				result = string_append_fmt( result, "%s\n", Entries[0]->to_string() ); | ||||
| 				result = string_append_length( result, Content, string_length( ccast(String, Content)) ); | ||||
| 			break; | ||||
|  | ||||
| 			case Export_Body: | ||||
| 			{ | ||||
| 				result = string_append_fmt( result, "export\n{\n" ); | ||||
| 				result = string_append_fmt( result, "%sexport\n%s{\n", indent_str, indent_str ); | ||||
|  | ||||
| 				s32 index = 0; | ||||
| 				s32 left  = num_entries(); | ||||
| 				while ( left -- ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s\n", Entries[index]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s\t%s\n", indent_str, Entries[index]->to_string() ); | ||||
| 					index++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "};\n" ); | ||||
| 				result = string_append_fmt( result, "%s};\n", indent_str ); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Extern_Linkage: | ||||
| 				result = string_append_fmt( result, "extern %s\n{\n%s\n};\n", Name, body()->to_string() ); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "extern %s\n%s{\n%s\n%s};\n" | ||||
| 					, Name | ||||
| 					, indent_str | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			break; | ||||
|  | ||||
| 			case Friend: | ||||
| 				result = string_append_fmt( result, "friend %s;\n", Entries[0]->to_string() ); | ||||
| 				result = string_append_fmt( result, "%sfriend %s;\n", indent_str, Entries[0]->to_string() ); | ||||
| 			break; | ||||
|  | ||||
| 			case Function: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				u32 idx  = 1; | ||||
| 				u32 left = num_entries(); | ||||
|  | ||||
| 				if ( left <= 0 ) | ||||
| 					log_failure( "Code::to_string - Name: %s Type: %s, expected definition", Name, Type ); | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s", Entries[idx]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 					left--; | ||||
| 				} | ||||
|  | ||||
| 				if ( left <= 0 ) | ||||
| 					log_failure( "Code::to_string - Name: %s Type: %s, expected return type", Name, Type ); | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s\n", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 					left--; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "\n%s %s(", Entries[idx]->to_string(), Name ); | ||||
| 				result = string_append_fmt( result, "%s %s(", Entries[idx]->to_string(), Name ); | ||||
| 				idx++; | ||||
| 				left--; | ||||
|  | ||||
| @@ -675,18 +778,21 @@ namespace gen | ||||
| 					result = string_append_fmt( result, "void" ); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, ")\n{\n%s\n}", body()->to_string() ); | ||||
| 				result = string_append_fmt( result, ")\n%s{\n%s\n%s}" | ||||
| 					, indent_str | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Function_Fwd: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				u32 idx  = 0; | ||||
| 				u32 left = array_count( Entries ); | ||||
|  | ||||
| 				if ( left <= 0 ) | ||||
| 					log_failure( "Code::to_string - Name: %s Type: %s, expected definition", Name, Type ); | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s\n", Entries[idx]->to_string() ); | ||||
| @@ -694,9 +800,6 @@ namespace gen | ||||
| 					left--; | ||||
| 				} | ||||
|  | ||||
| 				if ( left <= 0 ) | ||||
| 					log_failure( "Code::to_string - Name: %s Type: %s, expected return type", Name, Type ); | ||||
|  | ||||
| 				result = string_append_fmt( result, "\n%s %s(", Entries[idx]->to_string(), Name ); | ||||
| 				idx++; | ||||
| 				left--; | ||||
| @@ -717,28 +820,48 @@ namespace gen | ||||
| 			break; | ||||
|  | ||||
| 			case Module: | ||||
| 				// TODO: Add export condition | ||||
| 				// if ( ) | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "module %s", Content ); | ||||
| 			break; | ||||
|  | ||||
| 			case Namespace: | ||||
| 				result = string_append_fmt( result, "namespace %s\n{\n%s\n};\n", Name, body()->to_string() ); | ||||
| 				result = string_append_length( result, indent_str, tab_count); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "namespace %s\n%s{\n%s\n%s};\n" | ||||
| 					, Name | ||||
| 					, indent_str | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			break; | ||||
|  | ||||
| 			case Operator: | ||||
| 			case Operator_Member: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s", Entries[idx]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "%s operator%s(", Entries[idx]->to_string(), Name ); | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s\n", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "%s operator %s (", Entries[idx]->to_string(), Name ); | ||||
| 				idx++; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Parameters ) | ||||
| @@ -751,13 +874,21 @@ namespace gen | ||||
| 					result = string_append_fmt( result, "void" ); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, ")\n{\n%s\n}", body()->to_string() ); | ||||
| 				result = string_append_fmt( result, ")\n%s{\n%s\n%s}" | ||||
| 					, indent_str | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Operator_Fwd: | ||||
| 			case Operator_Member_Fwd: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				s32 idx; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| @@ -811,20 +942,28 @@ namespace gen | ||||
|  | ||||
| 			case Struct: | ||||
| 			{ | ||||
| 				result = string_append_fmt( result, "struct"); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "struct "); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, " %s", Entries[idx]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, " %s", Name ); | ||||
| 				result = string_append_fmt( result, "%s ", Name ); | ||||
|  | ||||
| 				if ( parent() ) | ||||
| 					result = string_append_fmt( result, " : %s", parent()->to_string() ); | ||||
| 				if ( Entries[idx] ) | ||||
| 				{ | ||||
| 					char const* access_str = to_str( ParentAccess ); | ||||
|  | ||||
| 					result = string_append_fmt( result, ": %s %s", access_str, Entries[idx]->to_string() ); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "\n{\n%s\n};\n", body()->to_string() ); | ||||
| 			} | ||||
| @@ -832,22 +971,30 @@ namespace gen | ||||
|  | ||||
| 			case Struct_Fwd: | ||||
| 			{ | ||||
| 				result = string_append_fmt( result, "struct"); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				result = string_append_fmt( result, "struct "); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, " %s", Entries[idx]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, " %s;", Name ); | ||||
| 				result = string_append_fmt( result, "%s;", Name ); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Variable: | ||||
| 			{ | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				s32 idx = 1; | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Specifiers ) | ||||
| @@ -864,27 +1011,87 @@ namespace gen | ||||
| 			break; | ||||
|  | ||||
| 			case Typedef: | ||||
| 				// TODO: Check for array expression | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				result = string_append_fmt( result, "typedef %s %s", Entries[0]->to_string(), Name ); | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				AST* type = Entries[0]; | ||||
|  | ||||
| 				if ( Entries[1] && Entries[1]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s ", Entries[1]->to_string() ); | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "typedef %s %s", type->to_string(), Name ); | ||||
|  | ||||
| 				if ( type->Entries[1] ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "[%s];", type->Entries[1]->to_string() ); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					result = string_append_length( result, ";", 1); | ||||
| 				} | ||||
| 			break; | ||||
|  | ||||
| 			case Typename: | ||||
| 				result = string_append_fmt( result, "%s %s", Name, Entries[0]->to_string() ); | ||||
| 				if ( Entries[0] ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s %s", Name, Entries[0]->to_string() ); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s", Name ); | ||||
| 				} | ||||
| 			break; | ||||
|  | ||||
| 			case Union: | ||||
| 				result = string_append_fmt( result, "union %s\n{\n%s\n};\n", Name, body()->to_string() ); | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				s32 idx = 0; | ||||
|  | ||||
| 				result = string_append_length( result, "union ", 6 ); | ||||
|  | ||||
| 				if ( Entries[idx]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s ", Entries[idx]->to_string() ); | ||||
| 					idx++; | ||||
| 				} | ||||
|  | ||||
| 				result = string_append_fmt( result, "%s\n%s{\n%s\n%s};\n" | ||||
| 					, Name | ||||
| 					, indent_str | ||||
| 					, body()->to_string() | ||||
| 					, indent_str | ||||
| 				); | ||||
| 			break; | ||||
|  | ||||
| 			case Using: | ||||
| 				// TODO: Check for array expression | ||||
| 				result = string_append_length( result, indent_str, tab_count ); | ||||
|  | ||||
| 				if ( Entries[0] ) | ||||
| 					result = string_append_fmt( result, "using %s = %s", Name, Entries[0] ); | ||||
| 				ProcessModuleFlags(); | ||||
|  | ||||
| 				AST* type = Entries[0]; | ||||
|  | ||||
| 				if ( Entries[1] && Entries[1]->Type == Attributes ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s ", Entries[1]->to_string() ); | ||||
| 				} | ||||
|  | ||||
| 				if ( type ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "using %s = %s", Name, type->to_string() ); | ||||
|  | ||||
| 					if ( type->Entries[1] ) | ||||
| 						result = string_append_fmt( result, "[%s]", type->Entries[1]->to_string() ); | ||||
|  | ||||
| 				} | ||||
| 				else | ||||
| 					result = string_append_fmt( result, "using %s", Name ); | ||||
|  | ||||
| 				result = string_append_fmt( result, ";" ); | ||||
| 			break; | ||||
|  | ||||
| 			case Using_Namespace: | ||||
| @@ -904,7 +1111,7 @@ namespace gen | ||||
| 				s32 left  = num_entries(); | ||||
| 				while ( left -- ) | ||||
| 				{ | ||||
| 					result = string_append_fmt( result, "%s\n", Entries[index]->to_string() ); | ||||
| 					result = string_append_fmt( result, "%s%s\n", indent_str, Entries[index]->to_string() ); | ||||
| 					index++; | ||||
| 				} | ||||
| 			} | ||||
| @@ -912,6 +1119,8 @@ namespace gen | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
|  | ||||
| 	#undef ProcessModuleFlags | ||||
| 	} | ||||
| #pragma endregion AST | ||||
|  | ||||
| @@ -1128,12 +1337,13 @@ namespace gen | ||||
| 		result->Content        = nullptr; | ||||
| 		result->Parent         = nullptr; | ||||
| 		result->Name           = nullptr; | ||||
| 		result->Comment        = nullptr; | ||||
| 		result->Type           = ECode::Invalid; | ||||
| 		result->Op             = EOperator::Invalid; | ||||
| 		result->ModuleFlags    = ModuleFlag::Invalid; | ||||
| 		result->ParentAccess   = AccessSpec::Invalid; | ||||
| 		result->StaticIndex    = 0; | ||||
| 		result->Readonly       = false; | ||||
| 		result->DynamicEntries = false; | ||||
| 		result->StaticIndex    = 0; | ||||
|  | ||||
| 		return result; | ||||
| 	} | ||||
| @@ -1621,7 +1831,7 @@ namespace gen | ||||
| 	Code def_class( s32 length, char const* name | ||||
| 		, Code body | ||||
| 		, Code parent, AccessSpec parent_access | ||||
| 		, Code specifiers, Code attributes | ||||
| 		, Code attributes | ||||
| 		, ModuleFlag mflags ) | ||||
| 	{ | ||||
| 		using namespace ECode; | ||||
| @@ -1634,15 +1844,9 @@ namespace gen | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		if ( specifiers && specifiers->Type != Specifiers ) | ||||
| 		if ( parent && parent->Type != Class || parent->Type != Struct || parent->Type != Typename || parent->Type != Untyped ) | ||||
| 		{ | ||||
| 			log_failure( "gen::def_class: specifiers was not a 'Specifiers' type: %s", specifiers->debug_str() ); | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		if ( parent && parent->Type != Class || parent->Type != Struct ) | ||||
| 		{ | ||||
| 			log_failure( "gen::def_class: parent provided is not type 'Class' or 'Struct': %s", parent->debug_str() ); | ||||
| 			log_failure( "gen::def_class: parent provided is not type 'Class', 'Struct', 'Typeanme', or 'Untyped': %s", parent->debug_str() ); | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| @@ -1675,11 +1879,11 @@ namespace gen | ||||
| 		if ( attributes ) | ||||
| 			result->add_entry( attributes ); | ||||
|  | ||||
| 		if ( specifiers ) | ||||
| 			result->add_entry( specifiers ); | ||||
|  | ||||
| 		if ( parent ) | ||||
| 		{ | ||||
| 			result->ParentAccess = parent_access; | ||||
| 			result->add_entry( parent ); | ||||
| 		} | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| @@ -1742,7 +1946,7 @@ namespace gen | ||||
| 		{ | ||||
| 			result->add_entry( type ); | ||||
| 		} | ||||
| 		else if ( result->Type == Enum_Class_Fwd || result->Type == Enum_Fwd ) | ||||
| 		else if ( result->Type != Enum_Class_Fwd && result->Type != Enum_Fwd ) | ||||
| 		{ | ||||
| 			log_failure( "gen::def_enum: enum forward declaration must have an underlying type" ); | ||||
| 			return Code::Invalid; | ||||
| @@ -2068,8 +2272,8 @@ namespace gen | ||||
|  | ||||
| 	Code def_struct( u32 length, char const* name | ||||
| 		, Code body | ||||
| 		, Code parent, Code parent_access | ||||
| 		, Code specifiers, Code attributes | ||||
| 		, Code parent, AccessSpec parent_access | ||||
| 		, Code attributes | ||||
| 		, ModuleFlag mflags ) | ||||
| 	{ | ||||
| 		using namespace ECode; | ||||
| @@ -2082,12 +2286,6 @@ namespace gen | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		if ( specifiers && specifiers->Type != Specifiers ) | ||||
| 		{ | ||||
| 			log_failure( "gen::def_struct: specifiers was not a `Specifiers` type" ); | ||||
| 			return Code::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		if ( parent && parent->Type != Struct ) | ||||
| 		{ | ||||
| 			log_failure( "gen::def_struct: parent was not a `Struct` type" ); | ||||
| @@ -2118,11 +2316,11 @@ namespace gen | ||||
| 		if ( attributes ) | ||||
| 			result->add_entry( attributes ); | ||||
|  | ||||
| 		if ( specifiers ) | ||||
| 			result->add_entry( specifiers ); | ||||
|  | ||||
| 		if ( parent ) | ||||
| 		{ | ||||
| 			result->ParentAccess = parent_access; | ||||
| 			result->add_entry( parent ); | ||||
| 		} | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| @@ -2237,8 +2435,9 @@ namespace gen | ||||
| 		} | ||||
|  | ||||
| 		Code | ||||
| 		result       = make_code(); | ||||
| 		result->Name = get_cached_string( name, length ); | ||||
| 		result              = make_code(); | ||||
| 		result->Name        = get_cached_string( name, length ); | ||||
| 		result->ModuleFlags = mflags; | ||||
|  | ||||
| 		switch ( specifier ) | ||||
| 		{ | ||||
| @@ -2254,6 +2453,9 @@ namespace gen | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if ( attributes ) | ||||
| 			result->add_entry( attributes ); | ||||
|  | ||||
| 		result.lock(); | ||||
| 		return result; | ||||
| 	} | ||||
| @@ -3218,14 +3420,6 @@ namespace gen | ||||
| #ifdef GEN_FEATURE_PARSING | ||||
| /* | ||||
| 	These constructors are the most implementation intensive other than the edtior or scanner. | ||||
|  | ||||
| 	The current implementation is very convervative and does not use a lexer to process the input first. | ||||
| 	Instead, it just sifts through the content directly looking for the syntax pattern for the code type | ||||
| 	and then constructs the AST after. | ||||
|  | ||||
| 	Eventually I will problably end up using a dedicated lexer for parser constructors to lower the sloc. | ||||
|  | ||||
| 	It uses the upfront constructors to help keep code from getitng to large since the target is to keep the sloc low | ||||
| */ | ||||
|  | ||||
| 	namespace Parser | ||||
| @@ -4151,9 +4345,7 @@ namespace gen | ||||
| 						{ | ||||
| 							case ESpecifier::Constexpr: | ||||
| 							case ESpecifier::Constinit: | ||||
| 							case ESpecifier::Export: | ||||
| 							case ESpecifier::External_Linkage: | ||||
| 							case ESpecifier::Import: | ||||
| 							case ESpecifier::Local_Persist: | ||||
| 							case ESpecifier::Mutable: | ||||
| 							case ESpecifier::Static_Member: | ||||
| @@ -4340,10 +4532,6 @@ namespace gen | ||||
| 					member = parse_variable( toks, context ); | ||||
| 				break; | ||||
|  | ||||
| 				case TokType::Spec_API: | ||||
| 					log_failure( "gen::%s: %s not allowed in function body", context, str_tok_type( currtok.Type ) ); | ||||
| 					return Code::Invalid; | ||||
|  | ||||
| 				default: | ||||
| 					Token untyped_tok = currtok; | ||||
|  | ||||
| @@ -4395,9 +4583,6 @@ namespace gen | ||||
|  | ||||
| 			switch ( spec ) | ||||
| 			{ | ||||
| 				case ESpecifier::API_Macro: | ||||
| 				case ESpecifier::API_Export: | ||||
| 				case ESpecifier::API_Import: | ||||
| 				case ESpecifier::External_Linkage: | ||||
| 				case ESpecifier::Local_Persist: | ||||
| 				case ESpecifier::Mutable: | ||||
| @@ -4685,9 +4870,6 @@ namespace gen | ||||
|  | ||||
| 			switch ( spec ) | ||||
| 			{ | ||||
| 				case ESpecifier::API_Macro: | ||||
| 				case ESpecifier::API_Export: | ||||
| 				case ESpecifier::API_Import: | ||||
| 				case ESpecifier::Constexpr: | ||||
| 				case ESpecifier::External_Linkage: | ||||
| 				case ESpecifier::Local_Persist: | ||||
|   | ||||
| @@ -291,6 +291,7 @@ namespace gen | ||||
|  | ||||
| 	enum class AccessSpec : u32 | ||||
| 	{ | ||||
| 		Default, | ||||
| 		Public, | ||||
| 		Protected, | ||||
| 		Private, | ||||
| @@ -304,6 +305,7 @@ namespace gen | ||||
| 	{ | ||||
| 		local_persist | ||||
| 		char const* lookup[ (u32)AccessSpec::Num_AccessSpec ] = { | ||||
| 			"", | ||||
| 			"private", | ||||
| 			"protected", | ||||
| 			"public", | ||||
| @@ -420,22 +422,6 @@ namespace gen | ||||
| 			return DynamicEntries ? array_count(Entries) : StaticIndex; | ||||
| 		} | ||||
|  | ||||
| 		// Class/Struct | ||||
|  | ||||
| 		inline | ||||
| 		AST* parent() | ||||
| 		{ | ||||
| 			return Entries[1]; | ||||
| 		} | ||||
|  | ||||
| 		// Enum | ||||
|  | ||||
| 		inline | ||||
| 		AST* underlying_type() | ||||
| 		{ | ||||
| 			return Entries[1]; | ||||
| 		} | ||||
|  | ||||
| 		// Parameter | ||||
|  | ||||
| 		bool add_param( AST* type, s32 length, char const* name ); | ||||
| @@ -533,7 +519,6 @@ namespace gen | ||||
| 			,	Readonly ? "true"       : "false" | ||||
| 			,	Parent   ? Parent->Name : "" | ||||
| 			,	Name     ? Name         : "" | ||||
| 			,	Comment  ? Comment      : "" | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| @@ -554,9 +539,10 @@ namespace gen | ||||
| 			- sizeof(CodeT) 	   // Type | ||||
| 			- sizeof(OperatorT)    // Op | ||||
| 			- sizeof(ModuleFlag)   // ModuleFlags | ||||
| 			- sizeof(AccessSpec)   // ParentAccess | ||||
| 			- sizeof(u32) 		   // StaticIndex | ||||
| 			- sizeof(bool) * 2     // Readonly, DynamicEntries | ||||
| 			- sizeof(u8) * 6 )     // _Align_Pad | ||||
| 			- sizeof(u8) * 2 )     // _Align_Pad | ||||
| 		/ sizeof(AST*); | ||||
|  | ||||
| 		constexpr static | ||||
| @@ -574,10 +560,11 @@ namespace gen | ||||
| 		CodeT             Type;                        \ | ||||
| 		OperatorT         Op;                          \ | ||||
| 		ModuleFlag        ModuleFlags;                 \ | ||||
| 		AccessSpec        ParentAccess;				   \ | ||||
| 		u32               StaticIndex;                 \ | ||||
| 		bool              Readonly;                    \ | ||||
| 		bool              DynamicEntries;              \ | ||||
| 		u8                _Align_Pad[6]; | ||||
| 		u8                _Align_Pad[2]; | ||||
|  | ||||
| 		Using_Code_POD | ||||
| 	}; | ||||
| @@ -785,8 +772,8 @@ namespace gen | ||||
|  | ||||
| 	Code def_class( s32 length, char const* name | ||||
| 		, Code body         = NoCode | ||||
| 		, Code parent       = NoCode, AccessSpec access     = AccessSpec::Public | ||||
| 		, Code specifiers   = NoCode, Code       attributes = NoCode | ||||
| 		, Code parent       = NoCode, AccessSpec access = AccessSpec::Public | ||||
| 		, Code attributes   = NoCode | ||||
| 		, ModuleFlag mflags = ModuleFlag::None ); | ||||
|  | ||||
| 	Code def_enum( s32 length, char const* name | ||||
| @@ -816,10 +803,10 @@ namespace gen | ||||
| 	Code def_specifier( SpecifierT specifier ); | ||||
|  | ||||
| 	Code def_struct( s32 length, char const* name | ||||
| 		, Code      body | ||||
| 		, Code      parent     = NoCode, AccessSpec access | ||||
| 		, Code      specifiers = NoCode, Code       attributes = NoCode | ||||
| 		, ModuleFlag mflags    = ModuleFlag::None ); | ||||
| 		, Code       body | ||||
| 		, Code       parent     = NoCode, AccessSpec access = AccessSpec::Public | ||||
| 		, Code       attributes = NoCode | ||||
| 		, ModuleFlag mflags     = ModuleFlag::None ); | ||||
|  | ||||
| 	Code def_typedef( s32 length, char const* name, Code type, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); | ||||
| 	Code def_type   ( s32 length, char const* name, Code arrayexpr = NoCode, Code specifiers = NoCode ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user