mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	C-library gen progress: Header files mostly done, starting dep c impl and fixes to generic selection generation
This commit is contained in:
		
							
								
								
									
										2
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -72,5 +72,5 @@ | |||||||
| 	}, | 	}, | ||||||
| 	"autoHide.autoHidePanel": false, | 	"autoHide.autoHidePanel": false, | ||||||
| 	"autoHide.autoHideSideBar": false, | 	"autoHide.autoHideSideBar": false, | ||||||
| 	"dimmer.enabled": true | 	"dimmer.enabled": false | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								gen_c_library/.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								gen_c_library/.editorconfig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | [*.c] | ||||||
|  | indent_style = tab | ||||||
|  | indent_size  = 4 | ||||||
|  |  | ||||||
|  | [*.cpp] | ||||||
|  | indent_style = tab | ||||||
|  | indent_size  = 2 | ||||||
|  |  | ||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | #include <cstdlib>   // for system() | ||||||
|  |  | ||||||
| #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| #define GEN_ENFORCE_STRONG_CODE_TYPES | #define GEN_ENFORCE_STRONG_CODE_TYPES | ||||||
| #define GEN_EXPOSE_BACKEND | #define GEN_EXPOSE_BACKEND | ||||||
| @@ -16,7 +18,6 @@ GEN_NS_END | |||||||
| #include "auxillary/builder.cpp" | #include "auxillary/builder.cpp" | ||||||
| #include "auxillary/scanner.hpp" | #include "auxillary/scanner.hpp" | ||||||
|  |  | ||||||
| #include <cstdlib>   // for system() |  | ||||||
|  |  | ||||||
| #include "components/memory.fixed_arena.hpp" | #include "components/memory.fixed_arena.hpp" | ||||||
| #include "components/misc.hpp" | #include "components/misc.hpp" | ||||||
| @@ -113,6 +114,7 @@ int gen_main() | |||||||
| 	PreprocessorDefines.append(txt("GEN_OPTIMIZE_MAPPINGS_BEGIN")); | 	PreprocessorDefines.append(txt("GEN_OPTIMIZE_MAPPINGS_BEGIN")); | ||||||
| 	PreprocessorDefines.append(txt("GEN_OPITMIZE_MAPPINGS_END")); | 	PreprocessorDefines.append(txt("GEN_OPITMIZE_MAPPINGS_END")); | ||||||
| 	//PreprocessorDefines.append(txt("GEN_EXECUTION_EXPRESSION_SUPPORT")); | 	//PreprocessorDefines.append(txt("GEN_EXECUTION_EXPRESSION_SUPPORT")); | ||||||
|  | 	PreprocessorDefines.append(txt("GEN_PARAM_DEFAULT")); | ||||||
|  |  | ||||||
| 	Code push_ignores           = scan_file( project_dir "helpers/push_ignores.inline.hpp" ); | 	Code push_ignores           = scan_file( project_dir "helpers/push_ignores.inline.hpp" ); | ||||||
| 	Code pop_ignores            = scan_file( project_dir "helpers/pop_ignores.inline.hpp" ); | 	Code pop_ignores            = scan_file( project_dir "helpers/pop_ignores.inline.hpp" ); | ||||||
| @@ -132,58 +134,57 @@ int gen_main() | |||||||
| 		// Only has operator overload definitions that C doesn't need. | 		// Only has operator overload definitions that C doesn't need. | ||||||
| 		// CodeBody ast_inlines = gen_ast_inlines(); | 		// CodeBody ast_inlines = gen_ast_inlines(); | ||||||
|  |  | ||||||
| 		Code interface  = scan_file( project_dir "components/interface.hpp" ); |  | ||||||
| 		Code inlines 	= scan_file( project_dir "components/inlines.hpp" ); | 		Code inlines 	= scan_file( project_dir "components/inlines.hpp" ); | ||||||
| 		Code header_end = scan_file( project_dir "components/header_end.hpp" ); |  | ||||||
|  |  | ||||||
| 		CodeBody ecode       = gen_ecode     ( project_dir "enums/ECodeTypes.csv", helper_use_c_definition ); | 		CodeBody ecode       = gen_ecode     ( project_dir "enums/ECodeTypes.csv", helper_use_c_definition ); | ||||||
| 		CodeBody eoperator   = gen_eoperator ( project_dir "enums/EOperator.csv",  helper_use_c_definition ); | 		CodeBody eoperator   = gen_eoperator ( project_dir "enums/EOperator.csv",  helper_use_c_definition ); | ||||||
| 		CodeBody especifier  = gen_especifier( project_dir "enums/ESpecifier.csv", helper_use_c_definition ); | 		CodeBody especifier  = gen_especifier( project_dir "enums/ESpecifier.csv", helper_use_c_definition ); | ||||||
|  |  | ||||||
|  | 		// The following pattern will be used throughout parsing: | ||||||
|  | 		// for ( Code entry = parsed_<name_of_file>.begin(); entry != parsed_<name_of_file>.end(); ++ entry ) switch(entry->Type) | ||||||
|  | 		// it provides a concise scope for inspecting a file scope ast and nested code bodies (struct bodies, etc) | ||||||
|  |  | ||||||
| 		CodeBody parsed_types = parse_file( project_dir "components/types.hpp" ); | 		CodeBody parsed_types = parse_file( project_dir "components/types.hpp" ); | ||||||
| 		CodeBody types        = def_body(CT_Global_Body); | 		CodeBody types        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = parsed_types.begin(); entry != parsed_types.end(); ++ entry ) | 		for ( Code entry = parsed_types.begin(); entry != parsed_types.end(); ++ entry ) switch(entry->Type) | ||||||
| 		{ | 		{ | ||||||
| 			switch(entry->Type) | 			case CT_Using: | ||||||
| 			{ | 			{ | ||||||
| 				case CT_Using: | 				CodeUsing using_ver = cast(CodeUsing, entry); | ||||||
| 				{ |  | ||||||
| 					CodeUsing using_ver = cast(CodeUsing, entry); |  | ||||||
|  |  | ||||||
| 					if (using_ver->UnderlyingType->ReturnType) | 				if (using_ver->UnderlyingType->ReturnType) | ||||||
| 					{ | 				{ | ||||||
| 						CodeTypename type       = using_ver->UnderlyingType; | 					CodeTypename type       = using_ver->UnderlyingType; | ||||||
| 						CodeTypedef typedef_ver = parse_typedef(token_fmt( | 					CodeTypedef typedef_ver = parse_typedef(token_fmt( | ||||||
| 							"ReturnType", to_string(type->ReturnType).to_strc() | 						"ReturnType", to_string(type->ReturnType).to_strc() | ||||||
| 						,	"Name"      , using_ver->Name | 					,	"Name"      , using_ver->Name | ||||||
| 						,	"Parameters", to_string(type->Params).to_strc() | 					,	"Parameters", to_string(type->Params).to_strc() | ||||||
| 						,	stringize( | 					,	stringize( | ||||||
| 								typedef <ReturnType>( * <Name>)(<Parameters>); | 							typedef <ReturnType>( * <Name>)(<Parameters>); | ||||||
| 						))); | 					))); | ||||||
| 						types.append(typedef_ver); |  | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 					CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); |  | ||||||
| 					types.append(typedef_ver); | 					types.append(typedef_ver); | ||||||
|  | 					break; | ||||||
| 				} | 				} | ||||||
| 				break; | 				CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); | ||||||
|  | 				types.append(typedef_ver); | ||||||
| 				case CT_Enum: |  | ||||||
| 				{ |  | ||||||
| 					log_fmt("Detected ENUM: %S", entry->Name); |  | ||||||
| 					convert_cpp_enum_to_c(cast(CodeEnum, entry), types); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
|  |  | ||||||
| 				default: |  | ||||||
| 					types.append(entry); |  | ||||||
| 				break; |  | ||||||
| 			} | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Enum: | ||||||
|  | 			{ | ||||||
|  | 				//log_fmt("Detected ENUM: %S", entry->Name); | ||||||
|  | 				convert_cpp_enum_to_c(cast(CodeEnum, entry), types); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			default: | ||||||
|  | 				types.append(entry); | ||||||
|  | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		CodeBody parsed_ast = parse_file( project_dir "components/ast.hpp" ); | 		CodeBody parsed_ast = parse_file( project_dir "components/ast.hpp" ); | ||||||
| 		CodeBody ast        = def_body(CT_Global_Body); | 		CodeBody ast        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = parsed_ast.begin(); entry != parsed_ast.end(); ++ entry ) | 		for ( Code entry = parsed_ast.begin(); entry != parsed_ast.end(); ++ entry ) switch (entry->Type) | ||||||
| 		switch (entry->Type) |  | ||||||
| 		{ | 		{ | ||||||
| 			case CT_Preprocess_If: | 			case CT_Preprocess_If: | ||||||
| 			{ | 			{ | ||||||
| @@ -230,21 +231,22 @@ int gen_main() | |||||||
|  |  | ||||||
| 				s32 constexpr_found = var->Specs ? var->Specs.remove( Spec_Constexpr ) : - 1; | 				s32 constexpr_found = var->Specs ? var->Specs.remove( Spec_Constexpr ) : - 1; | ||||||
| 				if (constexpr_found > -1) { | 				if (constexpr_found > -1) { | ||||||
| 					log_fmt("Found constexpr: %S\n", entry.to_string()); | 					//log_fmt("Found constexpr: %S\n", entry.to_string()); | ||||||
| 					if (var->Name.contains(txt("AST_ArrSpecs_Cap"))) | 					if (var->Name.contains(txt("AST_ArrSpecs_Cap"))) | ||||||
| 					{ | 					{ | ||||||
| 						Code def = untyped_str(txt( | 						Code def = untyped_str(txt( | ||||||
| R"(#define AST_ArrSpecs_Cap       \ | R"(#define AST_ArrSpecs_Cap    \ | ||||||
| (                                 \ | (                              \ | ||||||
|         AST_POD_Size              \ |         AST_POD_Size           \ | ||||||
| 		- sizeof(StringCached)    \ | 		- sizeof(Code)         \ | ||||||
| 		- sizeof(AST*) * 3        \ | 		- sizeof(StringCached) \ | ||||||
| 		- sizeof(Token*)          \ | 		- sizeof(Code) * 2     \ | ||||||
| 		- sizeof(AST*)            \ | 		- sizeof(Token*)       \ | ||||||
| 		- sizeof(CodeType)        \ | 		- sizeof(Code)         \ | ||||||
| 		- sizeof(ModuleFlag)      \ | 		- sizeof(CodeType)     \ | ||||||
| 		- sizeof(u32)             \ | 		- sizeof(ModuleFlag)   \ | ||||||
| )                                 \ | 		- sizeof(u32)          \ | ||||||
|  | )                              \ | ||||||
| / sizeof(Specifier) - 1 | / sizeof(Specifier) - 1 | ||||||
| )" | )" | ||||||
| 						)); | 						)); | ||||||
| @@ -263,6 +265,7 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
| 				ast.append(entry); | 				ast.append(entry); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		CodeBody parsed_code_types = parse_file( project_dir "components/code_types.hpp" ); | 		CodeBody parsed_code_types = parse_file( project_dir "components/code_types.hpp" ); | ||||||
| 		CodeBody code_types        = def_body(CT_Global_Body); | 		CodeBody code_types        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = parsed_code_types.begin(); entry != parsed_code_types.end(); ++ entry ) switch( entry->Type ) | 		for ( Code entry = parsed_code_types.begin(); entry != parsed_code_types.end(); ++ entry ) switch( entry->Type ) | ||||||
| @@ -286,6 +289,7 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
| 				code_types.append(entry); | 				code_types.append(entry); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		CodeBody parsed_ast_types = parse_file( project_dir "components/ast_types.hpp" ); | 		CodeBody parsed_ast_types = parse_file( project_dir "components/ast_types.hpp" ); | ||||||
| 		CodeBody ast_types        = def_body(CT_Global_Body); | 		CodeBody ast_types        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = parsed_ast_types.begin(); entry != parsed_ast_types.end(); ++ entry ) switch( entry->Type ) | 		for ( Code entry = parsed_ast_types.begin(); entry != parsed_ast_types.end(); ++ entry ) switch( entry->Type ) | ||||||
| @@ -302,9 +306,29 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
|  |  | ||||||
| 			case CT_Struct: | 			case CT_Struct: | ||||||
| 			{ | 			{ | ||||||
| 				CodeStruct struct_def = cast(CodeStruct, entry); | 				CodeBody body = cast(CodeBody, entry->Body); | ||||||
| 				CodeTypedef tdef = parse_typedef(token_fmt("name", struct_def->Name, stringize( typedef struct <name> <name>; ))); | 				for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch (body_entry->Type) | ||||||
| 				ast_types.append(struct_def); | 				{ | ||||||
|  | 					case CT_Union: | ||||||
|  | 					{ | ||||||
|  | 						Code union_entry = body_entry->Body->Front; | ||||||
|  | 						if ( body_entry && union_entry->Name.is_equal(txt("_PAD_")) ) | ||||||
|  | 						{ | ||||||
|  | 							char conversion_buf[32] = {}; | ||||||
|  | 							u64_to_str(size_of(AST_Body::_PAD_), conversion_buf, 10); | ||||||
|  |  | ||||||
|  | 							StrC arr_exp  = union_entry->ValueType->ArrExpr->Content; | ||||||
|  | 							StrC cpp_size = to_strc_from_c_str(conversion_buf); | ||||||
|  | 							union_entry->ValueType->ArrExpr = untyped_str( cpp_size ); | ||||||
|  | 							union_entry->InlineCmt          = untyped_str(token_fmt("arr_exp", arr_exp, | ||||||
|  | 								"// Had to hardcode _PAD_ because (<arr_exp>) was 67 bytes in C\n" | ||||||
|  | 								"// instead of 64 like C++'s AST_Body::_PAD_\n" | ||||||
|  | 							)); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				CodeTypedef tdef = parse_typedef(token_fmt("name", entry->Name, stringize( typedef struct <name> <name>; ))); | ||||||
|  | 				ast_types.append(entry); | ||||||
| 				ast_types.append(tdef); | 				ast_types.append(tdef); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| @@ -313,6 +337,73 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
| 				ast_types.append(entry); | 				ast_types.append(entry); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		CodeBody parsed_interface = parse_file( project_dir "components/interface.hpp" ); | ||||||
|  | 		CodeBody interface        = def_body(CT_Global_Body); | ||||||
|  | 		for ( Code entry = parsed_interface.begin(); entry != parsed_interface.end(); ++ entry ) switch( entry->Type ) | ||||||
|  | 		{ | ||||||
|  | 			case CT_Preprocess_IfDef: | ||||||
|  | 			{ | ||||||
|  | 				b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_code_types, code_types ); | ||||||
|  | 				if (found) break; | ||||||
|  |  | ||||||
|  | 				interface.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Function_Fwd: | ||||||
|  | 			case CT_Function: | ||||||
|  | 			{ | ||||||
|  | 				CodeFn fn = cast(CodeFn, entry); | ||||||
|  | 				Code prev = entry->Prev; | ||||||
|  | 				if (prev && prev->Name.is_equal(entry->Name)) { | ||||||
|  | 					String postfix_arr = String::fmt_buf(GlobalAllocator, "%SC_arr", entry->Name); | ||||||
|  | 					entry->Name = get_cached_string(postfix_arr.to_strc()); | ||||||
|  | 					postfix_arr.free(); | ||||||
|  | 				} | ||||||
|  | 				interface.append(fn); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Struct: | ||||||
|  | 			{ | ||||||
|  | 				CodeTypedef tdef = parse_typedef(token_fmt("name", entry->Name, stringize( typedef struct <name> <name>; ))); | ||||||
|  | 				interface.append(entry); | ||||||
|  | 				interface.append(tdef); | ||||||
|  | 				interface.append(fmt_newline); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			default: | ||||||
|  | 				interface.append(entry); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		s32 idx = 0; | ||||||
|  | 		CodeBody parsed_header_end = parse_file( project_dir "components/header_end.hpp" ); | ||||||
|  | 		CodeBody header_end        = def_body(CT_Global_Body); | ||||||
|  | 		for ( Code entry = parsed_header_end.begin(); entry != parsed_header_end.end(); ++ entry, ++ idx ) switch( entry->Type ) | ||||||
|  | 		{ | ||||||
|  | 			case CT_Variable: | ||||||
|  | 			{ | ||||||
|  | 				CodeVar var = cast(CodeVar, entry); | ||||||
|  | 				if (var->Specs) | ||||||
|  | 				{ | ||||||
|  | 					s32 constexpr_found = var->Specs.remove( Spec_Constexpr ); | ||||||
|  | 					if (constexpr_found > -1) { | ||||||
|  | 						CodeDefine define = def_define(entry->Name, entry->Value->Content); | ||||||
|  | 						header_end.append(define); | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				header_end.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			default: | ||||||
|  | 				header_end.append(entry); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| #pragma endregion Scan, Parse, and Generate Components | #pragma endregion Scan, Parse, and Generate Components | ||||||
|  |  | ||||||
| #pragma region Scan, Parse, and Generate Dependencies | #pragma region Scan, Parse, and Generate Dependencies | ||||||
| @@ -326,163 +417,157 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
|  |  | ||||||
| 		CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); | 		CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); | ||||||
| 		CodeBody memory        = def_body(CT_Global_Body); | 		CodeBody memory        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry ) | 		for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry ) switch (entry->Type) | ||||||
| 		{ | 		{ | ||||||
| 			switch (entry->Type) | 			case CT_Using: | ||||||
| 			{ | 			{ | ||||||
| 				case CT_Using: | 				log_fmt("REPLACE THIS MANUALLY: %SC\n", entry->Name); | ||||||
| 				{ | 				CodeUsing   using_ver   = cast(CodeUsing, entry); | ||||||
| 					log_fmt("REPLACE THIS MANUALLY: %SC\n", entry->Name); | 				CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); | ||||||
| 					CodeUsing   using_ver   = cast(CodeUsing, entry); |  | ||||||
| 					CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); |  | ||||||
|  |  | ||||||
| 					memory.append(typedef_ver); | 				memory.append(typedef_ver); | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Function_Fwd: |  | ||||||
| 				{ |  | ||||||
| 					CodeFn fn = cast(CodeFn, entry); |  | ||||||
| 					// for ( StrC id : to_rename ) if (fn->Name.is_equal(id)) { |  | ||||||
| 					// 	rename_function_to_unique_symbol(fn); |  | ||||||
| 					// } |  | ||||||
| 					memory.append(fn); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Function: |  | ||||||
| 				{ |  | ||||||
| 					CodeFn fn = cast(CodeFn, entry); |  | ||||||
| 					if (fn->Specs) { |  | ||||||
| 						s32 constexpr_found = fn->Specs.remove( Spec_Constexpr ); |  | ||||||
| 						if (constexpr_found > -1) { |  | ||||||
| 							log_fmt("Found constexpr: %S\n", entry.to_string()); |  | ||||||
| 							fn->Specs.append(Spec_Inline); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 					memory.append(fn); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Template: |  | ||||||
| 				{ |  | ||||||
| 					CodeTemplate tmpl = cast(CodeTemplate, entry); |  | ||||||
| 					if ( tmpl->Declaration->Name.contains(txt("swap"))) |  | ||||||
| 					{ |  | ||||||
| 						CodeBody macro_swap = parse_global_body( txt(R"( |  | ||||||
| #define swap( a, b )              \ |  | ||||||
| 	do                            \ |  | ||||||
| 	{                             \ |  | ||||||
| 		typeof( a ) temp = ( a ); \ |  | ||||||
| 		( a )            = ( b ); \ |  | ||||||
| 		( b )            = temp;  \ |  | ||||||
| 	} while ( 0 ) |  | ||||||
| )" |  | ||||||
| 						)); |  | ||||||
| 						memory.append(macro_swap); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Enum: |  | ||||||
| 				{ |  | ||||||
| 					convert_cpp_enum_to_c(cast(CodeEnum, entry), memory); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Struct_Fwd: |  | ||||||
| 				{ |  | ||||||
| 					CodeTypedef tdef = parse_typedef(token_fmt("name", entry->Name, stringize( typedef struct <name> <name>; ))); |  | ||||||
| 					memory.append(entry); |  | ||||||
| 					memory.append(tdef); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Class: |  | ||||||
| 				case CT_Struct: |  | ||||||
| 				{ |  | ||||||
| 					CodeBody body     = cast(CodeBody, entry->Body); |  | ||||||
| 					CodeBody new_body = def_body( entry->Body->Type ); |  | ||||||
| 					for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch |  | ||||||
| 					(body_entry->Type) { |  | ||||||
| 						case CT_Preprocess_If: |  | ||||||
| 						{ |  | ||||||
| 							b32 found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP"), body_entry, body, new_body ); |  | ||||||
| 							if (found) break; |  | ||||||
| 						} |  | ||||||
| 						break; |  | ||||||
|  |  | ||||||
| 						default: |  | ||||||
| 							new_body.append(body_entry); |  | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 					entry->Body = new_body; |  | ||||||
|  |  | ||||||
| 					CodeTypedef tdef = parse_typedef(token_fmt("name", entry->Name, stringize( typedef struct <name> <name>; ))); |  | ||||||
| 					memory.append(entry); |  | ||||||
| 					memory.append(tdef); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Preprocess_If: |  | ||||||
| 				{ |  | ||||||
| 					b32 found = ignore_preprocess_cond_block(txt("! GEN_C_LIKE_CPP"), entry, parsed_memory, memory ); |  | ||||||
| 					if (found) break; |  | ||||||
|  |  | ||||||
| 					memory.append(entry); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Preprocess_IfDef: |  | ||||||
| 				{ |  | ||||||
| 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_memory, memory ); |  | ||||||
| 					if (found) break; |  | ||||||
|  |  | ||||||
| 					memory.append(entry); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Preprocess_Pragma: |  | ||||||
| 				{ |  | ||||||
| 					CodePragma pragma = cast(CodePragma, entry); |  | ||||||
| 					// if (pragma->Content.starts_with(txt("region Memory"))) { |  | ||||||
| 					// 	memory.append(generic_test); |  | ||||||
| 					// 	break; |  | ||||||
| 					// } |  | ||||||
|  |  | ||||||
| 					b32 found = swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory); |  | ||||||
| 					if (found) break; |  | ||||||
|  |  | ||||||
| 					memory.append(entry); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				default: { |  | ||||||
| 					memory.append(entry); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 			} | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Function_Fwd: | ||||||
|  | 			{ | ||||||
|  | 				CodeFn fn = cast(CodeFn, entry); | ||||||
|  | 				// for ( StrC id : to_rename ) if (fn->Name.is_equal(id)) { | ||||||
|  | 				// 	rename_function_to_unique_symbol(fn); | ||||||
|  | 				// } | ||||||
|  | 				memory.append(fn); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Function: | ||||||
|  | 			{ | ||||||
|  | 				CodeFn fn = cast(CodeFn, entry); | ||||||
|  | 				if (fn->Specs) { | ||||||
|  | 					s32 constexpr_found = fn->Specs.remove( Spec_Constexpr ); | ||||||
|  | 					if (constexpr_found > -1) { | ||||||
|  | 						//log_fmt("Found constexpr: %S\n", entry.to_string()); | ||||||
|  | 						fn->Specs.append(Spec_Inline); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				memory.append(fn); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Template: | ||||||
|  | 			{ | ||||||
|  | 				CodeTemplate tmpl = cast(CodeTemplate, entry); | ||||||
|  | 				if ( tmpl->Declaration->Name.contains(txt("swap"))) | ||||||
|  | 				{ | ||||||
|  | 					CodeBody macro_swap = parse_global_body( txt(R"( | ||||||
|  | #define swap( a, b )              \ | ||||||
|  | do                            \ | ||||||
|  | {                             \ | ||||||
|  | 	typeof( a ) temp = ( a ); \ | ||||||
|  | 	( a )            = ( b ); \ | ||||||
|  | 	( b )            = temp;  \ | ||||||
|  | } while ( 0 ) | ||||||
|  | )" | ||||||
|  | 					)); | ||||||
|  | 					memory.append(macro_swap); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Enum: | ||||||
|  | 			{ | ||||||
|  | 				convert_cpp_enum_to_c(cast(CodeEnum, entry), memory); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Struct_Fwd: | ||||||
|  | 			{ | ||||||
|  | 				CodeTypedef tdef = parse_typedef(token_fmt("name", entry->Name, stringize( typedef struct <name> <name>; ))); | ||||||
|  | 				memory.append(entry); | ||||||
|  | 				memory.append(tdef); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Class: | ||||||
|  | 			case CT_Struct: | ||||||
|  | 			{ | ||||||
|  | 				CodeBody body     = cast(CodeBody, entry->Body); | ||||||
|  | 				CodeBody new_body = def_body( entry->Body->Type ); | ||||||
|  | 				for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch | ||||||
|  | 				(body_entry->Type) { | ||||||
|  | 					case CT_Preprocess_If: | ||||||
|  | 					{ | ||||||
|  | 						b32 found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP"), body_entry, body, new_body ); | ||||||
|  | 						if (found) break; | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 					default: | ||||||
|  | 						new_body.append(body_entry); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 				entry->Body = new_body; | ||||||
|  |  | ||||||
|  | 				CodeTypedef tdef = parse_typedef(token_fmt("name", entry->Name, stringize( typedef struct <name> <name>; ))); | ||||||
|  | 				memory.append(entry); | ||||||
|  | 				memory.append(tdef); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Preprocess_If: | ||||||
|  | 			{ | ||||||
|  | 				b32 found = ignore_preprocess_cond_block(txt("! GEN_C_LIKE_CPP"), entry, parsed_memory, memory ); | ||||||
|  | 				if (found) break; | ||||||
|  |  | ||||||
|  | 				memory.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Preprocess_IfDef: | ||||||
|  | 			{ | ||||||
|  | 				b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_memory, memory ); | ||||||
|  | 				if (found) break; | ||||||
|  |  | ||||||
|  | 				memory.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Preprocess_Pragma: | ||||||
|  | 			{ | ||||||
|  | 				CodePragma pragma = cast(CodePragma, entry); | ||||||
|  | 				// if (pragma->Content.starts_with(txt("region Memory"))) { | ||||||
|  | 				// 	memory.append(generic_test); | ||||||
|  | 				// 	break; | ||||||
|  | 				// } | ||||||
|  |  | ||||||
|  | 				b32 found = swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory); | ||||||
|  | 				if (found) break; | ||||||
|  |  | ||||||
|  | 				memory.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			default: { | ||||||
|  | 				memory.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		CodeBody printing_parsed = parse_file( project_dir "dependencies/printing.hpp" ); | 		CodeBody printing_parsed = parse_file( project_dir "dependencies/printing.hpp" ); | ||||||
| 		CodeBody printing        = def_body(CT_Global_Body); | 		CodeBody printing        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = printing_parsed.begin(); entry != printing_parsed.end(); ++ entry ) | 		for ( Code entry = printing_parsed.begin(); entry != printing_parsed.end(); ++ entry ) switch (entry->Type) | ||||||
| 		{ | 		{ | ||||||
| 			switch (entry->Type) | 			case CT_Preprocess_IfDef: | ||||||
| 			{ | 			{ | ||||||
| 				case CT_Preprocess_IfDef: | 				b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, printing_parsed, printing ); | ||||||
| 				{ | 				if (found) break; | ||||||
| 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, printing_parsed, printing ); |  | ||||||
| 					if (found) break; |  | ||||||
|  |  | ||||||
| 					printing.append(entry); | 				printing.append(entry); | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				case CT_Variable: |  | ||||||
| 				{ |  | ||||||
| 					if ( strc_contains(entry->Name, txt("Msg_Invalid_Value"))) |  | ||||||
| 					{ |  | ||||||
| 						CodeDefine define = def_define(entry->Name, entry->Value->Content); |  | ||||||
| 						printing.append(define); |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 					printing.append(entry); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				default: |  | ||||||
| 					printing.append(entry); |  | ||||||
| 				break; |  | ||||||
| 			} | 			} | ||||||
|  | 			break; | ||||||
|  | 			case CT_Variable: | ||||||
|  | 			{ | ||||||
|  | 				if ( strc_contains(entry->Name, txt("Msg_Invalid_Value"))) | ||||||
|  | 				{ | ||||||
|  | 					CodeDefine define = def_define(entry->Name, entry->Value->Content); | ||||||
|  | 					printing.append(define); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				printing.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			default: | ||||||
|  | 				printing.append(entry); | ||||||
|  | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" ); | 		CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" ); | ||||||
| @@ -520,7 +605,7 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
|  |  | ||||||
| 			case CT_Preprocess_IfNotDef: | 			case CT_Preprocess_IfNotDef: | ||||||
| 			{ | 			{ | ||||||
| 				log_fmt("\nIFNDEF: %SC\n", entry->Content); | 				//log_fmt("\nIFNDEF: %SC\n", entry->Content); | ||||||
| 				strings.append(entry); | 				strings.append(entry); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| @@ -589,73 +674,73 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
|  |  | ||||||
| 		CodeBody parsed_filesystem = parse_file( project_dir "dependencies/filesystem.hpp" ); | 		CodeBody parsed_filesystem = parse_file( project_dir "dependencies/filesystem.hpp" ); | ||||||
| 		CodeBody filesystem        = def_body(CT_Global_Body); | 		CodeBody filesystem        = def_body(CT_Global_Body); | ||||||
| 		for ( Code entry = parsed_filesystem.begin(); entry != parsed_filesystem.end(); ++ entry ) | 		for ( Code entry = parsed_filesystem.begin(); entry != parsed_filesystem.end(); ++ entry ) switch (entry->Type) | ||||||
| 		{ | 		{ | ||||||
| 			switch (entry->Type) | 			case CT_Preprocess_IfDef: | ||||||
| 			{ | 			{ | ||||||
| 				case CT_Preprocess_IfDef: | 				b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_filesystem, filesystem ); | ||||||
| 				{ | 				if (found) break; | ||||||
| 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_filesystem, filesystem ); |  | ||||||
| 					if (found) break; |  | ||||||
|  |  | ||||||
| 					filesystem.append(entry); | 				filesystem.append(entry); | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
|  |  | ||||||
| 				case CT_Enum: |  | ||||||
| 				{ |  | ||||||
| 					if (entry->Name.is_equal(txt("FileOperations"))) |  | ||||||
| 						continue; |  | ||||||
| 					convert_cpp_enum_to_c(cast(CodeEnum, entry), filesystem); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
|  |  | ||||||
| 				case CT_Enum_Fwd: |  | ||||||
| 				case CT_Struct_Fwd: |  | ||||||
| 				case CT_Struct: |  | ||||||
| 				case CT_Union: |  | ||||||
| 				case CT_Union_Fwd: |  | ||||||
| 				{ |  | ||||||
| 					StrC type_str      = codetype_to_keyword_str(entry->Type); |  | ||||||
| 					StrC formated_tmpl = token_fmt_impl( 3, |  | ||||||
| 						"type", type_str |  | ||||||
| 					,	"name", entry->Name, |  | ||||||
| 					stringize( |  | ||||||
| 						typedef <type> <name> <name>; |  | ||||||
| 					)); |  | ||||||
| 					CodeTypedef tdef = parse_typedef(formated_tmpl); |  | ||||||
| 					filesystem.append(entry); |  | ||||||
| 					filesystem.append(tdef); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
|  |  | ||||||
| 				case CT_Variable: |  | ||||||
| 				{ |  | ||||||
| 					CodeVar var = cast(CodeVar, entry); |  | ||||||
| 					if (var->Specs.has(Spec_Constexpr) > -1) |  | ||||||
| 					{ |  | ||||||
| 						CodeDefine define = def_define(entry->Name, entry->Value->Content); |  | ||||||
| 						filesystem.append(define); |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 					//if ( strc_contains(entry->Name, txt("Msg_Invalid_Value"))) |  | ||||||
| 					//{ |  | ||||||
| 					//	CodeDefine define = def_define(entry->Name, entry->Value->Content); |  | ||||||
| 					//	printing.append(define); |  | ||||||
| 					//	continue; |  | ||||||
| 					//} |  | ||||||
| 					filesystem.append(entry); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 				default: |  | ||||||
| 					filesystem.append(entry); |  | ||||||
| 				break; |  | ||||||
| 			} | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Enum: | ||||||
|  | 			{ | ||||||
|  | 				if (entry->Name.is_equal(txt("FileOperations"))) | ||||||
|  | 					continue; | ||||||
|  | 				convert_cpp_enum_to_c(cast(CodeEnum, entry), filesystem); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Enum_Fwd: | ||||||
|  | 			case CT_Struct_Fwd: | ||||||
|  | 			case CT_Struct: | ||||||
|  | 			case CT_Union: | ||||||
|  | 			case CT_Union_Fwd: | ||||||
|  | 			{ | ||||||
|  | 				StrC type_str      = codetype_to_keyword_str(entry->Type); | ||||||
|  | 				StrC formated_tmpl = token_fmt_impl( 3, | ||||||
|  | 					"type", type_str | ||||||
|  | 				,	"name", entry->Name, | ||||||
|  | 				stringize( | ||||||
|  | 					typedef <type> <name> <name>; | ||||||
|  | 				)); | ||||||
|  | 				CodeTypedef tdef = parse_typedef(formated_tmpl); | ||||||
|  | 				filesystem.append(entry); | ||||||
|  | 				filesystem.append(tdef); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Variable: | ||||||
|  | 			{ | ||||||
|  | 				CodeVar var = cast(CodeVar, entry); | ||||||
|  | 				if (var->Specs.has(Spec_Constexpr) > -1) | ||||||
|  | 				{ | ||||||
|  | 					CodeDefine define = def_define(entry->Name, entry->Value->Content); | ||||||
|  | 					filesystem.append(define); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				//if ( strc_contains(entry->Name, txt("Msg_Invalid_Value"))) | ||||||
|  | 				//{ | ||||||
|  | 				//	CodeDefine define = def_define(entry->Name, entry->Value->Content); | ||||||
|  | 				//	printing.append(define); | ||||||
|  | 				//	continue; | ||||||
|  | 				//} | ||||||
|  | 				filesystem.append(entry); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			default: | ||||||
|  | 				filesystem.append(entry); | ||||||
|  | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		CodeBody array_string_cached = gen_array(txt("StringCached"), txt("Array_StringCached")); | ||||||
|  |  | ||||||
| 		CodeBody containers = def_body(CT_Global_Body); | 		CodeBody containers = def_body(CT_Global_Body); | ||||||
| 		{ | 		{ | ||||||
| 			CodeBody array_ssize = gen_array(txt("ssize"), txt("Array_ssize")); | 			CodeBody array_ssize = gen_array(txt("ssize"), txt("Array_ssize")); | ||||||
|  | 			CodeBody array_u8    = gen_array(txt("u8"),    txt("Array_u8")); | ||||||
|  |  | ||||||
| 			containers.append( def_pragma(code(region Containers))); | 			containers.append( def_pragma(code(region Containers))); | ||||||
|  |  | ||||||
| @@ -667,6 +752,7 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
| 			containers.append( gen_hashtable_generic_selection_interface()); | 			containers.append( gen_hashtable_generic_selection_interface()); | ||||||
|  |  | ||||||
| 			containers.append(array_ssize); | 			containers.append(array_ssize); | ||||||
|  | 			containers.append(array_u8); | ||||||
|  |  | ||||||
| 			containers.append( def_pragma(code(endregion Containers))); | 			containers.append( def_pragma(code(endregion Containers))); | ||||||
| 			containers.append(fmt_newline); | 			containers.append(fmt_newline); | ||||||
| @@ -684,6 +770,7 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
| 		header.print( dump_to_scratch_and_retireve(memory) ); | 		header.print( dump_to_scratch_and_retireve(memory) ); | ||||||
| 		header.print( dump_to_scratch_and_retireve(printing)); | 		header.print( dump_to_scratch_and_retireve(printing)); | ||||||
| 		header.print( string_ops ); | 		header.print( string_ops ); | ||||||
|  | 		header.print(fmt_newline); | ||||||
| 		header.print( dump_to_scratch_and_retireve(containers)); | 		header.print( dump_to_scratch_and_retireve(containers)); | ||||||
| 		header.print( hashing ); | 		header.print( hashing ); | ||||||
| 		header.print( dump_to_scratch_and_retireve(strings)); | 		header.print( dump_to_scratch_and_retireve(strings)); | ||||||
| @@ -695,7 +782,6 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
|  |  | ||||||
| 		header.print(fmt_newline); | 		header.print(fmt_newline); | ||||||
|  |  | ||||||
| #if 1 |  | ||||||
| #pragma region region Print Components | #pragma region region Print Components | ||||||
| 		header.print_fmt( "GEN_NS_BEGIN\n" ); | 		header.print_fmt( "GEN_NS_BEGIN\n" ); | ||||||
| 		header.print_fmt( "GEN_API_C_BEGIN\n\n" ); | 		header.print_fmt( "GEN_API_C_BEGIN\n\n" ); | ||||||
| @@ -716,17 +802,87 @@ R"(#define AST_ArrSpecs_Cap       \ | |||||||
| 		header.print( dump_to_scratch_and_retireve(ast_types) ); | 		header.print( dump_to_scratch_and_retireve(ast_types) ); | ||||||
| 		header.print_fmt("\n#pragma endregion AST\n"); | 		header.print_fmt("\n#pragma endregion AST\n"); | ||||||
|  |  | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(interface) ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt("#pragma region Inlines\n"); | ||||||
|  | 		header.print( inlines ); | ||||||
|  | 		header.print_fmt("#pragma endregion Inlines\n"); | ||||||
|  |  | ||||||
|  | 		header.print(fmt_newline); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(array_string_cached)); | ||||||
|  | 		header.print(fmt_newline); | ||||||
|  |  | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(header_end) ); | ||||||
|  |  | ||||||
| 		header.print_fmt( "\nGEN_API_C_END\n" ); | 		header.print_fmt( "\nGEN_API_C_END\n" ); | ||||||
|  |  | ||||||
| 		header.print_fmt( "GEN_NS_END\n\n" ); | 		header.print_fmt( "GEN_NS_END\n\n" ); | ||||||
| #pragma endregion Print Compoennts | #pragma endregion Print Compoennts | ||||||
| #endif | 	} | ||||||
|  |  | ||||||
|  | 	// Implementation | ||||||
|  | 	{ | ||||||
|  | 		header.print_fmt( implementation_guard_start ); | ||||||
|  |  | ||||||
|  | #pragma region Scan, Parse, and Generate Dependencies | ||||||
|  | 			Code impl_start = scan_file( project_dir "dependencies/src_start.cpp" ); | ||||||
|  | 			Code debug      = scan_file( project_dir "dependencies/debug.cpp" ); | ||||||
|  | 			Code string_ops = scan_file( project_dir "dependencies/string_ops.cpp" ); | ||||||
|  | 			Code printing   = scan_file( project_dir "dependencies/printing.cpp" ); | ||||||
|  | 			Code memory     = scan_file( project_dir "dependencies/memory.cpp" ); | ||||||
|  | 			Code hashing    = scan_file( project_dir "dependencies/hashing.cpp" ); | ||||||
|  | 			Code strings    = scan_file( project_dir "dependencies/strings.cpp" ); | ||||||
|  | 			Code filesystem = scan_file( project_dir "dependencies/filesystem.cpp" ); | ||||||
|  | 			Code timing     = scan_file( project_dir "dependencies/timing.cpp" ); | ||||||
|  | #pragma region Scan, Parse, and Generate Dependencies | ||||||
|  |  | ||||||
|  | #pragma region Scan, Parse, and Generate Components | ||||||
|  | 		Code static_data 	   = scan_file( project_dir "components/static_data.cpp" ); | ||||||
|  | 		Code ast_case_macros   = scan_file( project_dir "components/ast_case_macros.cpp" ); | ||||||
|  | 		Code ast               = scan_file( project_dir "components/ast.cpp" ); | ||||||
|  | 		Code code              = scan_file( project_dir "components/code_serialization.cpp" ); | ||||||
|  | 		Code interface         = scan_file( project_dir "components/interface.cpp" ); | ||||||
|  | 		Code upfront           = scan_file( project_dir "components/interface.upfront.cpp" ); | ||||||
|  | 		Code lexer             = scan_file( project_dir "components/lexer.cpp" ); | ||||||
|  | 		Code parser            = scan_file( project_dir "components/parser.cpp" ); | ||||||
|  | 		Code parsing_interface = scan_file( project_dir "components/interface.parsing.cpp" ); | ||||||
|  | 		Code untyped           = scan_file( project_dir "components/interface.untyped.cpp" ); | ||||||
|  | #pragma endregion Scan, Parse, and Generate Components | ||||||
|  |  | ||||||
|  | #pragma region Print Dependencies | ||||||
|  | 		header.print_fmt( roll_own_dependencies_guard_start ); | ||||||
|  | 		header.print_fmt( "GEN_NS_BEGIN\n\n"); | ||||||
|  |  | ||||||
|  | 		header.print( impl_start ); | ||||||
|  | 		header.print( debug ); | ||||||
|  | 		header.print( string_ops ); | ||||||
|  | 		header.print( printing ); | ||||||
|  | 		header.print( memory ); | ||||||
|  | 		header.print( hashing ); | ||||||
|  | 		header.print( strings ); | ||||||
|  | 		header.print( filesystem ); | ||||||
|  | 		header.print( timing ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "\n#pragma region Parsing\n" ); | ||||||
|  | 		header.print( scan_file( project_dir "dependencies/parsing.cpp" ) ); | ||||||
|  | 		header.print_fmt( "#pragma endregion Parsing\n\n" ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "GEN_NS_END\n"); | ||||||
|  | 		header.print_fmt( roll_own_dependencies_guard_end ); | ||||||
|  |  | ||||||
|  | #pragma endregion Print Dependencies | ||||||
|  |  | ||||||
|  | #pragma region Print Components | ||||||
|  |  | ||||||
|  | #pragma endregion Print Components | ||||||
|  |  | ||||||
|  | 		header.print_fmt( implementation_guard_end ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	header.print( pop_ignores ); | 	header.print( pop_ignores ); | ||||||
| 	header.write(); | 	header.write(); | ||||||
|  |  | ||||||
| 	// format_file( "gen/gen.h" ); | 	//k | ||||||
|  |  | ||||||
| 	gen::deinit(); | 	gen::deinit(); | ||||||
| 	return 0; | 	return 0; | ||||||
|   | |||||||
| @@ -21,8 +21,9 @@ CodeBody gen_array_base() | |||||||
|  |  | ||||||
| 	Code grow_formula = untyped_str( txt( "#define array_grow_formula( value ) ( 2 * value + 8 )\n" )); | 	Code grow_formula = untyped_str( txt( "#define array_grow_formula( value ) ( 2 * value + 8 )\n" )); | ||||||
| 	Code get_header   = untyped_str( txt( "#define array_get_header( self ) ( (ArrayHeader*)( self ) - 1)\n" )); | 	Code get_header   = untyped_str( txt( "#define array_get_header( self ) ( (ArrayHeader*)( self ) - 1)\n" )); | ||||||
|  | 	Code type_define  = untyped_str( txt( "#define Array(Type) Array_##Type\n")); | ||||||
|  |  | ||||||
| 	return def_global_body( args( fmt_newline, td_header, header, grow_formula, get_header, fmt_newline ) ); | 	return def_global_body( args( fmt_newline, td_header, header, type_define, grow_formula, get_header, fmt_newline ) ); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| CodeBody gen_array( StrC type, StrC array_name ) | CodeBody gen_array( StrC type, StrC array_name ) | ||||||
| @@ -68,7 +69,7 @@ CodeBody gen_array( StrC type, StrC array_name ) | |||||||
| 		<array_type> <fn>_init( AllocatorInfo allocator ) | 		<array_type> <fn>_init( AllocatorInfo allocator ) | ||||||
| 		{ | 		{ | ||||||
| 			size_t initial_size = array_grow_formula(0); | 			size_t initial_size = array_grow_formula(0); | ||||||
| 			return array_init_reserve( <array_type>, allocator, initial_size ); | 			return array_init_reserve( <type>, allocator, initial_size ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		inline | 		inline | ||||||
| @@ -362,24 +363,24 @@ CodeBody gen_array( StrC type, StrC array_name ) | |||||||
| 	++ Array_DefinitionCounter; | 	++ Array_DefinitionCounter; | ||||||
| 	StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", Array_DefinitionCounter).to_strc(); | 	StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", Array_DefinitionCounter).to_strc(); | ||||||
|  |  | ||||||
| 	Code generic_interface_slot = untyped_str(token_fmt( "type_delimiter", (StrC)array_type, "slot", (StrC)slot_str, | 	Code generic_interface_slot = untyped_str(token_fmt( "type", type, "array_type", (StrC)array_type, "slot", (StrC)slot_str, | ||||||
| R"(#define GENERIC_SLOT_<slot>__array_init         <type_delimiter>,  <type_delimiter>_init | R"(#define GENERIC_SLOT_<slot>__array_init         <type>,        <array_type>_init | ||||||
| #define GENERIC_SLOT_<slot>__array_init_reserve    <type_delimiter>,  <type_delimiter>_init_reserve | #define GENERIC_SLOT_<slot>__array_init_reserve    <type>,        <array_type>_init_reserve | ||||||
| #define GENERIC_SLOT_<slot>__array_append          <type_delimiter>,  <type_delimiter>_append | #define GENERIC_SLOT_<slot>__array_append          <array_type>,  <array_type>_append | ||||||
| #define GENERIC_SLOT_<slot>__array_append_items    <type_delimiter>,  <type_delimiter>_append_items | #define GENERIC_SLOT_<slot>__array_append_items    <array_type>,  <array_type>_append_items | ||||||
| #define GENERIC_SLOT_<slot>__array_append_at       <type_delimiter>,  <type_delimiter>_append_at | #define GENERIC_SLOT_<slot>__array_append_at       <array_type>,  <array_type>_append_at | ||||||
| #define GENERIC_SLOT_<slot>__array_append_items_at <type_delimiter>,  <type_delimiter>_append_items_at | #define GENERIC_SLOT_<slot>__array_append_items_at <array_type>,  <array_type>_append_items_at | ||||||
| #define GENERIC_SLOT_<slot>__array_back            <type_delimiter>,  <type_delimiter>_back | #define GENERIC_SLOT_<slot>__array_back            <array_type>,  <array_type>_back | ||||||
| #define GENERIC_SLOT_<slot>__array_clear           <type_delimiter>,  <type_delimiter>_clear | #define GENERIC_SLOT_<slot>__array_clear           <array_type>,  <array_type>_clear | ||||||
| #define GENERIC_SLOT_<slot>__array_fill            <type_delimiter>,  <type_delimiter>_fill | #define GENERIC_SLOT_<slot>__array_fill            <array_type>,  <array_type>_fill | ||||||
| #define GENERIC_SLOT_<slot>__array_free            <type_delimiter>,  <type_delimiter>_free | #define GENERIC_SLOT_<slot>__array_free            <array_type>,  <array_type>_free | ||||||
| #define GENERIC_SLOT_<slot>__array_grow            <type_delimiter>*, <type_delimiter>_grow | #define GENERIC_SLOT_<slot>__array_grow            <array_type>*, <array_type>_grow | ||||||
| #define GENERIC_SLOT_<slot>__array_num             <type_delimiter>,  <type_delimiter>_num | #define GENERIC_SLOT_<slot>__array_num             <array_type>,  <array_type>_num | ||||||
| #define GENERIC_SLOT_<slot>__array_pop             <type_delimiter>,  <type_delimiter>_pop | #define GENERIC_SLOT_<slot>__array_pop             <array_type>,  <array_type>_pop | ||||||
| #define GENERIC_SLOT_<slot>__array_remove_at       <type_delimiter>,  <type_delimiter>_remove_at | #define GENERIC_SLOT_<slot>__array_remove_at       <array_type>,  <array_type>_remove_at | ||||||
| #define GENERIC_SLOT_<slot>__array_reserve         <type_delimiter>,  <type_delimiter>_reserve | #define GENERIC_SLOT_<slot>__array_reserve         <array_type>,  <array_type>_reserve | ||||||
| #define GENERIC_SLOT_<slot>__array_resize          <type_delimiter>,  <type_delimiter>_resize | #define GENERIC_SLOT_<slot>__array_resize          <array_type>,  <array_type>_resize | ||||||
| #define GENERIC_SLOT_<slot>__array_set_capacity    <type_delimiter>*, <type_delimiter>_set_capacity | #define GENERIC_SLOT_<slot>__array_set_capacity    <array_type>*, <array_type>_set_capacity | ||||||
| )" | )" | ||||||
| 	)); | 	)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -109,19 +109,19 @@ CodeBody gen_hashtable( StrC type, StrC hashtable_name ) | |||||||
|  |  | ||||||
| 		<tbl_type> <fn>init( AllocatorInfo allocator ) | 		<tbl_type> <fn>init( AllocatorInfo allocator ) | ||||||
| 		{ | 		{ | ||||||
| 			<tbl_type> result = hashtable_init_reserve(<tbl_type>, allocator, 8); | 			<tbl_type> result = hashtable_init_reserve(<type>, allocator, 8); | ||||||
| 			return result; | 			return result; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		<tbl_type> <fn>_init_reserve( AllocatorInfo allocator, ssize num ) | 		<tbl_type> <fn>_init_reserve( AllocatorInfo allocator, ssize num ) | ||||||
| 		{ | 		{ | ||||||
| 			<tbl_type> result = { NULL, NULL }; | 			<tbl_type> result = { NULL, NULL }; | ||||||
| 			result.Hashes  = array_init_reserve(Array_ssize, allocator, num ); | 			result.Hashes  = array_init_reserve(ssize, allocator, num ); | ||||||
| 			array_get_header(result.Hashes)->Num = num; | 			array_get_header(result.Hashes)->Num = num; | ||||||
| 			array_resize(result.Hashes, num); | 			array_resize(result.Hashes, num); | ||||||
| 			array_fill(result.Hashes, 0, num, -1); | 			array_fill(result.Hashes, 0, num, -1); | ||||||
|  |  | ||||||
| 			result.Entries = array_init_reserve(<array_entry>, allocator, num ); | 			result.Entries = array_init_reserve(<entry_type>, allocator, num ); | ||||||
| 			return result; | 			return result; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -199,7 +199,7 @@ CodeBody gen_hashtable( StrC type, StrC hashtable_name ) | |||||||
| 			ArrayHeader* old_hash_header    = array_get_header( self->Hashes ); | 			ArrayHeader* old_hash_header    = array_get_header( self->Hashes ); | ||||||
| 			ArrayHeader* old_entries_header = array_get_header( self->Entries ); | 			ArrayHeader* old_entries_header = array_get_header( self->Entries ); | ||||||
|  |  | ||||||
| 			<tbl_type> new_tbl = hashtable_init_reserve( <tbl_type>, old_hash_header->Allocator, old_hash_header->Num ); | 			<tbl_type> new_tbl = hashtable_init_reserve( <type>, old_hash_header->Allocator, old_hash_header->Num ); | ||||||
|  |  | ||||||
| 			ArrayHeader* new_hash_header = array_get_header( new_tbl.Hashes ); | 			ArrayHeader* new_hash_header = array_get_header( new_tbl.Hashes ); | ||||||
|  |  | ||||||
| @@ -375,24 +375,24 @@ CodeBody gen_hashtable( StrC type, StrC hashtable_name ) | |||||||
| 	++ HashTable_DefinitionCounter; | 	++ HashTable_DefinitionCounter; | ||||||
| 	StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", Array_DefinitionCounter).to_strc(); | 	StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", Array_DefinitionCounter).to_strc(); | ||||||
|  |  | ||||||
| 	Code generic_interface_slot = untyped_str(token_fmt( "type_delimiter", (StrC)tbl_type, "slot", (StrC)slot_str, | 	Code generic_interface_slot = untyped_str(token_fmt( "type", type, "tbl_type", (StrC)tbl_type, "slot", (StrC)slot_str, | ||||||
| R"(#define GENERIC_SLOT_<slot>__hashtable_init          <type_delimiter>,  <type_delimiter>_init | R"(#define GENERIC_SLOT_<slot>__hashtable_init          <type>,      <tbl_type>_init | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_init_reserve     <type_delimiter>,  <type_delimiter>_init_reserve | #define GENERIC_SLOT_<slot>__hashtable_init_reserve     <type>,      <tbl_type>_init_reserve | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_clear            <type_delimiter>,  <type_delimiter>_clear | #define GENERIC_SLOT_<slot>__hashtable_clear            <tbl_type>,  <tbl_type>_clear | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_destroy          <type_delimiter>*, <type_delimiter>_destroy | #define GENERIC_SLOT_<slot>__hashtable_destroy          <tbl_type>*, <tbl_type>_destroy | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_get              <type_delimiter>,  <type_delimiter>_get | #define GENERIC_SLOT_<slot>__hashtable_get              <tbl_type>,  <tbl_type>_get | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_map              <type_delimiter>,  <type_delimiter>_map | #define GENERIC_SLOT_<slot>__hashtable_map              <tbl_type>,  <tbl_type>_map | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_map_mut          <type_delimiter>,  <type_delimiter>_map_mut | #define GENERIC_SLOT_<slot>__hashtable_map_mut          <tbl_type>,  <tbl_type>_map_mut | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_grow             <type_delimiter>*, <type_delimiter>_grow | #define GENERIC_SLOT_<slot>__hashtable_grow             <tbl_type>*, <tbl_type>_grow | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_rehash           <type_delimiter>*, <type_delimiter>_rehash | #define GENERIC_SLOT_<slot>__hashtable_rehash           <tbl_type>*, <tbl_type>_rehash | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_rehash_fast      <type_delimiter>,  <type_delimiter>_rehash_fast | #define GENERIC_SLOT_<slot>__hashtable_rehash_fast      <tbl_type>,  <tbl_type>_rehash_fast | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_remove_entry     <type_delimiter>,  <type_delimiter>_remove_entry | #define GENERIC_SLOT_<slot>__hashtable_remove_entry     <tbl_type>,  <tbl_type>_remove_entry | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_set              <type_delimiter>*, <type_delimiter>_set | #define GENERIC_SLOT_<slot>__hashtable_set              <tbl_type>*, <tbl_type>_set | ||||||
| #define GENERIC_SLOT_<slot>__hashtable_slot             <type_delimiter>,  <type_delimiter>_slot | #define GENERIC_SLOT_<slot>__hashtable_slot             <tbl_type>,  <tbl_type>_slot | ||||||
|  |  | ||||||
| #define GENERIC_SLOT_<slot>__hashtable__add_entry       <type_delimiter>*, <type_delimiter>__add_entry | #define GENERIC_SLOT_<slot>__hashtable__add_entry       <tbl_type>*, <tbl_type>__add_entry | ||||||
| #define GENERIC_SLOT_<slot>__hashtable__find            <type_delimiter>,  <type_delimiter>__find | #define GENERIC_SLOT_<slot>__hashtable__find            <tbl_type>,  <tbl_type>__find | ||||||
| #define GENERIC_SLOT_<slot>__hashtable__full            <type_delimiter>,  <type_delimiter>__full | #define GENERIC_SLOT_<slot>__hashtable__full            <tbl_type>,  <tbl_type>__full | ||||||
| )" | )" | ||||||
| 	)); | 	)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,16 +4,20 @@ | |||||||
| 	See Readme.md for more information from the project repository. | 	See Readme.md for more information from the project repository. | ||||||
|  |  | ||||||
| 	Public Address: | 	Public Address: | ||||||
| 	https://github.com/Ed94/gencpp | 	https://github.com/Ed94/gencpp  ---------------------------------------------------------------. | ||||||
|  | 	|   _____                               _____ _                       _      ___   __     __    | | ||||||
| 	This is a single header C-Library variant. | 	|  / ____)                             / ____} |                     | |   / ,__} /  |   /  |   | | ||||||
| 	Define GEN_IMPLEMENTATION before including this file in a single compilation unit. | 	| | / ___  ___ _ __   ___ _ __  _ __  | {___ | l_ __ _  __ _, ___  __| |  | |    '-l |  '-l |   | | ||||||
|  | 	| | |{_  \/ __\ '_ \ / __} '_ l| '_ l  \___ \| __/ _` |/ _` |/ __\/ _` |  | |      | |    | |   | | ||||||
| 	! ----------------------------------------------------------------------- VERSION: v0.20-Alpha ! | 	| | l__j | ___/ | | | {__; ;_l } ;_l } ____} | l| (_} | {_| | ___j {_; |  | l___  _J l_  _J l_  | | ||||||
| 	! ============================================================================================ ! | 	|  \_____|\___}_l |_|\___} .__/| .__/ {_____/ \__\__/_l\__. |\___/\__,_l   \____}{_____}{_____} | | ||||||
| 	! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION                 ! | 	|                        | |   | |                      __} |                                   | | ||||||
| 	! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL ! | 	|                        l_l   l_l                     {___/                                    | | ||||||
| 	! ============================================================================================ ! | 	! ----------------------------------------------------------------------- VERSION: v0.20-Alpha  | | ||||||
|  | 	! ============================================================================================= | | ||||||
|  | 	! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION                  | | ||||||
|  | 	! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL  | | ||||||
|  | 	! ============================================================================================= / | ||||||
| */ | */ | ||||||
| #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | ||||||
| #	error Gen.hpp : GEN_TIME not defined | #	error Gen.hpp : GEN_TIME not defined | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& par | |||||||
| 	CodePreprocessCond cond = cast(CodePreprocessCond, entry_iter); | 	CodePreprocessCond cond = cast(CodePreprocessCond, entry_iter); | ||||||
| 	if ( cond->Content.is_equal(cond_sig) ) | 	if ( cond->Content.is_equal(cond_sig) ) | ||||||
| 	{ | 	{ | ||||||
| 		log_fmt("Preprocess cond found: %SC\n", cond->Content); | 		//log_fmt("Preprocess cond found: %SC\n", cond->Content); | ||||||
| 		found = true; | 		found = true; | ||||||
|  |  | ||||||
| 		s32 depth = 1; | 		s32 depth = 1; | ||||||
| @@ -105,7 +105,7 @@ R"(#define <macro_name>(selector_arg, ...) _Generic( (selector_arg), \ | |||||||
| 	for ( s32 slot = 1; slot <= num_slots; ++ slot ) | 	for ( s32 slot = 1; slot <= num_slots; ++ slot ) | ||||||
| 	{ | 	{ | ||||||
| 		StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", slot).to_strc(); | 		StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", slot).to_strc(); | ||||||
| 		if (slot == num_slots) | 		if (slot == num_slots && false) | ||||||
| 		{ | 		{ | ||||||
| 			define_builder.append( token_fmt( "macro_name", macro_name, "slot", slot_str, | 			define_builder.append( token_fmt( "macro_name", macro_name, "slot", slot_str, | ||||||
| R"(		GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(  GENERIC_SLOT_<slot>__<macro_name> ) \ | R"(		GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(  GENERIC_SLOT_<slot>__<macro_name> ) \ | ||||||
| @@ -128,6 +128,8 @@ R"(		GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_<slot>__<macro_name> ) | |||||||
| 		)); | 		)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	define_builder.append( txt("default: gen_generic_selection_fail") ); | ||||||
|  |  | ||||||
| 	if ( ! one_arg ) | 	if ( ! one_arg ) | ||||||
| 	{ | 	{ | ||||||
| 		if (opts == GenericSel_By_Ref) | 		if (opts == GenericSel_By_Ref) | ||||||
|   | |||||||
| @@ -6,6 +6,18 @@ | |||||||
| #include "gen/especifier.hpp" | #include "gen/especifier.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |   ______   ______  ________      __    __       ______                 __ | ||||||
|  |  /      \ /      \|        \    |  \  |  \     /      \               |  \ | ||||||
|  | |  ▓▓▓▓▓▓\  ▓▓▓▓▓▓\\▓▓▓▓▓▓▓▓    | ▓▓\ | ▓▓    |  ▓▓▓▓▓▓\ ______   ____| ▓▓ ______ | ||||||
|  | | ▓▓__| ▓▓ ▓▓___\▓▓  | ▓▓       | ▓▓▓\| ▓▓    | ▓▓   \▓▓/      \ /      ▓▓/      \ | ||||||
|  | | ▓▓    ▓▓\▓▓    \   | ▓▓       | ▓▓▓▓\ ▓▓    | ▓▓     |  ▓▓▓▓▓▓\  ▓▓▓▓▓▓▓  ▓▓▓▓▓▓\ | ||||||
|  | | ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\  | ▓▓       | ▓▓\▓▓ ▓▓    | ▓▓   __| ▓▓  | ▓▓ ▓▓  | ▓▓ ▓▓    ▓▓ | ||||||
|  | | ▓▓  | ▓▓  \__| ▓▓  | ▓▓       | ▓▓ \▓▓▓▓    | ▓▓__/  \ ▓▓__/ ▓▓ ▓▓__| ▓▓ ▓▓▓▓▓▓▓▓ | ||||||
|  | | ▓▓  | ▓▓\▓▓    ▓▓  | ▓▓       | ▓▓  \▓▓▓     \▓▓    ▓▓\▓▓    ▓▓\▓▓    ▓▓\▓▓     \ | ||||||
|  |  \▓▓   \▓▓ \▓▓▓▓▓▓    \▓▓        \▓▓   \▓▓      \▓▓▓▓▓▓  \▓▓▓▓▓▓  \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ | ||||||
|  | */ | ||||||
|  |  | ||||||
| struct AST; | struct AST; | ||||||
| struct AST_Body; | struct AST_Body; | ||||||
| struct AST_Attributes; | struct AST_Attributes; | ||||||
| @@ -84,6 +96,7 @@ typedef AST* Code; | |||||||
| #else | #else | ||||||
| struct Code; | struct Code; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| Define_Code(Body); | Define_Code(Body); | ||||||
| // These are to offer ease of use and optionally strong type safety for the AST. | // These are to offer ease of use and optionally strong type safety for the AST. | ||||||
| Define_Code(Attributes); | Define_Code(Attributes); | ||||||
| @@ -150,6 +163,7 @@ Define_Code(Typedef); | |||||||
| Define_Code(Union); | Define_Code(Union); | ||||||
| Define_Code(Using); | Define_Code(Using); | ||||||
| Define_Code(Var); | Define_Code(Var); | ||||||
|  |  | ||||||
| #undef Define_Code | #undef Define_Code | ||||||
|  |  | ||||||
| GEN_NS_PARSER_BEGIN | GEN_NS_PARSER_BEGIN | ||||||
| @@ -172,6 +186,7 @@ template< class Type> forceinline Type tmpl_cast( Code self ) { return * rcast( | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Code C-Interface | #pragma region Code C-Interface | ||||||
|  |  | ||||||
| void        code_append       (Code code, Code other ); | void        code_append       (Code code, Code other ); | ||||||
| char const* code_debug_str    (Code code); | char const* code_debug_str    (Code code); | ||||||
| Code        code_duplicate    (Code code); | Code        code_duplicate    (Code code); | ||||||
| @@ -185,6 +200,7 @@ String      code_to_string    (Code self ); | |||||||
| void        code_to_string_ptr(Code self, String* result ); | void        code_to_string_ptr(Code self, String* result ); | ||||||
| char const* code_type_str     (Code self ); | char const* code_type_str     (Code self ); | ||||||
| bool        code_validate_body(Code self ); | bool        code_validate_body(Code self ); | ||||||
|  |  | ||||||
| #pragma endregion Code C-Interface | #pragma endregion Code C-Interface | ||||||
|  |  | ||||||
| #if GEN_COMPILER_CPP | #if GEN_COMPILER_CPP | ||||||
| @@ -298,10 +314,11 @@ constexpr static | |||||||
| int AST_ArrSpecs_Cap = | int AST_ArrSpecs_Cap = | ||||||
| ( | ( | ||||||
| 		AST_POD_Size | 		AST_POD_Size | ||||||
|  | 		- sizeof(Code) | ||||||
| 		- sizeof(StringCached) | 		- sizeof(StringCached) | ||||||
| 		- sizeof(AST*) * 3 | 		- sizeof(Code) * 2 | ||||||
| 		- sizeof(Token*) | 		- sizeof(Token*) | ||||||
| 		- sizeof(AST*) | 		- sizeof(Code) | ||||||
| 		- sizeof(CodeType) | 		- sizeof(CodeType) | ||||||
| 		- sizeof(ModuleFlag) | 		- sizeof(ModuleFlag) | ||||||
| 		- sizeof(u32) | 		- sizeof(u32) | ||||||
|   | |||||||
| @@ -4,6 +4,22 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region AST Types | #pragma region AST Types | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |   ______   ______  ________      ________ | ||||||
|  |  /      \ /      \|        \    |        \ | ||||||
|  | |  ▓▓▓▓▓▓\  ▓▓▓▓▓▓\\▓▓▓▓▓▓▓▓     \▓▓▓▓▓▓▓▓__    __  ______   ______   _______ | ||||||
|  | | ▓▓__| ▓▓ ▓▓___\▓▓  | ▓▓          | ▓▓  |  \  |  \/      \ /      \ /       \ | ||||||
|  | | ▓▓    ▓▓\▓▓    \   | ▓▓          | ▓▓  | ▓▓  | ▓▓  ▓▓▓▓▓▓\  ▓▓▓▓▓▓\  ▓▓▓▓▓▓▓ | ||||||
|  | | ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\  | ▓▓          | ▓▓  | ▓▓  | ▓▓ ▓▓  | ▓▓ ▓▓    ▓▓\▓▓    \ | ||||||
|  | | ▓▓  | ▓▓  \__| ▓▓  | ▓▓          | ▓▓  | ▓▓__/ ▓▓ ▓▓__/ ▓▓ ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\ | ||||||
|  | | ▓▓  | ▓▓\▓▓    ▓▓  | ▓▓          | ▓▓   \▓▓    ▓▓ ▓▓    ▓▓\▓▓     \       ▓▓ | ||||||
|  |  \▓▓   \▓▓ \▓▓▓▓▓▓    \▓▓           \▓▓   _\▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓  \▓▓▓▓▓▓▓\▓▓▓▓▓▓▓ | ||||||
|  |                                          |  \__| ▓▓ ▓▓ | ||||||
|  |                                           \▓▓    ▓▓ ▓▓ | ||||||
|  |                                            \▓▓▓▓▓▓ \▓▓ | ||||||
|  | */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
| 	Show only relevant members of the AST for its type. | 	Show only relevant members of the AST for its type. | ||||||
| 	AST* fields are replaced with Code types. | 	AST* fields are replaced with Code types. | ||||||
| @@ -12,7 +28,9 @@ | |||||||
|  |  | ||||||
| struct AST_Body | struct AST_Body | ||||||
| { | { | ||||||
| 	char              _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; | 	union { | ||||||
|  | 		char          _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
|  | 	}; | ||||||
| 	StringCached      Name; | 	StringCached      Name; | ||||||
| 	Code              Front; | 	Code              Front; | ||||||
| 	Code              Back; | 	Code              Back; | ||||||
| @@ -550,7 +568,9 @@ static_assert( sizeof(AST_Fn) == sizeof(AST), "ERROR: AST_Fn is not the same siz | |||||||
|  |  | ||||||
| struct AST_Module | struct AST_Module | ||||||
| { | { | ||||||
| 	char              _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; | 	union { | ||||||
|  | 		char          _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
|  | 	}; | ||||||
| 	StringCached      Name; | 	StringCached      Name; | ||||||
| 	Code              Prev; | 	Code              Prev; | ||||||
| 	Code              Next; | 	Code              Next; | ||||||
| @@ -693,7 +713,7 @@ static_assert( sizeof(AST_PreprocessCond) == sizeof(AST), "ERROR: AST_Preprocess | |||||||
|  |  | ||||||
| struct AST_Specifiers | struct AST_Specifiers | ||||||
| { | { | ||||||
| 	Specifier        ArrSpecs[ AST_ArrSpecs_Cap ]; | 	Specifier         ArrSpecs[ AST_ArrSpecs_Cap ]; | ||||||
| 	StringCached      Name; | 	StringCached      Name; | ||||||
| 	CodeSpecifiers    NextSpecs; | 	CodeSpecifiers    NextSpecs; | ||||||
| 	Code              Prev; | 	Code              Prev; | ||||||
|   | |||||||
| @@ -3,7 +3,20 @@ | |||||||
| #include "ast.hpp" | #include "ast.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |   ______                 __               ______            __                        ______ | ||||||
|  |  /      \               |  \             |      \          |  \                      /      \ | ||||||
|  | |  ▓▓▓▓▓▓\ ______   ____| ▓▓ ______       \▓▓▓▓▓▓_______  _| ▓▓_    ______   ______ |  ▓▓▓▓▓▓\ ______   _______  ______ | ||||||
|  | | ▓▓   \▓▓/      \ /      ▓▓/      \       | ▓▓ |       \|   ▓▓ \  /      \ /      \| ▓▓_  \▓▓|      \ /       \/      \ | ||||||
|  | | ▓▓     |  ▓▓▓▓▓▓\  ▓▓▓▓▓▓▓  ▓▓▓▓▓▓\      | ▓▓ | ▓▓▓▓▓▓▓\\▓▓▓▓▓▓ |  ▓▓▓▓▓▓\  ▓▓▓▓▓▓\ ▓▓ \     \▓▓▓▓▓▓\  ▓▓▓▓▓▓▓  ▓▓▓▓▓▓\ | ||||||
|  | | ▓▓   __| ▓▓  | ▓▓ ▓▓  | ▓▓ ▓▓    ▓▓      | ▓▓ | ▓▓  | ▓▓ | ▓▓ __| ▓▓    ▓▓ ▓▓   \▓▓ ▓▓▓▓    /      ▓▓ ▓▓     | ▓▓    ▓▓ | ||||||
|  | | ▓▓__/  \ ▓▓__/ ▓▓ ▓▓__| ▓▓ ▓▓▓▓▓▓▓▓     _| ▓▓_| ▓▓  | ▓▓ | ▓▓|  \ ▓▓▓▓▓▓▓▓ ▓▓     | ▓▓     |  ▓▓▓▓▓▓▓ ▓▓_____| ▓▓▓▓▓▓▓▓ | ||||||
|  |  \▓▓    ▓▓\▓▓    ▓▓\▓▓    ▓▓\▓▓     \    |   ▓▓ \ ▓▓  | ▓▓  \▓▓  ▓▓\▓▓     \ ▓▓     | ▓▓      \▓▓    ▓▓\▓▓     \\▓▓     \ | ||||||
|  |   \▓▓▓▓▓▓  \▓▓▓▓▓▓  \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓     \▓▓▓▓▓▓\▓▓   \▓▓   \▓▓▓▓  \▓▓▓▓▓▓▓\▓▓      \▓▓       \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ | ||||||
|  | */ | ||||||
|  |  | ||||||
| #pragma region Code Type C-Interface | #pragma region Code Type C-Interface | ||||||
|  |  | ||||||
| void   body_append          ( CodeBody body, Code     other ); | void   body_append          ( CodeBody body, Code     other ); | ||||||
| void   body_append_body     ( CodeBody body, CodeBody other ); | void   body_append_body     ( CodeBody body, CodeBody other ); | ||||||
| String body_to_string       ( CodeBody body ); | String body_to_string       ( CodeBody body ); | ||||||
| @@ -14,7 +27,7 @@ Code begin_CodeBody( CodeBody body); | |||||||
| Code end_CodeBody  ( CodeBody body ); | Code end_CodeBody  ( CodeBody body ); | ||||||
| Code next_CodeBody ( CodeBody body, Code entry_iter ); | Code next_CodeBody ( CodeBody body, Code entry_iter ); | ||||||
|  |  | ||||||
| void   class_add_interface( CodeClass self, CodeType interface ); | void   class_add_interface( CodeClass self, CodeTypename interface ); | ||||||
| String class_to_string    ( CodeClass self ); | String class_to_string    ( CodeClass self ); | ||||||
| void   class_to_string_def( CodeClass self, String* result ); | void   class_to_string_def( CodeClass self, String* result ); | ||||||
| void   class_to_string_fwd( CodeClass self, String* result ); | void   class_to_string_fwd( CodeClass self, String* result ); | ||||||
| @@ -39,7 +52,7 @@ Specifier* begin_CodeSpecifiers(CodeSpecifiers specifiers); | |||||||
| Specifier* end_CodeSpecifiers  (CodeSpecifiers specifiers); | Specifier* end_CodeSpecifiers  (CodeSpecifiers specifiers); | ||||||
| Specifier* next_CodeSpecifiers (CodeSpecifiers specifiers, Specifier* spec_iter); | Specifier* next_CodeSpecifiers (CodeSpecifiers specifiers, Specifier* spec_iter); | ||||||
|  |  | ||||||
| void   struct_add_interface(CodeStruct self, CodeType interface); | void   struct_add_interface(CodeStruct self, CodeTypename interface); | ||||||
| String struct_to_string    (CodeStruct self); | String struct_to_string    (CodeStruct self); | ||||||
| void   struct_to_string_fwd(CodeStruct self, String* result); | void   struct_to_string_fwd(CodeStruct self, String* result); | ||||||
| void   struct_to_string_def(CodeStruct self, String* result); | void   struct_to_string_def(CodeStruct self, String* result); | ||||||
| @@ -126,6 +139,7 @@ void   using_to_string_ns (CodeUsing op_cast, String* result ); | |||||||
|  |  | ||||||
| String var_to_string    (CodeVar self); | String var_to_string    (CodeVar self); | ||||||
| void   var_to_string_ref(CodeVar self, String* result); | void   var_to_string_ref(CodeVar self, String* result); | ||||||
|  |  | ||||||
| #pragma endregion Code Type C-Interface | #pragma endregion Code Type C-Interface | ||||||
|  |  | ||||||
| #if GEN_COMPILER_CPP | #if GEN_COMPILER_CPP | ||||||
| @@ -214,24 +228,6 @@ struct CodeSpecifiers | |||||||
| 	AST_Specifiers* ast; | 	AST_Specifiers* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct CodeStruct |  | ||||||
| { |  | ||||||
| #if ! GEN_C_LIKE_CPP |  | ||||||
| 	Using_Code( CodeStruct ); |  | ||||||
| 	forceinline void add_interface( CodeType interface ) { return struct_add_interface(* this, interface); } |  | ||||||
| 	forceinline String to_string()                       { return struct_to_string(* this); } |  | ||||||
| 	forceinline void   to_string_fwd( String& result )   { return struct_to_string_fwd(* this, & result); } |  | ||||||
| 	forceinline void   to_string_def( String& result )   { return struct_to_string_def(* this, & result); } |  | ||||||
| #endif |  | ||||||
| 	Using_CodeOps( CodeStruct ); |  | ||||||
| 	forceinline operator Code() { return * rcast( Code*, this ); } |  | ||||||
| 	forceinline AST_Struct* operator->() { |  | ||||||
| 		GEN_ASSERT(ast); |  | ||||||
| 		return ast; |  | ||||||
| 	} |  | ||||||
| 	AST_Struct* ast; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct CodeAttributes | struct CodeAttributes | ||||||
| { | { | ||||||
| #if ! GEN_C_LIKE_CPP | #if ! GEN_C_LIKE_CPP | ||||||
| @@ -907,6 +903,24 @@ struct CodeVar | |||||||
| 	AST_Var* ast; | 	AST_Var* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | struct CodeStruct | ||||||
|  | { | ||||||
|  | #if ! GEN_C_LIKE_CPP | ||||||
|  | 	Using_Code( CodeStruct ); | ||||||
|  | 	forceinline void   add_interface( CodeTypename interface ) { return struct_add_interface(* this, interface); } | ||||||
|  | 	forceinline String to_string()                             { return struct_to_string(* this); } | ||||||
|  | 	forceinline void   to_string_fwd( String& result )         { return struct_to_string_fwd(* this, & result); } | ||||||
|  | 	forceinline void   to_string_def( String& result )         { return struct_to_string_def(* this, & result); } | ||||||
|  | #endif | ||||||
|  | 	Using_CodeOps( CodeStruct ); | ||||||
|  | 	forceinline operator Code() { return * rcast( Code*, this ); } | ||||||
|  | 	forceinline AST_Struct* operator->() { | ||||||
|  | 		GEN_ASSERT(ast); | ||||||
|  | 		return ast; | ||||||
|  | 	} | ||||||
|  | 	AST_Struct* ast; | ||||||
|  | }; | ||||||
|  |  | ||||||
| #undef Define_CodeType | #undef Define_CodeType | ||||||
| #undef Using_Code | #undef Using_Code | ||||||
| #undef Using_CodeOps | #undef Using_CodeOps | ||||||
| @@ -982,6 +996,7 @@ struct NullCode_ImplicitCaster | |||||||
|  |  | ||||||
| #if ! GEN_C_LIKE_CPP | #if ! GEN_C_LIKE_CPP | ||||||
| GEN_OPTIMIZE_MAPPINGS_BEGIN | GEN_OPTIMIZE_MAPPINGS_BEGIN | ||||||
|  |  | ||||||
| forceinline void   append          ( CodeBody body, Code     other ) { return body_append(body, other); } | forceinline void   append          ( CodeBody body, Code     other ) { return body_append(body, other); } | ||||||
| forceinline void   append          ( CodeBody body, CodeBody other ) { return body_append_body(body, other); } | forceinline void   append          ( CodeBody body, CodeBody other ) { return body_append_body(body, other); } | ||||||
| forceinline String to_string       ( CodeBody body )                 { return body_to_string(body); } | forceinline String to_string       ( CodeBody body )                 { return body_to_string(body); } | ||||||
| @@ -992,7 +1007,7 @@ forceinline Code begin( CodeBody body)                   { return begin_CodeBody | |||||||
| forceinline Code end  ( CodeBody body )                  { return end_CodeBody(body); } | forceinline Code end  ( CodeBody body )                  { return end_CodeBody(body); } | ||||||
| forceinline Code next ( CodeBody body, Code entry_iter ) { return next_CodeBody(body, entry_iter); } | forceinline Code next ( CodeBody body, Code entry_iter ) { return next_CodeBody(body, entry_iter); } | ||||||
|  |  | ||||||
| forceinline void   add_interface( CodeClass self, CodeType interface ) { return class_add_interface(self, interface); } | forceinline void   add_interface( CodeClass self, CodeTypename interface ) { return class_add_interface(self, interface); } | ||||||
| forceinline String to_string    ( CodeClass self )                     { return class_to_string(self); } | forceinline String to_string    ( CodeClass self )                     { return class_to_string(self); } | ||||||
| forceinline void   to_string_def( CodeClass self, String& result )     { return class_to_string_def(self, & result); } | forceinline void   to_string_def( CodeClass self, String& result )     { return class_to_string_def(self, & result); } | ||||||
| forceinline void   to_string_fwd( CodeClass self, String& result )     { return class_to_string_fwd(self, & result); } | forceinline void   to_string_fwd( CodeClass self, String& result )     { return class_to_string_fwd(self, & result); } | ||||||
| @@ -1017,10 +1032,10 @@ forceinline Specifier* begin(CodeSpecifiers specifiers)                       { | |||||||
| forceinline Specifier* end  (CodeSpecifiers specifiers)                       { return end_CodeSpecifiers(specifiers); } | forceinline Specifier* end  (CodeSpecifiers specifiers)                       { return end_CodeSpecifiers(specifiers); } | ||||||
| forceinline Specifier* next (CodeSpecifiers specifiers, Specifier& spec_iter) { return next_CodeSpecifiers(specifiers, & spec_iter); } | forceinline Specifier* next (CodeSpecifiers specifiers, Specifier& spec_iter) { return next_CodeSpecifiers(specifiers, & spec_iter); } | ||||||
|  |  | ||||||
| forceinline void   add_interface(CodeStruct self, CodeType interface) { return struct_add_interface(self, interface); } | forceinline void   add_interface(CodeStruct self, CodeTypename interface) { return struct_add_interface(self, interface); } | ||||||
| forceinline String to_string    (CodeStruct self)                     { return struct_to_string(self); } | forceinline String to_string    (CodeStruct self)                         { return struct_to_string(self); } | ||||||
| forceinline void   to_string_fwd(CodeStruct self, String& result)     { return struct_to_string_fwd(self, & result); } | forceinline void   to_string_fwd(CodeStruct self, String& result)         { return struct_to_string_fwd(self, & result); } | ||||||
| forceinline void   to_string_def(CodeStruct self, String& result)     { return struct_to_string_def(self, & result); } | forceinline void   to_string_def(CodeStruct self, String& result)         { return struct_to_string_def(self, & result); } | ||||||
|  |  | ||||||
| forceinline String to_string(CodeAttributes attributes)                 { return attributes_to_string(attributes); } | forceinline String to_string(CodeAttributes attributes)                 { return attributes_to_string(attributes); } | ||||||
| forceinline void   to_string(CodeAttributes attributes, String& result) { return attributes_to_string_ref(attributes, & result); } | forceinline void   to_string(CodeAttributes attributes, String& result) { return attributes_to_string_ref(attributes, & result); } | ||||||
| @@ -1104,6 +1119,7 @@ forceinline void   to_string_ns(CodeUsing op_cast, String& result ) { return usi | |||||||
|  |  | ||||||
| forceinline String to_string(CodeVar self)                 { return var_to_string(self); } | forceinline String to_string(CodeVar self)                 { return var_to_string(self); } | ||||||
| forceinline void   to_string(CodeVar self, String& result) { return var_to_string_ref(self, & result); } | forceinline void   to_string(CodeVar self, String& result) { return var_to_string_ref(self, & result); } | ||||||
|  |  | ||||||
| GEN_OPITMIZE_MAPPINGS_END | GEN_OPITMIZE_MAPPINGS_END | ||||||
| #endif //if GEN_C_LIKE_CPP | #endif //if GEN_C_LIKE_CPP | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,7 +68,8 @@ enum CodeType : u32 | |||||||
| 	CT_Using, | 	CT_Using, | ||||||
| 	CT_Using_Namespace, | 	CT_Using_Namespace, | ||||||
| 	CT_Variable, | 	CT_Variable, | ||||||
| 	CT_NumTypes | 	CT_NumTypes, | ||||||
|  | 	CT_UnderlyingType = GEN_U32_MAX | ||||||
| }; | }; | ||||||
|  |  | ||||||
| inline StrC codetype_to_str( CodeType type ) | inline StrC codetype_to_str( CodeType type ) | ||||||
|   | |||||||
| @@ -54,7 +54,8 @@ enum Operator : u32 | |||||||
| 	Op_NewArray, | 	Op_NewArray, | ||||||
| 	Op_Delete, | 	Op_Delete, | ||||||
| 	Op_DeleteArray, | 	Op_DeleteArray, | ||||||
| 	NumOps | 	Op_NumOps, | ||||||
|  | 	Op_UnderlyingType = 0xffffffffu | ||||||
| }; | }; | ||||||
|  |  | ||||||
| inline StrC operator_to_str( Operator op ) | inline StrC operator_to_str( Operator op ) | ||||||
|   | |||||||
| @@ -33,7 +33,8 @@ enum Specifier : u32 | |||||||
| 	Spec_Override, | 	Spec_Override, | ||||||
| 	Spec_Pure, | 	Spec_Pure, | ||||||
| 	Spec_Volatile, | 	Spec_Volatile, | ||||||
| 	Spec_NumSpecifiers | 	Spec_NumSpecifiers, | ||||||
|  | 	Spec_UnderlyingType = 0xffffffffu | ||||||
| }; | }; | ||||||
|  |  | ||||||
| inline StrC spec_to_str( Specifier type ) | inline StrC spec_to_str( Specifier type ) | ||||||
|   | |||||||
| @@ -6,13 +6,20 @@ | |||||||
| 	See Readme.md for more information from the project repository. | 	See Readme.md for more information from the project repository. | ||||||
|  |  | ||||||
| 	Public Address: | 	Public Address: | ||||||
| 	https://github.com/Ed94/gencpp | 	https://github.com/Ed94/gencpp  --------------------------------------------------------------. | ||||||
|  | 	|   _____                               _____ _                       _                        | | ||||||
| 	! ----------------------------------------------------------------------- VERSION: v0.20-Alpha ! | 	|  / ____)                             / ____} |                     | |                       | | ||||||
| 	! ============================================================================================ ! | 	| | / ___  ___ _ __   ___ _ __  _ __  | {___ | |__ _ _, __ _, ___  __| |                       | | ||||||
| 	! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION                 ! | 	| | |{_  |/ _ \ '_ \ / __} '_ l| '_ l `\___ \| __/ _` |/ _` |/ _ \/ _` |                       | | ||||||
| 	! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL ! | 	| | l__j | ___/ | | | {__; |+l } |+l | ____) | l| (_| | {_| | ___/ (_| |                       | | ||||||
| 	! ============================================================================================ ! | 	|  \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l                       | | ||||||
|  | 	|                        | |   | |                      __} |                                  | | ||||||
|  | 	|                        l_l   l_l                     {___/                                   | | ||||||
|  | 	! ----------------------------------------------------------------------- VERSION: v0.20-Alpha | | ||||||
|  | 	! ============================================================================================ | | ||||||
|  | 	! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION                 | | ||||||
|  | 	! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL | | ||||||
|  | 	! ============================================================================================ / | ||||||
| */ | */ | ||||||
| #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | ||||||
| #	error Gen.hpp : GEN_TIME not defined | #	error Gen.hpp : GEN_TIME not defined | ||||||
|   | |||||||
| @@ -104,7 +104,7 @@ forceinline | |||||||
| char const* code_type_str(Code self) | char const* code_type_str(Code self) | ||||||
| { | { | ||||||
| 	GEN_ASSERT(self != nullptr); | 	GEN_ASSERT(self != nullptr); | ||||||
| 	return codetype_to_str( self->Type ); | 	return codetype_to_str( self->Type ).Ptr; | ||||||
| } | } | ||||||
| #pragma endregion Code | #pragma endregion Code | ||||||
|  |  | ||||||
| @@ -138,7 +138,8 @@ Code begin_CodeBody( CodeBody body) { | |||||||
| 	GEN_ASSERT(body); | 	GEN_ASSERT(body); | ||||||
| 	if ( body != nullptr ) | 	if ( body != nullptr ) | ||||||
| 		return body->Front; | 		return body->Front; | ||||||
| 	return { nullptr }; |  | ||||||
|  | 	return NullCode; | ||||||
| } | } | ||||||
| forceinline | forceinline | ||||||
| Code end_CodeBody(CodeBody body ){ | Code end_CodeBody(CodeBody body ){ | ||||||
| @@ -170,7 +171,7 @@ void class_add_interface( CodeClass self, CodeTypename type ) | |||||||
|  |  | ||||||
| 	while ( possible_slot != nullptr ) | 	while ( possible_slot != nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		possible_slot = possible_slot->Next; | 		possible_slot = cast(CodeTypename, possible_slot->Next); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	possible_slot = type; | 	possible_slot = type; | ||||||
| @@ -212,7 +213,7 @@ CodeParam params_get(CodeParam self, s32 idx ) | |||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		if ( ++ param != nullptr ) | 		if ( ++ param != nullptr ) | ||||||
| 			return { nullptr }; | 			return NullCode; | ||||||
|  |  | ||||||
| 		param = cast(CodeParam, cast(Code, param)->Next); | 		param = cast(CodeParam, cast(Code, param)->Next); | ||||||
| 	} | 	} | ||||||
| @@ -246,7 +247,7 @@ forceinline | |||||||
| CodeParam end_CodeParam(CodeParam params) | CodeParam end_CodeParam(CodeParam params) | ||||||
| { | { | ||||||
| 	// return { (AST_Param*) rcast( AST*, ast)->Last }; | 	// return { (AST_Param*) rcast( AST*, ast)->Last }; | ||||||
| 	return { nullptr }; | 	return NullCode; | ||||||
| } | } | ||||||
| forceinline | forceinline | ||||||
| CodeParam next_CodeParam(CodeParam params, CodeParam param_iter) | CodeParam next_CodeParam(CodeParam params, CodeParam param_iter) | ||||||
| @@ -347,7 +348,7 @@ Specifier* next_CodeSpecifiers(CodeSpecifiers self, Specifier* spec_iter) | |||||||
|  |  | ||||||
| #pragma region CodeStruct | #pragma region CodeStruct | ||||||
| inline | inline | ||||||
| void add_interface(CodeStruct self, CodeTypename type ) | void struct_add_interface(CodeStruct self, CodeTypename type ) | ||||||
| { | { | ||||||
| 	CodeTypename possible_slot = self->ParentType; | 	CodeTypename possible_slot = self->ParentType; | ||||||
| 	if ( possible_slot != nullptr ) | 	if ( possible_slot != nullptr ) | ||||||
| @@ -360,7 +361,7 @@ void add_interface(CodeStruct self, CodeTypename type ) | |||||||
|  |  | ||||||
| 	while ( possible_slot != nullptr ) | 	while ( possible_slot != nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		possible_slot = possible_slot->Next; | 		possible_slot = cast(CodeTypename, possible_slot->Next); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	possible_slot = type; | 	possible_slot = type; | ||||||
| @@ -385,7 +386,7 @@ CodeBody def_body( CodeType type ) | |||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			log_failure( "def_body: Invalid type %s", (char const*)codetype_to_str(type) ); | 			log_failure( "def_body: Invalid type %s", codetype_to_str(type).Ptr ); | ||||||
| 			return (CodeBody)Code_Invalid; | 			return (CodeBody)Code_Invalid; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -407,6 +408,7 @@ StrC token_fmt_impl( ssize num, ... ) | |||||||
| 	ssize result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va); | 	ssize result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va); | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	return { result, buf }; | 	StrC str = { result, buf }; | ||||||
|  | 	return str; | ||||||
| } | } | ||||||
| #pragma endregion Interface | #pragma endregion Interface | ||||||
|   | |||||||
| @@ -4,6 +4,16 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Gen Interface | #pragma region Gen Interface | ||||||
|  | /* | ||||||
|  |  /      \                       |      \          |  \                      /      \ | ||||||
|  | |  ▓▓▓▓▓▓\ ______  _______       \▓▓▓▓▓▓_______  _| ▓▓_    ______   ______ |  ▓▓▓▓▓▓\ ______   _______  ______ | ||||||
|  | | ▓▓ __\▓▓/      \|       \       | ▓▓ |       \|   ▓▓ \  /      \ /      \| ▓▓_  \▓▓|      \ /       \/      \ | ||||||
|  | | ▓▓|    \  ▓▓▓▓▓▓\ ▓▓▓▓▓▓▓\      | ▓▓ | ▓▓▓▓▓▓▓\\▓▓▓▓▓▓ |  ▓▓▓▓▓▓\  ▓▓▓▓▓▓\ ▓▓ \     \▓▓▓▓▓▓\  ▓▓▓▓▓▓▓  ▓▓▓▓▓▓\ | ||||||
|  | | ▓▓ \▓▓▓▓ ▓▓    ▓▓ ▓▓  | ▓▓      | ▓▓ | ▓▓  | ▓▓ | ▓▓ __| ▓▓    ▓▓ ▓▓   \▓▓ ▓▓▓▓    /      ▓▓ ▓▓     | ▓▓    ▓▓ | ||||||
|  | | ▓▓__| ▓▓ ▓▓▓▓▓▓▓▓ ▓▓  | ▓▓     _| ▓▓_| ▓▓  | ▓▓ | ▓▓|  \ ▓▓▓▓▓▓▓▓ ▓▓     | ▓▓     |  ▓▓▓▓▓▓▓ ▓▓_____| ▓▓▓▓▓▓▓▓ | ||||||
|  |  \▓▓    ▓▓\▓▓     \ ▓▓  | ▓▓    |   ▓▓ \ ▓▓  | ▓▓  \▓▓  ▓▓\▓▓     \ ▓▓     | ▓▓      \▓▓    ▓▓\▓▓     \\▓▓     \ | ||||||
|  |   \▓▓▓▓▓▓  \▓▓▓▓▓▓▓\▓▓   \▓▓     \▓▓▓▓▓▓\▓▓   \▓▓   \▓▓▓▓  \▓▓▓▓▓▓▓\▓▓      \▓▓       \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ | ||||||
|  | */ | ||||||
|  |  | ||||||
| // Initialize the library. | // Initialize the library. | ||||||
| // This currently just initializes the CodePool. | // This currently just initializes the CodePool. | ||||||
| @@ -164,7 +174,7 @@ struct Opts_def_variable | |||||||
| CodeVar def_variable( CodeTypename type, StrC name, Opts_def_variable opts GEN_PARAM_DEFAULT ); | CodeVar def_variable( CodeTypename type, StrC name, Opts_def_variable opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| // Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries. | // Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries. | ||||||
| CodeBody def_body( CodeTypename type ); | CodeBody def_body( CodeType type ); | ||||||
|  |  | ||||||
| // There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num, | // There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num, | ||||||
| /// or provide as an array of Code objects. | /// or provide as an array of Code objects. | ||||||
| @@ -199,23 +209,23 @@ CodeBody       def_union_body      ( s32 num, Code* codes ); | |||||||
| // TODO(Ed) : Implmeent the new parser API design. | // TODO(Ed) : Implmeent the new parser API design. | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| namespace parser { | GEN_NS_PARSER_BEGIN | ||||||
| 	struct StackNode | struct StackNode | ||||||
| 	{ | { | ||||||
| 		StackNode* Prev; | 	StackNode* Prev; | ||||||
|  |  | ||||||
| 		Token Start; | 	Token Start; | ||||||
| 		Token Name;       // The name of the AST node (if parsed) | 	Token Name;       // The name of the AST node (if parsed) | ||||||
| 		StrC  FailedProc; // The name of the procedure that failed | 	StrC  FailedProc; // The name of the procedure that failed | ||||||
| 	}; | }; | ||||||
| 	// Stack nodes are allocated the error's allocator | // Stack nodes are allocated the error's allocator | ||||||
|  |  | ||||||
| 	struct Error | struct Error | ||||||
| 	{ | { | ||||||
| 		String     message; | 	String     message; | ||||||
| 		StackNode* context_stack; | 	StackNode* context_stack; | ||||||
| 	}; | }; | ||||||
| } | GEN_NS_PARSER_END | ||||||
|  |  | ||||||
| struct ParseInfo | struct ParseInfo | ||||||
| { | { | ||||||
| @@ -223,9 +233,9 @@ struct ParseInfo | |||||||
| 	Arena TokMem; | 	Arena TokMem; | ||||||
| 	Arena CodeMem; | 	Arena CodeMem; | ||||||
|  |  | ||||||
| 	FileContents         FileContent; | 	FileContents FileContent; | ||||||
| 	Array<parser::Token> Tokens; | 	Array<Token> Tokens; | ||||||
| 	Array<parser::Error> Errors; | 	Array<Error> Errors; | ||||||
| 	// Errors are allocated to a dedicated general arena. | 	// Errors are allocated to a dedicated general arena. | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1224,7 +1224,7 @@ CodeStruct def_struct( StrC name, Opts_def_struct p ) | |||||||
| 	{ | 	{ | ||||||
| 		for (s32 idx = 0; idx < num_interfaces; idx++ ) | 		for (s32 idx = 0; idx < num_interfaces; idx++ ) | ||||||
| 		{ | 		{ | ||||||
| 			add_interface(result, interfaces[idx] ); | 			struct_add_interface(result, interfaces[idx] ); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3010,15 +3010,21 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) | |||||||
| 				eat( Tok_Statement_End ); | 				eat( Tok_Statement_End ); | ||||||
| 				// <Macro>; | 				// <Macro>; | ||||||
|  |  | ||||||
|  | 				tok.Length += prevtok.Length; | ||||||
|  |  | ||||||
| 				// TODO(Ed): Reveiw the context for this? (ESPECIALLY THIS) | 				// TODO(Ed): Reveiw the context for this? (ESPECIALLY THIS) | ||||||
| 				if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) | 				if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) | ||||||
|  | 				{ | ||||||
| 					eat( Tok_Comment ); | 					eat( Tok_Comment ); | ||||||
| 					// <Macro>; <InlineCmt> | 					// <Macro>; <InlineCmt> | ||||||
|  |  | ||||||
|  | 					tok.Length += prevtok.Length; | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else if ( | 		else if ( | ||||||
| 				strc_contains(calling_proc, txt("parse_global_nspace")) | 				strc_contains(calling_proc, txt("parse_global_nspace")) | ||||||
| 			&&	strc_contains(calling_proc, txt("parse_class_struct_body")) | 			||	strc_contains(calling_proc, txt("parse_class_struct_body")) | ||||||
| 		) | 		) | ||||||
| 		{ | 		{ | ||||||
| 			if (peektok.Type == Tok_Statement_End) | 			if (peektok.Type == Tok_Statement_End) | ||||||
| @@ -3026,10 +3032,11 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) | |||||||
| 				Token stmt_end = currtok; | 				Token stmt_end = currtok; | ||||||
| 				eat( Tok_Statement_End ); | 				eat( Tok_Statement_End ); | ||||||
| 				// <Macro>; | 				// <Macro>; | ||||||
|  | 				tok.Length += prevtok.Length; | ||||||
| 			} | 			} | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		tok.Length = ( (sptr)currtok_noskip.Text + currtok_noskip.Length ) - (sptr)tok.Text; | 		} | ||||||
|  | 		// tok.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)tok.Text; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| Leave_Scope_Early: | Leave_Scope_Early: | ||||||
|   | |||||||
| @@ -3,6 +3,22 @@ | |||||||
| #include "header_start.hpp" | #include "header_start.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  ________                                              __    __      ________ | ||||||
|  | |        \                                            |  \  |  \    |        \ | ||||||
|  | | ▓▓▓▓▓▓▓▓_______  __    __ ______ ____   _______     | ▓▓\ | ▓▓     \▓▓▓▓▓▓▓▓__    __  ______   ______   _______ | ||||||
|  | | ▓▓__   |       \|  \  |  \      \    \ /       \    | ▓▓▓\| ▓▓       | ▓▓  |  \  |  \/      \ /      \ /       \ | ||||||
|  | | ▓▓  \  | ▓▓▓▓▓▓▓\ ▓▓  | ▓▓ ▓▓▓▓▓▓\▓▓▓▓\  ▓▓▓▓▓▓▓    | ▓▓▓▓\ ▓▓       | ▓▓  | ▓▓  | ▓▓  ▓▓▓▓▓▓\  ▓▓▓▓▓▓\  ▓▓▓▓▓▓▓ | ||||||
|  | | ▓▓▓▓▓  | ▓▓  | ▓▓ ▓▓  | ▓▓ ▓▓ | ▓▓ | ▓▓\▓▓    \     | ▓▓\▓▓ ▓▓       | ▓▓  | ▓▓  | ▓▓ ▓▓  | ▓▓ ▓▓    ▓▓\▓▓    \ | ||||||
|  | | ▓▓_____| ▓▓  | ▓▓ ▓▓__/ ▓▓ ▓▓ | ▓▓ | ▓▓_\▓▓▓▓▓▓\    | ▓▓ \▓▓▓▓       | ▓▓  | ▓▓__/ ▓▓ ▓▓__/ ▓▓ ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\ | ||||||
|  | | ▓▓     \ ▓▓  | ▓▓\▓▓    ▓▓ ▓▓ | ▓▓ | ▓▓       ▓▓    | ▓▓  \▓▓▓       | ▓▓   \▓▓    ▓▓ ▓▓    ▓▓\▓▓     \       ▓▓ | ||||||
|  |  \▓▓▓▓▓▓▓▓\▓▓   \▓▓ \▓▓▓▓▓▓ \▓▓  \▓▓  \▓▓\▓▓▓▓▓▓▓      \▓▓   \▓▓        \▓▓   _\▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓  \▓▓▓▓▓▓▓\▓▓▓▓▓▓▓ | ||||||
|  |                                                                              |  \__| ▓▓ ▓▓ | ||||||
|  |                                                                               \▓▓    ▓▓ ▓▓ | ||||||
|  |                                                                                \▓▓▓▓▓▓ \▓▓ | ||||||
|  |  | ||||||
|  | */ | ||||||
|  |  | ||||||
| using LogFailType = ssize(*)(char const*, ...); | using LogFailType = ssize(*)(char const*, ...); | ||||||
|  |  | ||||||
| // By default this library will either crash or exit if an error is detected while generating codes. | // By default this library will either crash or exit if an error is detected while generating codes. | ||||||
|   | |||||||
| @@ -459,6 +459,7 @@ FileContents file_read_contents( AllocatorInfo a, b32 zero_terminate, char const | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typedef struct _memory_fd _memory_fd; | ||||||
| struct _memory_fd | struct _memory_fd | ||||||
| { | { | ||||||
| 	u8            magic; | 	u8            magic; | ||||||
| @@ -505,7 +506,7 @@ b8 file_stream_new( FileInfo* file, AllocatorInfo allocator ) | |||||||
| 	d->allocator = allocator; | 	d->allocator = allocator; | ||||||
| 	d->flags     = EFileStream_CLONE_WRITABLE; | 	d->flags     = EFileStream_CLONE_WRITABLE; | ||||||
| 	d->cap       = 0; | 	d->cap       = 0; | ||||||
| 	d->buf       = array_init<u8>( allocator ); | 	d->buf       = array_init( u8, allocator ); | ||||||
|  |  | ||||||
| 	if ( ! d->buf ) | 	if ( ! d->buf ) | ||||||
| 		return false; | 		return false; | ||||||
| @@ -531,7 +532,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize | |||||||
| 	d->flags     = flags; | 	d->flags     = flags; | ||||||
| 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = array_init_reserve<u8>( allocator, size ); | 		Array(u8) arr = array_init_reserve(u8, allocator, size ); | ||||||
| 		d->buf = arr; | 		d->buf = arr; | ||||||
|  |  | ||||||
| 		if ( ! d->buf ) | 		if ( ! d->buf ) | ||||||
| @@ -608,9 +609,9 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
|  |  | ||||||
| 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array(u8) arr = { d->buf }; | ||||||
|  |  | ||||||
| 		if ( array_get_header(arr)->Capacity < usize(new_cap) ) | 		if ( array_get_header(arr)->Capacity < scast(usize, new_cap) ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( ! array_grow( & arr, ( s64 )( new_cap ) ) ) | 			if ( ! array_grow( & arr, ( s64 )( new_cap ) ) ) | ||||||
| 				return false; | 				return false; | ||||||
| @@ -622,7 +623,7 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
|  |  | ||||||
| 	if ( ( d->flags & EFileStream_CLONE_WRITABLE ) && extralen > 0 ) | 	if ( ( d->flags & EFileStream_CLONE_WRITABLE ) && extralen > 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array(u8) arr = { d->buf }; | ||||||
|  |  | ||||||
| 		mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen ); | 		mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen ); | ||||||
| 		d->cap = new_cap; | 		d->cap = new_cap; | ||||||
| @@ -646,7 +647,7 @@ GEN_FILE_CLOSE_PROC( _memory_file_close ) | |||||||
|  |  | ||||||
| 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array(u8) arr = { d->buf }; | ||||||
| 		array_free(arr); | 		array_free(arr); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -284,14 +284,15 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if GEN_COMPILER_C | #if GEN_COMPILER_C | ||||||
| // ------------------------ _Generic function overloading ----------------------------------------- | //   ____                       _        ______                _   _                ____                  _                 __ _ | ||||||
| // This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in: | //  / ___}                     (_)      |  ____}              | | (_)              / __ \                | |               | |(_) | ||||||
| // https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md | // | | ___  ___ _ __   ___ _ __ _  ___  | |__ _   _ _ __   ___| |_ _  ___  _ __   | |  | |_   _____ _ __ | | ___   __ _  __| | _ _ __   __ _ | ||||||
| // Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unopaque as possible. | // | |{__ |/ _ \ '_ \ / _ \ '__} |/ __| |  __} | | | '_ \ / __} __} |/ _ \| '_ \  | |  | \ \ / / _ \ '_ \| |/ _ \ / _` |/ _` || | '_ \ / _` | | ||||||
| // Extensive effort was put in below to make this as easy as possible to understand what is going on with this mess of a preoprocessor. | // | |__j |  __/ | | |  __/ |  | | (__  | |  | |_| | | | | (__| l_| | (_) | | | | | l__| |\ V /  __/ | | | | (_) | (_| | (_| || | | | | (_| | | ||||||
|  | //  \____/ \___}_l l_l\___}_l  l_l\___| l_l   \__,_l_l l_l\___}\__}_l\___/l_l l_l  \____/  \_/ \___}_l l_l_l\___/ \__,_l\__,_l|_|_| |_|\__, | | ||||||
| // Where the signature would be defined using: | // This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in:                                            __| | | ||||||
| #define GEN_TYPE_TO_EXP(type) (* (type*)NULL) | // https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md                            {___/ | ||||||
|  | // Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible. | ||||||
|  |  | ||||||
| #define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly. | #define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly. | ||||||
|  |  | ||||||
| @@ -314,25 +315,23 @@ | |||||||
| #define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , ) | #define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , ) | ||||||
| //                                                          ^ Selects the comma                              ^ is the type                             ^ is the function                             ^ Insert a comma | //                                                          ^ Selects the comma                              ^ is the type                             ^ is the function                             ^ Insert a comma | ||||||
| // The slot won't exist if that comma is not found.                                                                                                                                                  | | // The slot won't exist if that comma is not found.                                                                                                                                                  | | ||||||
| //                                                                                                                                                                                                   | |  | ||||||
| // This  is the same as above but it does not insert a comma                                                                                                                                         V no comma here. | // For the occastion where an expression didn't resolve to a selection option the "default: <value>" wilbe set to: | ||||||
| #define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ), , ) | struct NO_RESOLVED_GENERIC_SELECTION { | ||||||
| // Needed for the last slot as they don't allow trailing commas. | 	unsigned long long failure; | ||||||
|  | }; | ||||||
|  | struct NO_RESOLVED_GENERIC_SELECTION const gen_generic_selection_fail = {}; | ||||||
|  | // Which will provide the message:  error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer | ||||||
| // ---------------------------------------------------------------------------------------------------------------------------------- | // ---------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| // Below are generated on demand for an overlaod depdendent on a type: | // Below are generated on demand for an overlaod depdendent on a type: | ||||||
| // ---------------------------------------------------------------------------------------------------------------------------------- | // -----------------------------------------------------------------------------------------------------#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic(       k | ||||||
| #define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic(           \ | #define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic(       \ | ||||||
| (selector_arg), /* Select Via Expression*/                               \ | (selector_arg), /* Select Via Expression*/                           \ | ||||||
|   /* Extendibility slots: */                                             \ |   /* Extendibility slots: */                                         \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ | 	default: gen_generic_selection_fail                              \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ |  | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ |  | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ |  | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )     \ |  | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_1 ) \ |  | ||||||
| ) GEN_RESOLVED_FUNCTION_CALL( selector_arg ) | ) GEN_RESOLVED_FUNCTION_CALL( selector_arg ) | ||||||
| // ---------------------------------------------------------------------------------------------------------------------------------- | // ---------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| @@ -355,17 +354,18 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u | |||||||
|  |  | ||||||
| // If using an Editor with support for syntax hightlighting macros: HASH__ARGS_SIG_1 and HASH_ARGS_SIG_2 should show color highlighting indicating the slot is enabled, | // If using an Editor with support for syntax hightlighting macros: HASH__ARGS_SIG_1 and HASH_ARGS_SIG_2 should show color highlighting indicating the slot is enabled, | ||||||
| // or, "defined" for usage during the compilation pass that handles the _Generic instrinsic. | // or, "defined" for usage during the compilation pass that handles the _Generic instrinsic. | ||||||
| #define hash( function_arguments ) _Generic(                        \ | #define hash( function_arguments ) _Generic(                   \ | ||||||
| (function_arguments), /* Select Via Expression*/                    \ | (function_arguments), /* Select Via Expression*/               \ | ||||||
|   /* Extendibility slots: */                                        \ |   /* Extendibility slots: */                                   \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 )      \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 ) \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( HASH__ARGS_SIG_8 ) \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_8 ) \ | ||||||
|  | 	default: gen_generic_selection_fail                        \ | ||||||
| ) GEN_RESOLVED_FUNCTION_CALL( function_arguments ) | ) GEN_RESOLVED_FUNCTION_CALL( function_arguments ) | ||||||
|  |  | ||||||
| // Additional Variations: | // Additional Variations: | ||||||
| @@ -376,7 +376,8 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u | |||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )        \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )        \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 )        \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 )        \ | ||||||
| 	...                                                                     \ | 	...                                                                     \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_N )    \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N )         \ | ||||||
|  | 	default: gen_generic_selection_fail                                     \ | ||||||
| ) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ ) | ) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ ) | ||||||
|  |  | ||||||
| // If the function does not take the arugment as a parameter: | // If the function does not take the arugment as a parameter: | ||||||
| @@ -385,9 +386,13 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u | |||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )       \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 )       \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 )       \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 )       \ | ||||||
| 	/* ... */                                                              \ | 	/* ... */                                                              \ | ||||||
| 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_N )   \ | 	GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N )        \ | ||||||
|  | 	default: gen_generic_selection_fail                                    \ | ||||||
| ) GEN_RESOLVED_FUNCTION_CALL() | ) GEN_RESOLVED_FUNCTION_CALL() | ||||||
|  |  | ||||||
|  | // Used to keep the _Generic keyword happy as bare types are not considered "expressions" | ||||||
|  | #define GEN_TYPE_TO_EXP(type) (* (type*)NULL) | ||||||
|  |  | ||||||
| // typedef void* GEN_GenericExampleType; | // typedef void* GEN_GenericExampleType; | ||||||
| // GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType ); | // GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType ); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -46,6 +46,7 @@ void const* mem_find( void const* data, u8 c, ssize n ) | |||||||
|  |  | ||||||
| #define GEN_HEAP_STATS_MAGIC 0xDEADC0DE | #define GEN_HEAP_STATS_MAGIC 0xDEADC0DE | ||||||
|  |  | ||||||
|  | typedef struct _heap_stats _heap_stats; | ||||||
| struct _heap_stats | struct _heap_stats | ||||||
| { | { | ||||||
| 	u32 magic; | 	u32 magic; | ||||||
| @@ -80,6 +81,7 @@ void heap_stats_check( void ) | |||||||
| 	GEN_ASSERT( _heap_stats_info.alloc_count == 0 ); | 	GEN_ASSERT( _heap_stats_info.alloc_count == 0 ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typedef struct _heap_alloc_info _heap_alloc_info; | ||||||
| struct _heap_alloc_info | struct _heap_alloc_info | ||||||
| { | { | ||||||
| 	ssize    size; | 	ssize    size; | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ enum | |||||||
| 	GEN_FMT_INTS = GEN_FMT_CHAR | GEN_FMT_SHORT | GEN_FMT_INT | GEN_FMT_LONG | GEN_FMT_LLONG | GEN_FMT_SIZE | GEN_FMT_INTPTR | 	GEN_FMT_INTS = GEN_FMT_CHAR | GEN_FMT_SHORT | GEN_FMT_INT | GEN_FMT_LONG | GEN_FMT_LLONG | GEN_FMT_SIZE | GEN_FMT_INTPTR | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | typedef struct _format_info _format_info; | ||||||
| struct _format_info | struct _format_info | ||||||
| { | { | ||||||
| 	s32 base; | 	s32 base; | ||||||
| @@ -429,7 +430,7 @@ neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_lis | |||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				String gen_str = String { va_arg( va, char*) }; | 				String gen_str = { va_arg( va, char*) }; | ||||||
|  |  | ||||||
| 				info.precision = string_length(gen_str); | 				info.precision = string_length(gen_str); | ||||||
| 				len            = _print_string( text, remaining, &info, gen_str ); | 				len            = _print_string( text, remaining, &info, gen_str ); | ||||||
|   | |||||||
| @@ -7,17 +7,21 @@ | |||||||
|  |  | ||||||
| String string_make_length( AllocatorInfo allocator, char const* str, ssize length ) | String string_make_length( AllocatorInfo allocator, char const* str, ssize length ) | ||||||
| { | { | ||||||
| 	constexpr ssize header_size = sizeof( StringHeader ); | 	ssize const header_size = sizeof( StringHeader ); | ||||||
|  |  | ||||||
| 	s32   alloc_size = header_size + length + 1; | 	s32   alloc_size = header_size + length + 1; | ||||||
| 	void* allocation = alloc( allocator, alloc_size ); | 	void* allocation = alloc( allocator, alloc_size ); | ||||||
|  |  | ||||||
| 	if ( allocation == nullptr ) | 	if ( allocation == nullptr ) { | ||||||
| 		return { nullptr }; | 		String null_string = {nullptr}; | ||||||
|  | 		return null_string; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	StringHeader& | 	StringHeader* | ||||||
| 	header = * rcast(StringHeader*, allocation); | 	header = rcast(StringHeader*, allocation); | ||||||
| 	header = { allocator, length, length }; | 	header->Allocator = allocator; | ||||||
|  | 	header->Capacity  = length; | ||||||
|  | 	header->Length    = length; | ||||||
|  |  | ||||||
| 	String  result = { rcast( char*, allocation) + header_size }; | 	String  result = { rcast( char*, allocation) + header_size }; | ||||||
|  |  | ||||||
| @@ -33,14 +37,15 @@ String string_make_length( AllocatorInfo allocator, char const* str, ssize lengt | |||||||
|  |  | ||||||
| String string_make_reserve( AllocatorInfo allocator, ssize capacity ) | String string_make_reserve( AllocatorInfo allocator, ssize capacity ) | ||||||
| { | { | ||||||
| 	constexpr ssize header_size = sizeof( StringHeader ); | 	ssize const header_size = sizeof( StringHeader ); | ||||||
|  |  | ||||||
| 	s32   alloc_size = header_size + capacity + 1; | 	s32   alloc_size = header_size + capacity + 1; | ||||||
| 	void* allocation = alloc( allocator, alloc_size ); | 	void* allocation = alloc( allocator, alloc_size ); | ||||||
|  |  | ||||||
| 	if ( allocation == nullptr ) | 	if ( allocation == nullptr ) { | ||||||
| 		return { nullptr }; | 		String null_string = {nullptr}; | ||||||
|  | 		return null_string; | ||||||
|  | 	} | ||||||
| 	mem_set( allocation, 0, alloc_size ); | 	mem_set( allocation, 0, alloc_size ); | ||||||
|  |  | ||||||
| 	StringHeader* | 	StringHeader* | ||||||
|   | |||||||
| @@ -7,12 +7,12 @@ | |||||||
|  |  | ||||||
| struct StrC; | struct StrC; | ||||||
|  |  | ||||||
|  | StrC        to_strc_from_c_str       (char const* bad_string); | ||||||
| bool        strc_are_equal           (StrC lhs, StrC rhs); | bool        strc_are_equal           (StrC lhs, StrC rhs); | ||||||
| char const* strc_back                (StrC str); | char const* strc_back                (StrC str); | ||||||
| bool        strc_contains            (StrC str, StrC substring); | bool        strc_contains            (StrC str, StrC substring); | ||||||
| StrC        strc_duplicate           (StrC str, AllocatorInfo allocator); | StrC        strc_duplicate           (StrC str, AllocatorInfo allocator); | ||||||
| b32         strc_starts_with         (StrC str, StrC substring); | b32         strc_starts_with         (StrC str, StrC substring); | ||||||
| StrC        strc_to_str              (char const* bad_string); |  | ||||||
| StrC        strc_visualize_whitespace(StrC str, AllocatorInfo allocator); | StrC        strc_visualize_whitespace(StrC str, AllocatorInfo allocator); | ||||||
|  |  | ||||||
| // Constant string with length. | // Constant string with length. | ||||||
|   | |||||||
| @@ -41,13 +41,13 @@ CodeBody gen_ecode( char const* path, bool use_c_definition = false ) | |||||||
| 	if (use_c_definition) | 	if (use_c_definition) | ||||||
| 	{ | 	{ | ||||||
| 		enum_code = parse_enum(token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries), | 		enum_code = parse_enum(token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries), | ||||||
| 			"enum CodeType enum_underlying(u32) { <entries> CT_NumTypes };" | 			"enum CodeType enum_underlying(u32) { <entries> CT_NumTypes, CT_UnderlyingType = GEN_U32_MAX };" | ||||||
| 		)); | 		)); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		enum_code = parse_enum(token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries), | 		enum_code = parse_enum(token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries), | ||||||
| 			"enum CodeType : u32 { <entries> CT_NumTypes };" | 			"enum CodeType : u32 { <entries> CT_NumTypes, CT_UnderlyingType = GEN_U32_MAX };" | ||||||
| 		)); | 		)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -140,7 +140,8 @@ CodeBody gen_eoperator( char const* path, bool use_c_definition = false ) | |||||||
| 			enum Operator enum_underlying(u32) | 			enum Operator enum_underlying(u32) | ||||||
| 			{ | 			{ | ||||||
| 				<entries> | 				<entries> | ||||||
| 				NumOps | 				Op_NumOps, | ||||||
|  | 				Op_UnderlyingType = GEN_U32_MAX | ||||||
| 			}; | 			}; | ||||||
| 		))); | 		))); | ||||||
| 	#pragma pop_macro("enum_underlying") | 	#pragma pop_macro("enum_underlying") | ||||||
| @@ -151,7 +152,8 @@ CodeBody gen_eoperator( char const* path, bool use_c_definition = false ) | |||||||
| 			enum Operator : u32 | 			enum Operator : u32 | ||||||
| 			{ | 			{ | ||||||
| 				<entries> | 				<entries> | ||||||
| 				NumOps | 				Op_NumOps, | ||||||
|  | 				Op_UnderlyingType = GEN_U32_MAX | ||||||
| 			}; | 			}; | ||||||
| 		))); | 		))); | ||||||
| 	} | 	} | ||||||
| @@ -233,7 +235,8 @@ CodeBody gen_especifier( char const* path, bool use_c_definition = false ) | |||||||
| 			enum Specifier enum_underlying(u32) | 			enum Specifier enum_underlying(u32) | ||||||
| 			{ | 			{ | ||||||
| 				<entries> | 				<entries> | ||||||
| 				Spec_NumSpecifiers | 				Spec_NumSpecifiers, | ||||||
|  | 				Spec_UnderlyingType = GEN_U32_MAX | ||||||
| 			}; | 			}; | ||||||
| 		))); | 		))); | ||||||
| 	#pragma pop_macro("enum_underlying") | 	#pragma pop_macro("enum_underlying") | ||||||
| @@ -244,7 +247,8 @@ CodeBody gen_especifier( char const* path, bool use_c_definition = false ) | |||||||
| 			enum Specifier : u32 | 			enum Specifier : u32 | ||||||
| 			{ | 			{ | ||||||
| 				<entries> | 				<entries> | ||||||
| 				Spec_NumSpecifiers | 				Spec_NumSpecifiers, | ||||||
|  | 				Spec_UnderlyingType = GEN_U32_MAX | ||||||
| 			}; | 			}; | ||||||
| 		))); | 		))); | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user