mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 22:40:54 -07:00 
			
		
		
		
	Compare commits
	
		
			71 Commits
		
	
	
		
			v0.19-Alph
			...
			9b059dca47
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9b059dca47 | |||
| 46562d54e7 | |||
| ec07c70dcf | |||
| 63dd77237a | |||
| cf3908c6f0 | |||
| 266163557f | |||
| 8bb2bc7b1b | |||
| a3407c14d5 | |||
| 47b9c37e94 | |||
| 1c3134218e | |||
| a3e7ec4c72 | |||
| cae1555b11 | |||
| f7709bb64e | |||
| 3a55af9ce4 | |||
| 6081834687 | |||
| a3548a5bd3 | |||
| d686831a7c | |||
| ba1dd1894a | |||
| e00b2f8afb | |||
| 72d088c566 | |||
| c6fba23173 | |||
| d45908fb32 | |||
| a7c9dad9fd | |||
| 63ebd0d094 | |||
| f28ae57f16 | |||
| 2fe708e4be | |||
| 69a9abcd59 | |||
| defe42c15c | |||
| 05e65aa464 | |||
| 8f47f3b30f | |||
| 0bad61fda6 | |||
| ea18792373 | |||
| 16b8a3a164 | |||
| 5b0079fb0c | |||
| 9321a04ebc | |||
| 9b68791e38 | |||
| 2dcc968c39 | |||
| c38b077c37 | |||
| f9b5029e64 | |||
| 2b24511f7d | |||
| 5cd69e1742 | |||
| 007bfa0cb0 | |||
| 37c33ffb3e | |||
| 937235b776 | |||
| f9c21ebc04 | |||
| fec709cc76 | |||
| 80cb3f4eca | |||
| 9e88cb8724 | |||
| f61c1c560d | |||
| 8ef982003a | |||
| 31691b1466 | |||
| ed0c0422ad | |||
| e5acac1d18 | |||
| c7b072266f | |||
| a96d03eaed | |||
| 0b4ccac8f9 | |||
| 31a3609b28 | |||
| fbdb870986 | |||
| 6d04165b96 | |||
| cc245cc263 | |||
| 06deb1e836 | |||
| 5527a27f7b | |||
| a67fdef20a | |||
| 056a5863b8 | |||
| 79eb5f1f76 | |||
| c6cb583518 | |||
| 34eec66f35 | |||
| 4137ebfbd8 | |||
| 5958dd2055 | |||
| 163ad0a511 | |||
| e3c2a577ba | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -31,3 +31,4 @@ project/auxillary/vis_ast/dependencies/temp | |||||||
| test/gen/original | test/gen/original | ||||||
| singleheader/gen/scratch.hpp | singleheader/gen/scratch.hpp | ||||||
| test/gen/scratch.cpp | test/gen/scratch.cpp | ||||||
|  | gen_c_library/gen | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -37,7 +37,26 @@ | |||||||
| 		"propidl.h": "c", | 		"propidl.h": "c", | ||||||
| 		"android_native_app_glue.h": "c", | 		"android_native_app_glue.h": "c", | ||||||
| 		"raylib.h": "c", | 		"raylib.h": "c", | ||||||
| 		"*.m": "cpp" | 		"*.m": "cpp", | ||||||
|  | 		"atomic": "cpp", | ||||||
|  | 		"gen.h": "c", | ||||||
|  | 		"string_ops.hpp": "c", | ||||||
|  | 		"assert.h": "c", | ||||||
|  | 		"intrin.h": "c", | ||||||
|  | 		"bit": "cpp", | ||||||
|  | 		"cmath": "cpp", | ||||||
|  | 		"cstddef": "cpp", | ||||||
|  | 		"cstdint": "cpp", | ||||||
|  | 		"cstdio": "cpp", | ||||||
|  | 		"cstdlib": "cpp", | ||||||
|  | 		"cstring": "cpp", | ||||||
|  | 		"ctime": "cpp", | ||||||
|  | 		"cwchar": "cpp", | ||||||
|  | 		"iosfwd": "cpp", | ||||||
|  | 		"new": "cpp", | ||||||
|  | 		"typeinfo": "cpp", | ||||||
|  | 		"unordered_map": "cpp", | ||||||
|  | 		"xstddef": "cpp" | ||||||
| 	}, | 	}, | ||||||
| 	"C_Cpp.intelliSenseEngineFallback": "disabled", | 	"C_Cpp.intelliSenseEngineFallback": "disabled", | ||||||
| 	"mesonbuild.configureOnOpen": true, | 	"mesonbuild.configureOnOpen": true, | ||||||
|   | |||||||
| @@ -552,7 +552,7 @@ Serialization: | |||||||
| Fields: | Fields: | ||||||
|  |  | ||||||
| ```cpp | ```cpp | ||||||
| SpecifierT     ArrSpecs[ AST::ArrSpecs_Cap ]; | SpecifierT     ArrSpecs[ AST_ArrSpecs_Cap ]; | ||||||
| CodeSpecifiers NextSpecs; | CodeSpecifiers NextSpecs; | ||||||
| Code           Prev; | Code           Prev; | ||||||
| Code           Next; | Code           Next; | ||||||
|   | |||||||
| @@ -25,6 +25,8 @@ This library was written in a subset of C++ where the following are not used at | |||||||
| * Exceptions | * Exceptions | ||||||
|  |  | ||||||
| Polymorphic & Member-functions are used as an ergonomic choice, along with a conserative use of operator overloads.   | Polymorphic & Member-functions are used as an ergonomic choice, along with a conserative use of operator overloads.   | ||||||
|  | The base library itself does not use anything but C-like features to allow for generating a derviative compatiable with C (WIP). | ||||||
|  |  | ||||||
| There are only 4 template definitions in the entire library. (`Array<Type>`, `Hashtable<Type>`, `swap<Type>`, and `AST/Code::cast<Type>`) | There are only 4 template definitions in the entire library. (`Array<Type>`, `Hashtable<Type>`, `swap<Type>`, and `AST/Code::cast<Type>`) | ||||||
|  |  | ||||||
| Two generic templated containers are used throughout the library: | Two generic templated containers are used throughout the library: | ||||||
| @@ -99,7 +101,7 @@ union { | |||||||
|     }; |     }; | ||||||
|     StringCached  Content;          // Attributes, Comment, Execution, Include |     StringCached  Content;          // Attributes, Comment, Execution, Include | ||||||
|     struct { |     struct { | ||||||
|         SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers |         SpecifierT ArrSpecs[AST_ArrSpecs_Cap]; // Specifiers | ||||||
|         AST*       NextSpecs;                   // Specifiers |         AST*       NextSpecs;                   // Specifiers | ||||||
|     }; |     }; | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										492
									
								
								gen_c_library/c_library.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										492
									
								
								gen_c_library/c_library.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,492 @@ | |||||||
|  | #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
|  | #define GEN_ENFORCE_STRONG_CODE_TYPES | ||||||
|  | #define GEN_EXPOSE_BACKEND | ||||||
|  | #define GEN_SUPPORT_CPP_MEMBER_FEATURES 1 | ||||||
|  | #define GEN_SUPPORT_CPP_REFERENCES      1 | ||||||
|  | #include "../project/gen.cpp" | ||||||
|  |  | ||||||
|  | #include "helpers/push_ignores.inline.hpp" | ||||||
|  | #include "helpers/helper.hpp" | ||||||
|  |  | ||||||
|  | GEN_NS_BEGIN | ||||||
|  | #include "helpers/push_container_defines.inline.hpp" | ||||||
|  | #include "dependencies/parsing.cpp" | ||||||
|  | #include "helpers/pop_container_defines.inline.hpp" | ||||||
|  | GEN_NS_END | ||||||
|  |  | ||||||
|  | #include "auxillary/builder.hpp" | ||||||
|  | #include "auxillary/builder.cpp" | ||||||
|  | #include "auxillary/scanner.hpp" | ||||||
|  |  | ||||||
|  | #include <cstdlib>   // for system() | ||||||
|  |  | ||||||
|  | #include "components/memory.fixed_arena.hpp" | ||||||
|  | #include "components/misc.hpp" | ||||||
|  | #include "components/containers.array.hpp" | ||||||
|  | #include "components/containers.hashtable.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | constexpr char const* generation_notice = | ||||||
|  | "// This file was generated automatially by gencpp's c_library.cpp  " | ||||||
|  | "(See: https://github.com/Ed94/gencpp)\n\n"; | ||||||
|  |  | ||||||
|  | constexpr StrC roll_own_dependencies_guard_start = txt(R"( | ||||||
|  | //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. | ||||||
|  | // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl | ||||||
|  | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC roll_own_dependencies_guard_end = txt(R"( | ||||||
|  | // GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  | #endif | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC implementation_guard_start = txt(R"( | ||||||
|  | #pragma region GENCPP IMPLEMENTATION GUARD | ||||||
|  | #if defined(GEN_IMPLEMENTATION) && ! defined(GEN_IMPLEMENTED) | ||||||
|  | #	define GEN_IMPLEMENTED | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC implementation_guard_end = txt(R"( | ||||||
|  | #endif | ||||||
|  | #pragma endregion GENCPP IMPLEMENTATION GUARD | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | void format_file( char const* path ) | ||||||
|  | { | ||||||
|  | 	String resolved_path = String::make(GlobalAllocator, to_strc_from_c_str(path)); | ||||||
|  |  | ||||||
|  | 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | ||||||
|  | 	style_arg.append("../scripts/.clang-format "); | ||||||
|  |  | ||||||
|  | 	// Need to execute clang format on the generated file to get it to match the original. | ||||||
|  | 	#define clang_format      "clang-format " | ||||||
|  | 	#define cf_format_inplace "-i " | ||||||
|  | 	#define cf_verbose        "-verbose " | ||||||
|  | 	String command = String::make( GlobalAllocator, clang_format ); | ||||||
|  | 	command.append( cf_format_inplace ); | ||||||
|  | 	command.append( cf_verbose ); | ||||||
|  | 	command.append( style_arg ); | ||||||
|  | 	command.append( resolved_path ); | ||||||
|  | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
|  | 		system( command ); | ||||||
|  | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
|  | 	#undef cf_cmd | ||||||
|  | 	#undef cf_format_inplace | ||||||
|  | 	#undef cf_style | ||||||
|  | 	#undef cf_verbse | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code dump_to_scratch_and_retireve( Code code ) | ||||||
|  | { | ||||||
|  | 	Builder ecode_file_temp = Builder::open("gen/scratch.hpp"); | ||||||
|  | 	ecode_file_temp.print(code); | ||||||
|  | 	ecode_file_temp.write(); | ||||||
|  | 	format_file("gen/scratch.hpp"); | ||||||
|  | 	Code result = scan_file( "gen/scratch.hpp" ); | ||||||
|  | 	remove("gen/scratch.hpp"); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CodeBody parse_file( const char* path ) | ||||||
|  | { | ||||||
|  | 	FileContents file = file_read_contents( GlobalAllocator, true, path ); | ||||||
|  | 	CodeBody     code = parse_global_body( { file.size, (char const*)file.data } ); | ||||||
|  | 	log_fmt("\nParsed: %s\n", path); | ||||||
|  | 	return code; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int gen_main() | ||||||
|  | { | ||||||
|  | #define project_dir "../project/" | ||||||
|  | 	gen::init(); | ||||||
|  |  | ||||||
|  | 	PreprocessorDefines.append(txt("GEN_API_C_BEGIN")); | ||||||
|  | 	PreprocessorDefines.append(txt("GEN_API_C_END")); | ||||||
|  | 	PreprocessorDefines.append(txt("HashTable(")); | ||||||
|  |  | ||||||
|  | 	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 c_library_header_start = scan_file( "components/header_start.hpp" ); | ||||||
|  |  | ||||||
|  | 	Builder | ||||||
|  | 	header = Builder::open( "gen/gen.h" ); | ||||||
|  | 	header.print_fmt( generation_notice ); | ||||||
|  | 	header.print_fmt("#pragma once\n\n"); | ||||||
|  | 	header.print( push_ignores ); | ||||||
|  |  | ||||||
|  | 	// Headers | ||||||
|  | 	{ | ||||||
|  | 		header.print( c_library_header_start ); | ||||||
|  |  | ||||||
|  | #pragma region Scan, Parse, and Generate Components | ||||||
|  | 		Code types      = scan_file( project_dir "components/types.hpp" ); | ||||||
|  | 		Code ast        = scan_file( project_dir "components/ast.hpp" ); | ||||||
|  | 		Code ast_types  = scan_file( project_dir "components/ast_types.hpp" ); | ||||||
|  | 		Code code_types = scan_file( project_dir "components/code_types.hpp" ); | ||||||
|  | 		Code interface  = scan_file( project_dir "components/interface.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/ECode.csv" ); | ||||||
|  | 		CodeBody eoperator   = gen_eoperator ( project_dir "enums/EOperator.csv" ); | ||||||
|  | 		CodeBody especifier  = gen_especifier( project_dir "enums/ESpecifier.csv" ); | ||||||
|  | 		CodeBody ast_inlines = gen_ast_inlines(); | ||||||
|  | #pragma endregion Scan, Parse, and Generate Components | ||||||
|  |  | ||||||
|  | #pragma region Scan, Parse, and Generate Dependencies | ||||||
|  | 		Code platform     = scan_file( project_dir "dependencies/platform.hpp" ); | ||||||
|  | 		Code macros       = scan_file( project_dir "dependencies/macros.hpp" ); | ||||||
|  | 		Code basic_types  = scan_file( project_dir "dependencies/basic_types.hpp" ); | ||||||
|  | 		Code debug        = scan_file( project_dir "dependencies/debug.hpp" ); | ||||||
|  | 		Code string_ops   = scan_file( project_dir "dependencies/string_ops.hpp" ); | ||||||
|  | 		Code hashing      = scan_file( project_dir "dependencies/hashing.hpp" ); | ||||||
|  | 		Code timing       = scan_file( project_dir "dependencies/timing.hpp" ); | ||||||
|  |  | ||||||
|  | 		CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); | ||||||
|  | 		CodeBody memory        = def_body(CT_Global_Body); | ||||||
|  | 		for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case CT_Using: | ||||||
|  | 				{ | ||||||
|  | 					log_fmt("REPLACE THIS MANUALLY: %SC\n", entry->Name); | ||||||
|  | 					CodeUsing   using_ver   = cast(CodeUsing, entry); | ||||||
|  | 					CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); | ||||||
|  |  | ||||||
|  | 					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); | ||||||
|  | 					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); | ||||||
|  | 					} | ||||||
|  | 					// for ( StrC id : to_rename ) if (fn->Name.is_equal(id)) { | ||||||
|  | 					// 	Array(CodeFn) list = * needs_selectors.get(id); | ||||||
|  | 					// 	list.append(rename_function_to_unique_symbol(fn)); | ||||||
|  | 					// } | ||||||
|  | 					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_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: | ||||||
|  | 						{ | ||||||
|  | 							ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), body_entry, body, new_body ); | ||||||
|  | 						} | ||||||
|  | 						break; | ||||||
|  |  | ||||||
|  | 						default: | ||||||
|  | 							new_body.append(body_entry); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					entry->Body = new_body; | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case CT_Preprocess_If: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), entry, parsed_memory, memory ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_REFERENCES"), 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        = def_body(CT_Global_Body); | ||||||
|  | 		for ( Code entry = printing_parsed.begin(); entry != printing_parsed.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case CT_Preprocess_IfDef: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, printing_parsed, printing ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					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; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" ); | ||||||
|  | 		CodeBody strings        = def_body(CT_Global_Body); | ||||||
|  | 		for ( Code entry = parsed_strings.begin(); entry != parsed_strings.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case CT_Preprocess_If: | ||||||
|  | 				{ | ||||||
|  | 					CodePreprocessCond cond = cast(CodePreprocessCond, entry); | ||||||
|  | 					if (cond->Content.starts_with(txt("GEN_COMPILER_C || ! GEN_SUPPORT_CPP_MEMBER_FEATURES"))) | ||||||
|  | 					{ | ||||||
|  | 						for (; entry != end(parsed_strings) && entry->Type != CT_Typedef; ++ entry) {} | ||||||
|  | 						strings.append(entry); | ||||||
|  | 						strings.append(fmt_newline); | ||||||
|  |  | ||||||
|  | 						for (; entry != end(parsed_strings) && entry->Type != CT_Preprocess_EndIf; ++ entry) {} | ||||||
|  | 						++ entry; | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					bool found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP"), entry, parsed_strings, strings); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_REFERENCES"), entry, parsed_strings, strings ); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				case CT_Preprocess_IfDef: | ||||||
|  | 				{ | ||||||
|  | 					ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_strings, strings ); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				case CT_Struct_Fwd: | ||||||
|  | 				{ | ||||||
|  | 					if ( entry->Name.is_equal(txt("String")) ) | ||||||
|  | 					{ | ||||||
|  | 						CodeTypedef c_def = parse_typedef(code( typedef char* String; )); | ||||||
|  | 						strings.append(c_def); | ||||||
|  | 						strings.append(fmt_newline); | ||||||
|  | 						++ entry; | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 					strings.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				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"), body_entry, body, new_body ); | ||||||
|  | 							if (found) break; | ||||||
|  |  | ||||||
|  | 							new_body.append(body_entry); | ||||||
|  | 						} | ||||||
|  | 						break; | ||||||
|  | 						default: | ||||||
|  | 							new_body.append(body_entry); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					entry->Body = new_body; | ||||||
|  | 					strings.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				case CT_Typedef: | ||||||
|  | 				{ | ||||||
|  | 					StrC name_string_table = txt("StringTable"); | ||||||
|  |  | ||||||
|  | 					CodeTypedef td = cast(CodeTypedef, entry); | ||||||
|  | 					if (td->Name.contains(name_string_table)) | ||||||
|  | 					{ | ||||||
|  | 						CodeBody ht = gen_hashtable(txt("StrC"), name_string_table); | ||||||
|  | 						strings.append(ht); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					strings.append(td); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 					strings.append(entry); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		CodeBody parsed_filesystem = parse_file( project_dir "dependencies/filesystem.hpp" ); | ||||||
|  | 		CodeBody filesystem        = def_body(CT_Global_Body); | ||||||
|  | 		for ( Code entry = parsed_filesystem.begin(); entry != parsed_filesystem.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case CT_Preprocess_IfDef: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_filesystem, filesystem ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					filesystem.append(entry); | ||||||
|  | 				} | ||||||
|  | 				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 containers = def_body(CT_Global_Body); | ||||||
|  | 		{ | ||||||
|  | 			CodeBody array_ssize = gen_array(txt("ssize"), txt("Array_ssize")); | ||||||
|  |  | ||||||
|  | 			containers.append( def_pragma(code(region Containers))); | ||||||
|  |  | ||||||
|  | 			// At this point all arrays required should have been defined so its safe to generate the generic selectors. | ||||||
|  | 			containers.append( gen_array_base() ); | ||||||
|  | 			containers.append( gen_array_generic_selection_interface()); | ||||||
|  | 			containers.append( gen_hashtable_base() ); | ||||||
|  | 			containers.append(fmt_newline); | ||||||
|  | 			containers.append( gen_hashtable_generic_selection_interface()); | ||||||
|  |  | ||||||
|  | 			containers.append(array_ssize); | ||||||
|  |  | ||||||
|  | 			containers.append( def_pragma(code(endregion Containers))); | ||||||
|  | 			containers.append(fmt_newline); | ||||||
|  | 		} | ||||||
|  | #pragma endregion Scan, Parse, and Generate Dependencies | ||||||
|  |  | ||||||
|  | #pragma region Print Dependencies | ||||||
|  | 		header.print_fmt( roll_own_dependencies_guard_start ); | ||||||
|  | 		header.print( platform ); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  |  | ||||||
|  | 		header.print( macros ); | ||||||
|  | 		header.print( basic_types ); | ||||||
|  | 		header.print( debug ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(memory) ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(printing)); | ||||||
|  | 		header.print( string_ops ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(containers)); | ||||||
|  | 		header.print( hashing ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(strings)); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(filesystem)); | ||||||
|  | 		header.print( timing ); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_END\n" ); | ||||||
|  | 		header.print_fmt( roll_own_dependencies_guard_end ); | ||||||
|  | #pragma endregion Print Dependencies | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | #region region Print Components | ||||||
|  | 		header.print_fmt("#pragma region Types\n"); | ||||||
|  | 		header.print( types ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( ecode )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( eoperator )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( especifier )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print_fmt("#pragma endregion Types\n\n"); | ||||||
|  | #pragma endregion Print Compoennts | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	header.print( pop_ignores ); | ||||||
|  | 	header.write(); | ||||||
|  |  | ||||||
|  | 	// format_file( "gen/gen.h" ); | ||||||
|  |  | ||||||
|  | 	gen::deinit(); | ||||||
|  | 	return 0; | ||||||
|  | #undef project_dir | ||||||
|  | } | ||||||
							
								
								
									
										417
									
								
								gen_c_library/components/containers.array.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										417
									
								
								gen_c_library/components/containers.array.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,417 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | // Used to know what slot the array will be for generic selection | ||||||
|  | global s32 Array_DefinitionCounter = 0; | ||||||
|  |  | ||||||
|  | CodeBody gen_array_base() | ||||||
|  | { | ||||||
|  | 	CodeTypedef td_header = parse_typedef( code( typedef struct ArrayHeader ArrayHeader; )); | ||||||
|  | 	CodeStruct  header    = parse_struct( code( | ||||||
|  | 		struct ArrayHeader | ||||||
|  | 		{ | ||||||
|  | 			AllocatorInfo Allocator; | ||||||
|  | 			usize         Capacity; | ||||||
|  | 			usize         Num; | ||||||
|  | 		}; | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	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" )); | ||||||
|  |  | ||||||
|  | 	return def_global_body( args( fmt_newline, td_header, header, grow_formula, get_header, fmt_newline ) ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CodeBody gen_array( StrC type, StrC array_name ) | ||||||
|  | { | ||||||
|  | 	String array_type = String::fmt_buf( GlobalAllocator, "%.*s", array_name.Len, array_name.Ptr ); | ||||||
|  | 	String fn         = String::fmt_buf( GlobalAllocator, "%.*s", array_name.Len, array_name.Ptr ); | ||||||
|  | 	// str_to_lower(fn.Data); | ||||||
|  |  | ||||||
|  | #pragma push_macro( "GEN_ASSERT" ) | ||||||
|  | #pragma push_macro( "rcast" ) | ||||||
|  | #pragma push_macro( "cast" ) | ||||||
|  | #pragma push_macro( "typeof" ) | ||||||
|  | #pragma push_macro( "forceinline" ) | ||||||
|  | #undef GEN_ASSERT | ||||||
|  | #undef rcast | ||||||
|  | #undef cast | ||||||
|  | #undef typeof | ||||||
|  | #undef forceinline | ||||||
|  | 	CodeBody result = parse_global_body( token_fmt( "array_type", (StrC)array_type, "fn", (StrC)fn, "type", (StrC)type | ||||||
|  | 	, stringize( | ||||||
|  | 		typedef <type>* <array_type>; | ||||||
|  |  | ||||||
|  | 		<array_type> <fn>_init           ( AllocatorInfo allocator ); | ||||||
|  | 		<array_type> <fn>_init_reserve   ( AllocatorInfo allocator, usize capacity ); | ||||||
|  | 		bool         <fn>_append_array   ( <array_type>*  self, <array_type> other ); | ||||||
|  | 		bool         <fn>_append         ( <array_type>*  self, <type> value ); | ||||||
|  | 		bool         <fn>_append_items   ( <array_type>*  self, <type>* items, usize item_num ); | ||||||
|  | 		bool         <fn>_append_at      ( <array_type>*  self, <type> item, usize idx ); | ||||||
|  | 		bool         <fn>_append_items_at( <array_type>*  self, <type>* items, usize item_num, usize idx ); | ||||||
|  | 		<type>*      <fn>_back           ( <array_type>   self ); | ||||||
|  | 		void         <fn>_clear          ( <array_type>   self ); | ||||||
|  | 		bool         <fn>_fill		     ( <array_type>   self, usize begin, usize end, <type> value ); | ||||||
|  | 		void         <fn>_free           ( <array_type>*  self ); | ||||||
|  | 		bool         <fn>_grow           ( <array_type>*  self, usize min_capacity ); | ||||||
|  | 		usize        <fn>_num            ( <array_type>   self ); | ||||||
|  | 		<type>       <fn>_pop 	         ( <array_type>   self ); | ||||||
|  | 		void         <fn>_remove_at      ( <array_type>   self, usize idx ); | ||||||
|  | 		bool         <fn>_reserve        ( <array_type>*  self, usize new_capacity ); | ||||||
|  | 		bool         <fn>_resize         ( <array_type>*  self, usize num ); | ||||||
|  | 		bool         <fn>_set_capacity   ( <array_type>*  self, usize new_capacity ); | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		<array_type> <fn>_init( AllocatorInfo allocator ) | ||||||
|  | 		{ | ||||||
|  | 			size_t initial_size = array_grow_formula(0); | ||||||
|  | 			return array_init_reserve( <array_type>, allocator, initial_size ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		<array_type> <fn>_init_reserve( AllocatorInfo allocator, usize capacity ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(capacity > 0); | ||||||
|  | 			ArrayHeader* header = rcast(ArrayHeader*, alloc(allocator, sizeof(ArrayHeader) + sizeof(<type>) * capacity)); | ||||||
|  |  | ||||||
|  | 			if (header == nullptr) | ||||||
|  | 				return nullptr; | ||||||
|  |  | ||||||
|  | 			header->Allocator = allocator; | ||||||
|  | 			header->Capacity  = capacity; | ||||||
|  | 			header->Num       = 0; | ||||||
|  |  | ||||||
|  | 			return rcast(<type>*, header + 1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		bool <fn>_append_array( <array_type>* self, <array_type> other ) | ||||||
|  | 		{ | ||||||
|  | 			return array_append_items( * self, (<array_type>)other, <fn>_num(other)); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_append( <array_type>* self, <type> value ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Num == header->Capacity ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! array_grow( self, header->Capacity)) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = array_get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			(* self)[ header->Num ] = value; | ||||||
|  | 			header->Num++; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_append_items( <array_type>* self, <type>* items, usize item_num ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			GEN_ASSERT(items != nullptr); | ||||||
|  | 			GEN_ASSERT(item_num > 0); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Num + item_num > header->Capacity ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! array_grow( self, header->Capacity + item_num )) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = array_get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			mem_copy( (* self) + header->Num, items, sizeof(<type>) * item_num ); | ||||||
|  | 			header->Num += item_num; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_append_at( <array_type>* self, <type> item, usize idx ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( idx >= header->Num ) | ||||||
|  | 				idx = header->Num - 1; | ||||||
|  |  | ||||||
|  | 			if ( idx < 0 ) | ||||||
|  | 				idx = 0; | ||||||
|  |  | ||||||
|  | 			if ( header->Capacity < header->Num + 1 ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! array_grow( self, header->Capacity + 1 ) ) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = array_get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			<array_type> target = (* self) + idx; | ||||||
|  |  | ||||||
|  | 			mem_move( target + 1, target, (header->Num - idx) * sizeof(<type>) ); | ||||||
|  | 			header->Num++; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_append_items_at( <array_type>* self, <type>* items, usize item_num, usize idx ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( idx >= header->Num ) | ||||||
|  | 			{ | ||||||
|  | 				return array_append_items( * self, items, item_num ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if ( item_num > header->Capacity ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! array_grow( self, item_num + header->Capacity ) ) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = array_get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			<type>* target = (* self) + idx + item_num; | ||||||
|  | 			<type>* src    = (* self) + idx; | ||||||
|  |  | ||||||
|  | 			mem_move( target, src, (header->Num - idx) * sizeof(<type>) ); | ||||||
|  | 			mem_copy( src, items, item_num * sizeof(<type>) ); | ||||||
|  | 			header->Num += item_num; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		<type>* <fn>_back( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Num == 0 ) | ||||||
|  | 				return NULL; | ||||||
|  |  | ||||||
|  | 			return self + header->Num - 1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		void <fn>_clear( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( self ); | ||||||
|  | 			header->Num = 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_fill( <array_type> self, usize begin, usize end, <type> value ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(self != nullptr); | ||||||
|  | 			GEN_ASSERT(begin <= end); | ||||||
|  | 			ArrayHeader* header = array_get_header( self ); | ||||||
|  |  | ||||||
|  | 			if ( begin < 0 || end >= header->Num ) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
|  | 			for ( ssize idx = begin; idx < end; idx ++ ) | ||||||
|  | 				self[ idx ] = value; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		void <fn>_free( <array_type>* self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  | 			allocator_free( header->Allocator, header ); | ||||||
|  | 			self = NULL; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_grow( <array_type>* self, usize min_capacity ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			GEN_ASSERT( min_capacity > 0 ); | ||||||
|  | 			ArrayHeader* header       = array_get_header( *self ); | ||||||
|  | 			usize        new_capacity = array_grow_formula( header->Capacity ); | ||||||
|  |  | ||||||
|  | 			if ( new_capacity < min_capacity ) | ||||||
|  | 				new_capacity = min_capacity; | ||||||
|  |  | ||||||
|  | 			return array_set_capacity( self, new_capacity ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		usize <fn>_num( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			return array_get_header(self)->Num; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		<type> <fn>_pop( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( self ); | ||||||
|  | 			GEN_ASSERT( header->Num > 0 ); | ||||||
|  |  | ||||||
|  | 			<type> result = self[ header->Num - 1 ]; | ||||||
|  | 			header->Num--; | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		forceinline | ||||||
|  | 		void <fn>_remove_at( <array_type> self, usize idx ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			ArrayHeader* header = array_get_header( self ); | ||||||
|  | 			GEN_ASSERT( idx < header->Num ); | ||||||
|  |  | ||||||
|  | 			mem_move( self + idx, self + idx + 1, sizeof( <type> ) * ( header->Num - idx - 1 ) ); | ||||||
|  | 			header->Num--; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_reserve( <array_type>* self, usize new_capacity ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			GEN_ASSERT(new_capacity > 0); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Capacity < new_capacity ) | ||||||
|  | 				return array_set_capacity( self, new_capacity ); | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_resize( <array_type>* self, usize num ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			GEN_ASSERT(num > 0); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Capacity < num ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! array_grow( self, num ) ) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = array_get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			header->Num = num; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		bool <fn>_set_capacity( <array_type>* self, usize new_capacity ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT(  self != nullptr); | ||||||
|  | 			GEN_ASSERT(* self != nullptr); | ||||||
|  | 			GEN_ASSERT( new_capacity > 0 ); | ||||||
|  | 			ArrayHeader* header = array_get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( new_capacity == header->Capacity ) | ||||||
|  | 				return true; | ||||||
|  |  | ||||||
|  | 			if ( new_capacity < header->Num ) | ||||||
|  | 			{ | ||||||
|  | 				header->Num = new_capacity; | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			usize        size       = sizeof( ArrayHeader ) + sizeof( <type> ) * new_capacity; | ||||||
|  | 			ArrayHeader* new_header = cast( ArrayHeader*, alloc( header->Allocator, size )); | ||||||
|  |  | ||||||
|  | 			if ( new_header == NULL ) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
|  | 			mem_move( new_header, header, sizeof( ArrayHeader ) + sizeof( <type> ) * header->Num ); | ||||||
|  | 			new_header->Capacity = new_capacity; | ||||||
|  |  | ||||||
|  | 			allocator_free( header->Allocator, & header ); | ||||||
|  |  | ||||||
|  | 			* self = cast( <type>*, new_header + 1 ); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	))); | ||||||
|  | #pragma pop_macro( "GEN_ASSERT" ) | ||||||
|  | #pragma pop_macro( "rcast" ) | ||||||
|  | #pragma pop_macro( "cast" ) | ||||||
|  | #pragma pop_macro( "typeof" ) | ||||||
|  | #pragma pop_macro( "forceinline" ) | ||||||
|  |  | ||||||
|  | 	++ Array_DefinitionCounter; | ||||||
|  | 	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, | ||||||
|  | R"(#define GENERIC_SLOT_<slot>__array_init         <type_delimiter>,  <type_delimiter>_init | ||||||
|  | #define GENERIC_SLOT_<slot>__array_init_reserve    <type_delimiter>,  <type_delimiter>_init_reserve | ||||||
|  | #define GENERIC_SLOT_<slot>__array_append          <type_delimiter>,  <type_delimiter>_append | ||||||
|  | #define GENERIC_SLOT_<slot>__array_append_items    <type_delimiter>,  <type_delimiter>_append_items | ||||||
|  | #define GENERIC_SLOT_<slot>__array_append_at       <type_delimiter>,  <type_delimiter>_append_at | ||||||
|  | #define GENERIC_SLOT_<slot>__array_append_items_at <type_delimiter>,  <type_delimiter>_append_items_at | ||||||
|  | #define GENERIC_SLOT_<slot>__array_back            <type_delimiter>,  <type_delimiter>_back | ||||||
|  | #define GENERIC_SLOT_<slot>__array_clear           <type_delimiter>,  <type_delimiter>_clear | ||||||
|  | #define GENERIC_SLOT_<slot>__array_fill            <type_delimiter>,  <type_delimiter>_fill | ||||||
|  | #define GENERIC_SLOT_<slot>__array_free            <type_delimiter>,  <type_delimiter>_free | ||||||
|  | #define GENERIC_SLOT_<slot>__array_grow            <type_delimiter>*, <type_delimiter>_grow | ||||||
|  | #define GENERIC_SLOT_<slot>__array_num             <type_delimiter>,  <type_delimiter>_num | ||||||
|  | #define GENERIC_SLOT_<slot>__array_pop             <type_delimiter>,  <type_delimiter>_pop | ||||||
|  | #define GENERIC_SLOT_<slot>__array_remove_at       <type_delimiter>,  <type_delimiter>_remove_at | ||||||
|  | #define GENERIC_SLOT_<slot>__array_reserve         <type_delimiter>,  <type_delimiter>_reserve | ||||||
|  | #define GENERIC_SLOT_<slot>__array_resize          <type_delimiter>,  <type_delimiter>_resize | ||||||
|  | #define GENERIC_SLOT_<slot>__array_set_capacity    <type_delimiter>*, <type_delimiter>_set_capacity | ||||||
|  | )" | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	return def_global_body( args( | ||||||
|  | 		def_pragma( string_to_strc( string_fmt_buf( GlobalAllocator, "region %S", array_type ))), | ||||||
|  | 		fmt_newline, | ||||||
|  | 		generic_interface_slot, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		result, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		def_pragma( string_to_strc(string_fmt_buf( GlobalAllocator, "endregion %S", array_type ))), | ||||||
|  | 		fmt_newline | ||||||
|  | 	)); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CodeBody gen_array_generic_selection_interface() | ||||||
|  | { | ||||||
|  | 	CodeBody interface_defines = def_body(CT_Global_Body); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_init"), GenericSel_Direct_Type )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_init_reserve"), GenericSel_Direct_Type )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_append"), GenericSel_By_Ref )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_append_items"), GenericSel_By_Ref )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_back"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_clear"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_fill")) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_free"), GenericSel_By_Ref, GenericSel_One_Arg ) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_grow")) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_num"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_pop"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_remove_at")) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_reserve"), GenericSel_By_Ref) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_resize"), GenericSel_By_Ref) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( Array_DefinitionCounter, txt("array_set_capacity")) ); | ||||||
|  | 	return interface_defines; | ||||||
|  | } | ||||||
							
								
								
									
										434
									
								
								gen_c_library/components/containers.hashtable.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								gen_c_library/components/containers.hashtable.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,434 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  | #include "containers.array.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | global s32 HashTable_DefinitionCounter = 0; | ||||||
|  |  | ||||||
|  | CodeBody gen_hashtable_base() | ||||||
|  | { | ||||||
|  | 	CodeBody struct_def = parse_global_body( code( | ||||||
|  | 		typedef struct HT_FindResult_Def HT_FindResult; | ||||||
|  | 		struct HT_FindResult_Def | ||||||
|  | 		{ | ||||||
|  | 			ssize HashIndex; | ||||||
|  | 			ssize PrevIndex; | ||||||
|  | 			ssize EntryIndex; | ||||||
|  | 		}; | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	Code define_type = untyped_str(txt( | ||||||
|  | R"(#define HashTable(_type) struct _type | ||||||
|  | )" | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	Code define_critical_load_scale = untyped_str(txt("#define HashTable_CriticalLoadScale 0.7f\n")); | ||||||
|  | 	return def_global_body(args(struct_def, define_type, define_critical_load_scale)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CodeBody gen_hashtable( StrC type, StrC hashtable_name ) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	String tbl_type = {(char*) hashtable_name.duplicate(GlobalAllocator).Ptr}; | ||||||
|  | 	String fn       = tbl_type.duplicate(GlobalAllocator); | ||||||
|  | 	// str_to_lower(fn.Data); | ||||||
|  |  | ||||||
|  | 	String name_lower = String::make( GlobalAllocator, hashtable_name ); | ||||||
|  | 	// str_to_lower( name_lower.Data ); | ||||||
|  |  | ||||||
|  | 	String hashtable_entry   = String::fmt_buf( GlobalAllocator, "HTE_%.*s",     hashtable_name.Len, hashtable_name.Ptr ); | ||||||
|  | 	String entry_array_name  = String::fmt_buf( GlobalAllocator, "Arr_HTE_%.*s", hashtable_name.Len, hashtable_name.Ptr ); | ||||||
|  | 	String entry_array_fn_ns = String::fmt_buf( GlobalAllocator, "arr_hte_%.*s", name_lower.length(), name_lower.Data ); | ||||||
|  |  | ||||||
|  | 	CodeBody hashtable_types = parse_global_body( token_fmt( | ||||||
|  | 		"type",        (StrC) type, | ||||||
|  | 		"tbl_name",    (StrC) hashtable_name, | ||||||
|  | 		"tbl_type",    (StrC) tbl_type, | ||||||
|  | 	stringize( | ||||||
|  | 		typedef struct HashTable_<type> <tbl_type>; | ||||||
|  | 		typedef struct HTE_<tbl_name> HTE_<tbl_name>; | ||||||
|  | 		struct HTE_<tbl_name> { | ||||||
|  | 			u64    Key; | ||||||
|  | 			ssize  Next; | ||||||
|  | 			<type> Value; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		typedef void (* <tbl_type>_MapProc)    ( <tbl_type> self, u64 key, <type> value ); | ||||||
|  | 		typedef void (* <tbl_type>_MapMutProc) ( <tbl_type> self, u64 key, <type>* value ); | ||||||
|  | 	))); | ||||||
|  |  | ||||||
|  | 	CodeBody entry_array = gen_array( hashtable_entry, entry_array_name ); | ||||||
|  |  | ||||||
|  | #pragma push_macro( "GEN_ASSERT" ) | ||||||
|  | #pragma push_macro( "GEN_ASSERT_NOT_NULL" ) | ||||||
|  | #pragma push_macro( "rcast" ) | ||||||
|  | #pragma push_macro( "cast" ) | ||||||
|  | #pragma push_macro( "typeof" ) | ||||||
|  | #pragma push_macro( "forceinline" ) | ||||||
|  | #undef GEN_ASSERT | ||||||
|  | #undef GEN_ASSERT_NOT_NULL | ||||||
|  | #undef GEN_ASSERT | ||||||
|  | #undef rcast | ||||||
|  | #undef cast | ||||||
|  | #undef typeof | ||||||
|  | #undef forceinline | ||||||
|  | 	CodeBody hashtable_def = parse_global_body( token_fmt( | ||||||
|  | 		"type",           (StrC) type, | ||||||
|  | 		"tbl_name",       (StrC) hashtable_name, | ||||||
|  | 		"tbl_type",       (StrC) tbl_type, | ||||||
|  | 		"fn",             (StrC) fn, | ||||||
|  | 		"entry_type",     (StrC) hashtable_entry, | ||||||
|  | 		"array_entry",    (StrC) entry_array_name, | ||||||
|  | 		"fn_array",       (StrC) entry_array_fn_ns, | ||||||
|  | 	stringize( | ||||||
|  | 		struct HashTable_<type> { | ||||||
|  | 			Array_ssize   Hashes; | ||||||
|  | 			<array_entry> Entries; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		<tbl_type> <fn>_init        ( AllocatorInfo allocator ); | ||||||
|  | 		<tbl_type> <fn>_init_reserve( AllocatorInfo allocator, ssize num ); | ||||||
|  | 		void       <fn>_clear       ( <tbl_type>  self ); | ||||||
|  | 		void       <fn>_destroy     ( <tbl_type>* self ); | ||||||
|  | 		<type>*    <fn>_get         ( <tbl_type>  self, u64 key ); | ||||||
|  | 		void       <fn>_map         ( <tbl_type>  self, <tbl_type>_MapProc map_proc ); | ||||||
|  | 		void       <fn>_map_mut     ( <tbl_type>  self, <tbl_type>_MapMutProc map_proc ); | ||||||
|  | 		void       <fn>_grow        ( <tbl_type>* self ); | ||||||
|  | 		void       <fn>_rehash      ( <tbl_type>* self, ssize new_num ); | ||||||
|  | 		void       <fn>_rehash_fast ( <tbl_type>  self ); | ||||||
|  | 		void       <fn>_remove      ( <tbl_type>  self, u64 key ); | ||||||
|  | 		void       <fn>_remove_entry( <tbl_type>  self, ssize idx ); | ||||||
|  | 		void       <fn>_set         ( <tbl_type>* self, u64 key, <type> value ); | ||||||
|  | 		ssize      <fn>_slot        ( <tbl_type>  self, u64 key ); | ||||||
|  |  | ||||||
|  | 		ssize         <fn>__add_entry( <tbl_type>* self, u64 key ); | ||||||
|  | 		HT_FindResult <fn>__find     ( <tbl_type>  self, u64 key ); | ||||||
|  | 		b32           <fn>__full     ( <tbl_type>  self ); | ||||||
|  |  | ||||||
|  | 		<tbl_type> <fn>init( AllocatorInfo allocator ) | ||||||
|  | 		{ | ||||||
|  | 			<tbl_type> result = hashtable_init_reserve(<tbl_type>, allocator, 8); | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		<tbl_type> <fn>_init_reserve( AllocatorInfo allocator, ssize num ) | ||||||
|  | 		{ | ||||||
|  | 			<tbl_type> result = { NULL, NULL }; | ||||||
|  | 			result.Hashes  = array_init_reserve(Array_ssize, allocator, num ); | ||||||
|  | 			array_get_header(result.Hashes)->Num = num; | ||||||
|  | 			array_resize(result.Hashes, num); | ||||||
|  | 			array_fill(result.Hashes, 0, num, -1); | ||||||
|  |  | ||||||
|  | 			result.Entries = array_init_reserve(<array_entry>, allocator, num ); | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_clear( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			array_clear( self.Entries ); | ||||||
|  | 			s32 what = array_num(self.Hashes); | ||||||
|  | 			array_fill( self.Hashes, 0, what, (ssize)-1 ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_destroy( <tbl_type>* self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Entries); | ||||||
|  | 			if ( self->Hashes && array_get_header(self->Hashes)->Capacity) { | ||||||
|  | 				array_free( self->Hashes ); | ||||||
|  | 				array_free( self->Entries ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		<type>* <fn>_get( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			ssize idx = <fn>__find( self, key ).EntryIndex; | ||||||
|  | 			if ( idx > 0 ) | ||||||
|  | 				return & self.Entries[idx].Value; | ||||||
|  |  | ||||||
|  | 			return nullptr; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_map( <tbl_type> self, <tbl_type>_MapProc map_proc ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			GEN_ASSERT_NOT_NULL( map_proc ); | ||||||
|  |  | ||||||
|  | 			for ( ssize idx = 0; idx < array_get_header( self.Entries )->Num; idx++ ) { | ||||||
|  | 				map_proc( self, self.Entries[idx].Key, self.Entries[idx].Value ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_map_mut( <tbl_type> self, <tbl_type>_MapMutProc map_proc ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			GEN_ASSERT_NOT_NULL( map_proc ); | ||||||
|  |  | ||||||
|  | 			for ( ssize idx = 0; idx < array_get_header( self.Entries )->Num; idx++ ) { | ||||||
|  | 				map_proc( self, self.Entries[idx].Key, & self.Entries[idx].Value ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_grow( <tbl_type>* self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Entries); | ||||||
|  | 			ssize new_num = array_grow_formula( array_get_header( self->Entries )->Num ); | ||||||
|  | 			hashtable_rehash( self, new_num ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_rehash( <tbl_type>* self, ssize new_num ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Entries); | ||||||
|  | 			GEN_ASSERT( new_num > 0 ); | ||||||
|  | 			ssize idx; | ||||||
|  | 			ssize last_added_index; | ||||||
|  |  | ||||||
|  | 			ArrayHeader* old_hash_header    = array_get_header( self->Hashes ); | ||||||
|  | 			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 ); | ||||||
|  |  | ||||||
|  | 			ArrayHeader* new_hash_header = array_get_header( new_tbl.Hashes ); | ||||||
|  |  | ||||||
|  | 			for (ssize idx = 0; idx < cast(ssize, old_hash_header->Num); ++idx) | ||||||
|  | 			{ | ||||||
|  | 				<entry_type>* entry = & self->Entries[idx]; | ||||||
|  | 				HT_FindResult find_result; | ||||||
|  |  | ||||||
|  | 				find_result      = <fn>__find( new_tbl, entry->Key); | ||||||
|  | 				last_added_index = <fn>__add_entry( & new_tbl, entry->Key); | ||||||
|  |  | ||||||
|  | 				if (find_result.PrevIndex < 0) | ||||||
|  | 					new_tbl.Hashes[find_result.HashIndex] = last_added_index; | ||||||
|  | 				else | ||||||
|  | 					new_tbl.Entries[find_result.PrevIndex].Next = last_added_index; | ||||||
|  |  | ||||||
|  | 				new_tbl.Entries[last_added_index].Next = find_result.EntryIndex; | ||||||
|  | 				new_tbl.Entries[last_added_index].Value = entry->Value; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			<fn>_destroy( self ); | ||||||
|  | 			* self = new_tbl; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_rehash_fast( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			ssize idx; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < array_get_header( self.Entries )->Num; idx++ ) | ||||||
|  | 				self.Entries[ idx ].Next = -1; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < array_get_header( self.Hashes )->Num; idx++ ) | ||||||
|  | 				self.Hashes[ idx ] = -1; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < array_get_header( self.Entries )->Num; idx++ ) | ||||||
|  | 			{ | ||||||
|  | 				<entry_type>*     entry; | ||||||
|  | 				HT_FindResult find_result; | ||||||
|  |  | ||||||
|  | 				entry       = & self.Entries[ idx ]; | ||||||
|  | 				find_result = <fn>__find( self, entry->Key ); | ||||||
|  |  | ||||||
|  | 				if ( find_result.PrevIndex < 0 ) | ||||||
|  | 					self.Hashes[ find_result.HashIndex ] = idx; | ||||||
|  | 				else | ||||||
|  | 					self.Entries[ find_result.PrevIndex ].Next = idx; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_remove( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			HT_FindResult find_result = <fn>__find( self, key ); | ||||||
|  |  | ||||||
|  | 			if ( find_result.EntryIndex >= 0 ) { | ||||||
|  | 				array_remove_at( self.Entries, find_result.EntryIndex ); | ||||||
|  | 				hashtable_rehash_fast( self ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_remove_entry( <tbl_type> self, ssize idx ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			array_remove_at( self.Entries, idx ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_set( <tbl_type>* self, u64 key, <type> value ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Entries); | ||||||
|  | 			ssize         idx; | ||||||
|  | 			HT_FindResult find_result; | ||||||
|  |  | ||||||
|  | 			if ( array_get_header( self->Hashes )->Num == 0 ) | ||||||
|  | 				hashtable_grow( self ); | ||||||
|  |  | ||||||
|  | 			find_result = <fn>__find( * self, key ); | ||||||
|  |  | ||||||
|  | 			if ( find_result.EntryIndex >= 0 ) { | ||||||
|  | 				idx = find_result.EntryIndex; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				idx = <fn>__add_entry( self, key ); | ||||||
|  |  | ||||||
|  | 				if ( find_result.PrevIndex >= 0 ) { | ||||||
|  | 					self->Entries[ find_result.PrevIndex ].Next = idx; | ||||||
|  | 				} | ||||||
|  | 				else { | ||||||
|  | 					self->Hashes[ find_result.HashIndex ] = idx; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			self->Entries[ idx ].Value = value; | ||||||
|  |  | ||||||
|  | 			if ( <fn>__full( * self ) ) | ||||||
|  | 				hashtable_grow( self ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ssize <fn>_slot( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			for ( ssize idx = 0; idx < array_get_header( self.Hashes )->Num; ++idx ) | ||||||
|  | 				if ( self.Hashes[ idx ] == key ) | ||||||
|  | 					return idx; | ||||||
|  |  | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ssize <fn>__add_entry( <tbl_type>* self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self->Entries); | ||||||
|  | 			ssize idx; | ||||||
|  | 			<entry_type> entry = { key, -1 }; | ||||||
|  |  | ||||||
|  | 			idx = array_get_header( self->Entries )->Num; | ||||||
|  | 			array_append( self->Entries, entry ); | ||||||
|  | 			return idx; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		HT_FindResult <fn>__find( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			HT_FindResult result = { -1, -1, -1 }; | ||||||
|  |  | ||||||
|  | 			ArrayHeader* hash_header = array_get_header( self.Hashes ); | ||||||
|  | 			if ( hash_header->Num > 0 ) | ||||||
|  | 			{ | ||||||
|  | 				result.HashIndex  = key % hash_header->Num; | ||||||
|  | 				result.EntryIndex = self.Hashes[ result.HashIndex ]; | ||||||
|  |  | ||||||
|  | 				while ( result.EntryIndex >= 0 ) | ||||||
|  | 				{ | ||||||
|  | 					if ( self.Entries[ result.EntryIndex ].Key == key ) | ||||||
|  | 						break; | ||||||
|  |  | ||||||
|  | 					result.PrevIndex  = result.EntryIndex; | ||||||
|  | 					result.EntryIndex = self.Entries[ result.EntryIndex ].Next; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		b32 <fn>__full( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Hashes); | ||||||
|  | 			GEN_ASSERT_NOT_NULL(self.Entries); | ||||||
|  | 			ArrayHeader* hash_header    = array_get_header( self.Hashes ); | ||||||
|  | 			ArrayHeader* entries_header = array_get_header( self.Entries ); | ||||||
|  |  | ||||||
|  | 			usize critical_load = cast(usize, HashTable_CriticalLoadScale * cast(f32, hash_header->Num)); | ||||||
|  | 			b32 result = entries_header->Num > critical_load; | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  | 	))); | ||||||
|  | #pragma pop_macro( "GEN_ASSERT" ) | ||||||
|  | #pragma pop_macro( "GEN_ASSERT_NOT_NULL" ) | ||||||
|  | #pragma pop_macro( "rcast" ) | ||||||
|  | #pragma pop_macro( "cast" ) | ||||||
|  | #pragma pop_macro( "typeof" ) | ||||||
|  | #pragma pop_macro( "forceinline" ) | ||||||
|  |  | ||||||
|  | 	++ HashTable_DefinitionCounter; | ||||||
|  | 	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, | ||||||
|  | R"(#define GENERIC_SLOT_<slot>__hashtable_init          <type_delimiter>,  <type_delimiter>_init | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_init_reserve     <type_delimiter>,  <type_delimiter>_init_reserve | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_clear            <type_delimiter>,  <type_delimiter>_clear | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_destroy          <type_delimiter>*, <type_delimiter>_destroy | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_get              <type_delimiter>,  <type_delimiter>_get | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_map              <type_delimiter>,  <type_delimiter>_map | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_map_mut          <type_delimiter>,  <type_delimiter>_map_mut | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_grow             <type_delimiter>*, <type_delimiter>_grow | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_rehash           <type_delimiter>*, <type_delimiter>_rehash | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_rehash_fast      <type_delimiter>,  <type_delimiter>_rehash_fast | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_remove_entry     <type_delimiter>,  <type_delimiter>_remove_entry | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_set              <type_delimiter>*, <type_delimiter>_set | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable_slot             <type_delimiter>,  <type_delimiter>_slot | ||||||
|  |  | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable__add_entry       <type_delimiter>*, <type_delimiter>__add_entry | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable__find            <type_delimiter>,  <type_delimiter>__find | ||||||
|  | #define GENERIC_SLOT_<slot>__hashtable__full            <type_delimiter>,  <type_delimiter>__full | ||||||
|  | )" | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	char const* cmt_str = str_fmt_buf( "Name: %.*s Type: %.*s" | ||||||
|  | 		, tbl_type.length(), tbl_type.Data | ||||||
|  | 		, type.Len, type.Ptr ); | ||||||
|  |  | ||||||
|  | 	return def_global_body(args( | ||||||
|  | 		def_pragma( string_to_strc( string_fmt_buf( GlobalAllocator, "region %S", tbl_type ))), | ||||||
|  | 		fmt_newline, | ||||||
|  | 		generic_interface_slot, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		hashtable_types, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		entry_array, | ||||||
|  | 		hashtable_def, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		def_pragma( string_to_strc( string_fmt_buf( GlobalAllocator, "endregion %S", tbl_type ))), | ||||||
|  | 		fmt_newline | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CodeBody gen_hashtable_generic_selection_interface() | ||||||
|  | { | ||||||
|  | 	CodeBody interface_defines = def_body(CT_Global_Body); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_init"), GenericSel_Direct_Type )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_init_reserve"), GenericSel_Direct_Type )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_clear"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_destroy"), GenericSel_By_Ref, GenericSel_One_Arg ) ); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_get") )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_grow"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_rehash") )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_rehash_fast"), GenericSel_Default, GenericSel_One_Arg )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_remove") )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_remove_entry") )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_set"), GenericSel_By_Ref )); | ||||||
|  | 	interface_defines.append( gen_generic_selection_function_macro( HashTable_DefinitionCounter, txt("hashtable_slot") )); | ||||||
|  | 	return interface_defines; | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								gen_c_library/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								gen_c_library/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | /* | ||||||
|  | 	gencpp: An attempt at "simple" staged metaprogramming for c/c++. | ||||||
|  |  | ||||||
|  | 	See Readme.md for more information from the project repository. | ||||||
|  |  | ||||||
|  | 	Public Address: | ||||||
|  | 	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. | ||||||
|  |  | ||||||
|  | 	! ----------------------------------------------------------------------- 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) | ||||||
|  | #	error Gen.hpp : GEN_TIME not defined | ||||||
|  | #endif | ||||||
							
								
								
									
										128
									
								
								gen_c_library/components/memory.fixed_arena.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								gen_c_library/components/memory.fixed_arena.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | CodeBody gen_fixed_arenas() | ||||||
|  | { | ||||||
|  | 	CodeBody result = def_body(CT_Global_Body); | ||||||
|  | 	result.append(def_pragma(txt("region FixedArena"))); | ||||||
|  |  | ||||||
|  | 	char const* template_struct = stringize( | ||||||
|  | 		struct FixedArena_<Name>_Def | ||||||
|  | 		{ | ||||||
|  | 			char  memory[<Size>]; | ||||||
|  | 			Arena arena; | ||||||
|  | 		}; | ||||||
|  | 		typedef struct FixedArena_<Name>_Def FixedArena_<Name>; | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	char const* template_interface = stringize( | ||||||
|  | 		inline | ||||||
|  | 		void fixed_arena_init_<Name>(FixedArena_<Name>* result) | ||||||
|  | 		{ | ||||||
|  | 			result->arena = arena_init_from_memory(& result->memory[0], <Size>); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		ssize fixed_arena_size_remaining_<Name>(FixedArena_<Name>* fixed_arena, ssize alignment) | ||||||
|  | 		{ | ||||||
|  | 			return arena_size_remaining( & fixed_arena->arena, alignment); | ||||||
|  | 		} | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CodeBody arena_struct_1kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("1KB"),   "Size", txt("kilobytes(1)"),   template_struct )); | ||||||
|  | 	CodeBody arena_struct_4kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("4KB"),   "Size", txt("kilobytes(4)"),   template_struct )); | ||||||
|  | 	CodeBody arena_struct_8kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("8KB"),   "Size", txt("kilobytes(8)"),   template_struct )); | ||||||
|  | 	CodeBody arena_struct_16kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("16KB"),  "Size", txt("kilobytes(16)"),  template_struct )); | ||||||
|  | 	CodeBody arena_struct_32kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("32KB"),  "Size", txt("kilobytes(32)"),  template_struct )); | ||||||
|  | 	CodeBody arena_struct_64kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("64KB"),  "Size", txt("kilobytes(64)"),  template_struct )); | ||||||
|  | 	CodeBody arena_struct_128kb = parse_global_body( token_fmt_impl( 3, "Name", txt("128KB"), "Size", txt("kilobytes(128)"), template_struct )); | ||||||
|  | 	CodeBody arena_struct_256kb = parse_global_body( token_fmt_impl( 3, "Name", txt("256KB"), "Size", txt("kilobytes(256)"), template_struct )); | ||||||
|  | 	CodeBody arena_struct_512kb = parse_global_body( token_fmt_impl( 3, "Name", txt("512KB"), "Size", txt("kilobytes(512)"), template_struct )); | ||||||
|  | 	CodeBody arena_struct_1mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("1MB"),   "Size", txt("megabytes(1)"),   template_struct )); | ||||||
|  | 	CodeBody arena_struct_2mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("2MB"),   "Size", txt("megabytes(2)"),   template_struct )); | ||||||
|  | 	CodeBody arena_struct_4mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("4MB"),   "Size", txt("megabytes(4)"),   template_struct )); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	CodeBody arena_interface_1kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("1KB"),   "Size", txt("kilobytes(1)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_4kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("4KB"),   "Size", txt("kilobytes(4)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_8kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("8KB"),   "Size", txt("kilobytes(8)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_16kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("16KB"),  "Size", txt("kilobytes(16)"),  template_interface )); | ||||||
|  | 	CodeBody arena_interface_32kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("32KB"),  "Size", txt("kilobytes(32)"),  template_interface )); | ||||||
|  | 	CodeBody arena_interface_64kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("64KB"),  "Size", txt("kilobytes(64)"),  template_interface )); | ||||||
|  | 	CodeBody arena_interface_128kb = parse_global_body( token_fmt_impl( 3, "Name", txt("128KB"), "Size", txt("kilobytes(128)"), template_interface )); | ||||||
|  | 	CodeBody arena_interface_256kb = parse_global_body( token_fmt_impl( 3, "Name", txt("256KB"), "Size", txt("kilobytes(256)"), template_interface )); | ||||||
|  | 	CodeBody arena_interface_512kb = parse_global_body( token_fmt_impl( 3, "Name", txt("512KB"), "Size", txt("kilobytes(512)"), template_interface )); | ||||||
|  | 	CodeBody arena_interface_1mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("1MB"),   "Size", txt("megabytes(1)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_2mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("2MB"),   "Size", txt("megabytes(2)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_4mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("4MB"),   "Size", txt("megabytes(4)"),   template_interface )); | ||||||
|  |  | ||||||
|  | 	result.append(arena_struct_1kb); | ||||||
|  | 	result.append(arena_struct_4kb); | ||||||
|  | 	result.append(arena_struct_8kb); | ||||||
|  | 	result.append(arena_struct_16kb); | ||||||
|  | 	result.append(arena_struct_32kb); | ||||||
|  | 	result.append(arena_struct_64kb); | ||||||
|  | 	result.append(arena_struct_128kb); | ||||||
|  | 	result.append(arena_struct_256kb); | ||||||
|  | 	result.append(arena_struct_512kb); | ||||||
|  | 	result.append(arena_struct_1mb); | ||||||
|  | 	result.append(arena_struct_2mb); | ||||||
|  | 	result.append(arena_struct_4mb); | ||||||
|  |  | ||||||
|  | 	result.append(arena_interface_1kb); | ||||||
|  | 	result.append(arena_interface_4kb); | ||||||
|  | 	result.append(arena_interface_8kb); | ||||||
|  | 	result.append(arena_interface_16kb); | ||||||
|  | 	result.append(arena_interface_32kb); | ||||||
|  | 	result.append(arena_interface_64kb); | ||||||
|  | 	result.append(arena_interface_128kb); | ||||||
|  | 	result.append(arena_interface_256kb); | ||||||
|  | 	result.append(arena_interface_512kb); | ||||||
|  | 	result.append(arena_interface_1mb); | ||||||
|  | 	result.append(arena_interface_2mb); | ||||||
|  | 	result.append(arena_interface_4mb); | ||||||
|  |  | ||||||
|  | 	CodeDefine def = def_define(txt("fixed_arena_allocator_info(fixed_arena)"), code({ arena_allocator_proc, & fixed_arena.arena }) ); | ||||||
|  | 	result.append(def); | ||||||
|  | 	result.append(fmt_newline); | ||||||
|  |  | ||||||
|  | 	result.append(parse_global_body(txt(R"( | ||||||
|  | #define fixed_arena_init(expr) _Generic((expr), \ | ||||||
|  |     FixedArena_1KB*   : fixed_arena_init_1KB,   \ | ||||||
|  |     FixedArena_4KB*   : fixed_arena_init_4KB,   \ | ||||||
|  |     FixedArena_8KB*   : fixed_arena_init_8KB,   \ | ||||||
|  |     FixedArena_16KB*  : fixed_arena_init_16KB,  \ | ||||||
|  |     FixedArena_32KB*  : fixed_arena_init_32KB,  \ | ||||||
|  |     FixedArena_64KB*  : fixed_arena_init_64KB,  \ | ||||||
|  |     FixedArena_128KB* : fixed_arena_init_128KB, \ | ||||||
|  |     FixedArena_256KB* : fixed_arena_init_256KB, \ | ||||||
|  |     FixedArena_512KB* : fixed_arena_init_512KB, \ | ||||||
|  |     FixedArena_1MB*   : fixed_arena_init_1MB,   \ | ||||||
|  |     FixedArena_2MB*   : fixed_arena_init_2MB,   \ | ||||||
|  |     FixedArena_4MB*   : fixed_arena_init_4MB    \ | ||||||
|  | ) GEN_RESOLVED_FUNCTION_CALL(& expr) | ||||||
|  |  | ||||||
|  | #define fixed_arena_size_remaining(expr, alignment) _Generic((expr), \ | ||||||
|  |     FixedArena_1KB*   : fixed_arena_size_remaining_1KB,              \ | ||||||
|  |     FixedArena_4KB*   : fixed_arena_size_remaining_4KB,              \ | ||||||
|  |     FixedArena_8KB*   : fixed_arena_size_remaining_8KB,              \ | ||||||
|  |     FixedArena_16KB*  : fixed_arena_size_remaining_16KB,             \ | ||||||
|  |     FixedArena_32KB*  : fixed_arena_size_remaining_32KB,             \ | ||||||
|  |     FixedArena_64KB*  : fixed_arena_size_remaining_64KB,             \ | ||||||
|  |     FixedArena_128KB* : fixed_arena_size_remaining_128KB,            \ | ||||||
|  |     FixedArena_256KB* : fixed_arena_size_remaining_256KB,            \ | ||||||
|  |     FixedArena_512KB* : fixed_arena_size_remaining_512KB,            \ | ||||||
|  |     FixedArena_1MB*   : fixed_arena_size_remaining_1MB,              \ | ||||||
|  |     FixedArena_2MB*   : fixed_arena_size_remaining_2MB,              \ | ||||||
|  |     FixedArena_4MB*   : fixed_arena_size_remaining_4MB               \ | ||||||
|  | )	GEN_RESOLVED_FUNCTION_CALL(& expr, alignment) | ||||||
|  | )" | ||||||
|  | 	))); | ||||||
|  |  | ||||||
|  | 	result.append(fmt_newline); | ||||||
|  | 	result.append(def_pragma(txt("endregion FixedArena"))); | ||||||
|  |  | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
							
								
								
									
										238
									
								
								gen_c_library/components/misc.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								gen_c_library/components/misc.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& parsed_body, CodeBody& body ) | ||||||
|  | { | ||||||
|  | 	b32 found = false; | ||||||
|  | 	CodePreprocessCond cond = cast(CodePreprocessCond, entry_iter); | ||||||
|  | 	if ( cond->Content.contains(cond_sig) ) | ||||||
|  | 	{ | ||||||
|  | 		log_fmt("Preprocess cond found: %SC\n", cond->Content); | ||||||
|  | 		found = true; | ||||||
|  |  | ||||||
|  | 		s32 depth = 1; | ||||||
|  | 		++ entry_iter; | ||||||
|  | 		for(b32 continue_for = true; continue_for && entry_iter != parsed_body.end(); ) switch | ||||||
|  | 		(entry_iter->Type) { | ||||||
|  | 			case CT_Preprocess_If: | ||||||
|  | 			case CT_Preprocess_IfDef: | ||||||
|  | 			case CT_Preprocess_IfNotDef: | ||||||
|  | 				++ depth; | ||||||
|  | 		 		++ entry_iter; | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Preprocess_Else: | ||||||
|  | 				++ entry_iter; | ||||||
|  | 				for(; continue_for && entry_iter != parsed_body.end(); ++ entry_iter) | ||||||
|  | 				{ | ||||||
|  | 					if (entry_iter->Type == CT_Preprocess_EndIf) | ||||||
|  | 					{ | ||||||
|  | 						continue_for = false; | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					body.append(entry_iter); | ||||||
|  | 				} | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Preprocess_EndIf: | ||||||
|  | 			{ | ||||||
|  | 				depth --; | ||||||
|  | 				if (depth == 0) { | ||||||
|  | 					continue_for = false; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 				++ entry_iter; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			default: | ||||||
|  | 				++ entry_iter; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return found; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | constexpr bool GenericSel_One_Arg = true; | ||||||
|  | enum GenericSelectionOpts : u32 { GenericSel_Default, GenericSel_By_Ref, GenericSel_Direct_Type }; | ||||||
|  | Code gen_generic_selection_function_macro( s32 num_slots, StrC macro_name, GenericSelectionOpts opts = GenericSel_Default, bool one_arg = false ) | ||||||
|  | { | ||||||
|  | /* Implements: | ||||||
|  | 	#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg, ... ) _Generic(      \ | ||||||
|  | 	(selector_arg),                                                          \ | ||||||
|  | 		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_LAST(FunctionID__ARGS_SIG_N ) \ | ||||||
|  | 	) GEN_RESOLVED_FUNCTION_CALL( selector_arg ) | ||||||
|  | */ | ||||||
|  | 	local_persist | ||||||
|  | 	String define_builder = String::make_reserve(GlobalAllocator, kilobytes(64)); | ||||||
|  | 	define_builder.clear(); | ||||||
|  |  | ||||||
|  | 	StrC macro_begin; | ||||||
|  | 	if (opts == GenericSel_Direct_Type) { | ||||||
|  | 		macro_begin = token_fmt( "macro_name", (StrC)macro_name, | ||||||
|  | R"(#define <macro_name>(selector_arg, ...) _Generic( (*(selector_arg*)NULL ), \ | ||||||
|  | )" | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		macro_begin = token_fmt( "macro_name", (StrC)macro_name, | ||||||
|  | R"(#define <macro_name>(selector_arg, ...) _Generic( (selector_arg), \ | ||||||
|  | )" | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 	define_builder.append(macro_begin); | ||||||
|  |  | ||||||
|  | 	for ( s32 slot = 1; slot <= num_slots; ++ slot ) | ||||||
|  | 	{ | ||||||
|  | 		StrC slot_str = String::fmt_buf(GlobalAllocator, "%d", slot).to_strc(); | ||||||
|  | 		if (slot == num_slots) | ||||||
|  | 		{ | ||||||
|  | 			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> ) \ | ||||||
|  | )" | ||||||
|  | 			)); | ||||||
|  | 			// if ( one_arg ) | ||||||
|  | 			// 	define_builder.append(token_fmt( "macro_name", macro_name, stringize( | ||||||
|  | 			// 		default: static_assert(false, "<macro_name>: Failed to select correct function signature (Did you pass the type?)") | ||||||
|  | 			// 	))); | ||||||
|  | 			// else | ||||||
|  | 			// 	define_builder.append(token_fmt( "macro_name", macro_name, stringize( | ||||||
|  | 			// 		default: static_assert(false, "<macro_name>: Failed to select correct function signature") | ||||||
|  | 			// 	))); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		define_builder.append( token_fmt( "macro_name", macro_name, "slot", slot_str, | ||||||
|  | R"(		GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_<slot>__<macro_name> ) \ | ||||||
|  | )" | ||||||
|  | 		)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ( ! one_arg ) | ||||||
|  | 	{ | ||||||
|  | 		if (opts == GenericSel_By_Ref) | ||||||
|  | 			define_builder.append(txt("\t)\tGEN_RESOLVED_FUNCTION_CALL( & selector_arg, __VA_ARGS__ )")); | ||||||
|  | 		else if (opts == GenericSel_Direct_Type) | ||||||
|  | 			define_builder.append(txt("\t)\tGEN_RESOLVED_FUNCTION_CALL( __VA_ARGS__ )")); | ||||||
|  | 		else | ||||||
|  | 			define_builder.append(txt("\t)\tGEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )")); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		if (opts == GenericSel_By_Ref) | ||||||
|  | 			define_builder.append(txt("\t)\tGEN_RESOLVED_FUNCTION_CALL( & selector_arg )")); | ||||||
|  | 		else if (opts == GenericSel_Direct_Type) | ||||||
|  | 			define_builder.append(txt("\t)\tGEN_RESOLVED_FUNCTION_CALL()")); | ||||||
|  | 		else | ||||||
|  | 			define_builder.append(txt("\t)\tGEN_RESOLVED_FUNCTION_CALL( selector_arg )")); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Add gap for next definition | ||||||
|  | 	define_builder.append(txt("\n\n")); | ||||||
|  |  | ||||||
|  | 	Code macro = untyped_str(define_builder.to_strc()); | ||||||
|  | 	return macro; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CodeFn rename_function_to_unique_symbol(CodeFn fn, StrC optional_prefix = txt("")) | ||||||
|  | { | ||||||
|  |     // Get basic components for the name | ||||||
|  |     StrC old_name = fn->Name; | ||||||
|  |     String new_name; | ||||||
|  |  | ||||||
|  |     // Add prefix if provided | ||||||
|  |     if (optional_prefix.Len) | ||||||
|  |         new_name = string_fmt_buf(GlobalAllocator, "%SC_%SC_", optional_prefix, old_name); | ||||||
|  |     else | ||||||
|  |         new_name = string_fmt_buf(GlobalAllocator, "%SC_", old_name); | ||||||
|  |  | ||||||
|  |     // Add return type to the signature | ||||||
|  |     if (fn->ReturnType) | ||||||
|  |         new_name.append_fmt("_%SC", fn->ReturnType->Name); | ||||||
|  |  | ||||||
|  |     // Add parameter types to create a unique signature | ||||||
|  |     bool first_param = true; | ||||||
|  |     for (CodeParam param = fn->Params; param.ast; param = param->Next) | ||||||
|  |     { | ||||||
|  |         if (param->ValueType) | ||||||
|  |         { | ||||||
|  |             // Add separator for readability | ||||||
|  |             if (first_param) | ||||||
|  |             { | ||||||
|  |                 new_name.append("_P_"); | ||||||
|  |                 first_param = false; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 new_name.append("_"); | ||||||
|  |  | ||||||
|  |             // Add parameter type, handle any specifiers | ||||||
|  |             if (param->ValueType->Specs && param->ValueType->Specs->NumEntries > 0) | ||||||
|  |             { | ||||||
|  |                 // Add specifiers (const, volatile, etc) | ||||||
|  |                 for (Specifier spec : param->ValueType->Specs) | ||||||
|  |                 { | ||||||
|  | 					if (spec == Spec_Ptr) { | ||||||
|  | 						new_name.append("ptr_"); | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  |                     new_name.append_fmt("%SC_", to_str(spec)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             new_name.append_fmt("%SC", param->ValueType->Name); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Handle function specifiers if present | ||||||
|  |     if (fn->Specs && fn->Specs->NumEntries > 0) | ||||||
|  |     { | ||||||
|  |         new_name.append("_S_"); | ||||||
|  |         for (Specifier* spec = begin(fn->Specs);  | ||||||
|  |              spec != end(fn->Specs);  | ||||||
|  |              ++spec) | ||||||
|  |         { | ||||||
|  |             new_name.append_fmt("%SC_", to_str(*spec)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn->Name = new_name; | ||||||
|  |     return fn; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | using SwapContentProc = CodeBody(void); | ||||||
|  | bool swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_content, Code& entry_iter, CodeBody& body ) | ||||||
|  | { | ||||||
|  | 	bool found = false; | ||||||
|  | 	CodePragma possible_region = cast(CodePragma, entry_iter); | ||||||
|  |  | ||||||
|  | 	String region_sig    = string_fmt_buf(GlobalAllocator, "region %s",    region_name.Ptr); | ||||||
|  | 	String endregion_sig = string_fmt_buf(GlobalAllocator, "endregion %s", region_name.Ptr); | ||||||
|  | 	if ( possible_region->Content.contains(region_sig)) | ||||||
|  | 	{ | ||||||
|  | 		found = true; | ||||||
|  | 		// body.append(possible_region); | ||||||
|  | 		body.append(swap_content()); | ||||||
|  |  | ||||||
|  | 		++ entry_iter; | ||||||
|  | 		for(b32 continue_for = true; continue_for; ++entry_iter) switch | ||||||
|  | 		(entry_iter->Type) { | ||||||
|  | 			case CT_Preprocess_Pragma: | ||||||
|  | 			{ | ||||||
|  | 				CodePragma possible_end_region = cast(CodePragma, entry_iter); | ||||||
|  | 				if ( possible_end_region->Content.contains(endregion_sig) ) { | ||||||
|  | 					// body.append(possible_end_region); | ||||||
|  | 					continue_for = false; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		body.append(entry_iter); | ||||||
|  | 	} | ||||||
|  | 	return found; | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								gen_c_library/gen.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								gen_c_library/gen.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | #define GEN_IMPLEMENTATION | ||||||
|  | #include "gen/gen.h" | ||||||
|  |  | ||||||
|  | int main() | ||||||
|  | { | ||||||
|  | 	// init(); | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| # Singleheader | # Singleheader | ||||||
| 
 | 
 | ||||||
| Creates a single header file version of the library using `gen.singleheader.cpp`. | Creates a single header file version of the library using `singleheader.cpp`. | ||||||
| Follows the same convention seen in the gb, stb, and zpl libraries. | Follows the same convention seen in the gb, stb, and zpl libraries. | ||||||
							
								
								
									
										20
									
								
								gen_singleheader/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								gen_singleheader/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | /* | ||||||
|  | 	gencpp: An attempt at "simple" staged metaprogramming for c/c++. | ||||||
|  |  | ||||||
|  | 	See Readme.md for more information from the project repository. | ||||||
|  |  | ||||||
|  | 	Public Address: | ||||||
|  | 	https://github.com/Ed94/gencpp | ||||||
|  |  | ||||||
|  | 	This is a single header variant of the library. | ||||||
|  | 	Define GEN_IMPLEMENTATION before including this file in a single compilation unit. | ||||||
|  |  | ||||||
|  | 	! ----------------------------------------------------------------------- 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) | ||||||
|  | #	error Gen.hpp : GEN_TIME not defined | ||||||
|  | #endif | ||||||
| @@ -1,6 +1,8 @@ | |||||||
| #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 | ||||||
|  | #define GEN_SUPPORT_CPP_MEMBER_FEATURES 1 | ||||||
|  | #define GEN_SUPPORT_CPP_REFERENCES      0 | ||||||
| #include "gen.cpp" | #include "gen.cpp" | ||||||
| 
 | 
 | ||||||
| #include "helpers/push_ignores.inline.hpp" | #include "helpers/push_ignores.inline.hpp" | ||||||
| @@ -7,6 +7,12 @@ | |||||||
| 	https://github.com/Ed94/gencpp
 | 	https://github.com/Ed94/gencpp
 | ||||||
| 
 | 
 | ||||||
| 	This is a variant intended for use with Unreal Engine 5 | 	This is a variant intended for use with Unreal Engine 5 | ||||||
|  | 
 | ||||||
|  | 	! ----------------------------------------------------------------------- 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 | ||||||
| @@ -10,7 +10,7 @@ | |||||||
| 		<IsVirtual>false</IsVirtual> | 		<IsVirtual>false</IsVirtual> | ||||||
| 		<IsFolder>false</IsFolder> | 		<IsFolder>false</IsFolder> | ||||||
| 		<BuildCommand>pwsh ./scripts/build.ps1 msvc debug bootstrap</BuildCommand> | 		<BuildCommand>pwsh ./scripts/build.ps1 msvc debug bootstrap</BuildCommand> | ||||||
| 		<RebuildCommand></RebuildCommand> | 		<RebuildCommand>pwsh ./scripts/build.ps1 msvc debug c_library</RebuildCommand> | ||||||
| 		<BuildFileCommand></BuildFileCommand> | 		<BuildFileCommand></BuildFileCommand> | ||||||
| 		<CleanCommand>pwsh ./scripts/clean.ps1</CleanCommand> | 		<CleanCommand>pwsh ./scripts/clean.ps1</CleanCommand> | ||||||
| 		<BuildWorkingDirectory></BuildWorkingDirectory> | 		<BuildWorkingDirectory></BuildWorkingDirectory> | ||||||
|   | |||||||
| @@ -30,6 +30,13 @@ Feature Macros: | |||||||
| * `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves. | * `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves. | ||||||
| * `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized. | * `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized. | ||||||
|  |  | ||||||
|  | By default the base library implementation strictly uses a C-like interface. This is to allow for the generation of a C-variant of the library using [gen_c_library](../gen_c_library/). However, the library was written in C++ and supports some of its features: | ||||||
|  |  | ||||||
|  | * `GEN_SUPPORT_CPP_REFERENCES` : Will enable support for reference interface on some definitions | ||||||
|  | * `GEN_SUPPORT_CPP_MEMBER_FEATURES` : Will enable support for definitions to have their interface as members. | ||||||
|  |  | ||||||
|  | *Note: A variant of the C++ library could be generated where those additonal support features are removed (see gen_c_library implementation for an idea of how)* | ||||||
|  |  | ||||||
| ## On multi-threading | ## On multi-threading | ||||||
|  |  | ||||||
| Currently unsupported. I want the library to be *stable* and *correct*, with the addition of exhausting all basic single-threaded optimizations before I consider multi-threading. | Currently unsupported. I want the library to be *stable* and *correct*, with the addition of exhausting all basic single-threaded optimizations before I consider multi-threading. | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ Builder Builder::open( char const* path ) | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	result.Buffer = String::make_reserve( GlobalAllocator, Builder_StrBufferReserve ); | 	result.Buffer = string_make_reserve( GlobalAllocator, Builder_StrBufferReserve ); | ||||||
|  |  | ||||||
| 	// log_fmt("$Builder - Opened file: %s\n", result.File.filename ); | 	// log_fmt("$Builder - Opened file: %s\n", result.File.filename ); | ||||||
| 	return result; | 	return result; | ||||||
| @@ -21,15 +21,15 @@ Builder Builder::open( char const* path ) | |||||||
|  |  | ||||||
| void Builder::pad_lines( s32 num ) | void Builder::pad_lines( s32 num ) | ||||||
| { | { | ||||||
| 	Buffer.append( "\n" ); | 	string_append_strc( & Buffer, txt("\n") ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::print( Code code ) | void Builder::print( Code code ) | ||||||
| { | { | ||||||
| 	String   str = code->to_string(); | 	String   str = to_string(code); | ||||||
| 	// const ssize len = str.length(); | 	// const ssize len = str.length(); | ||||||
| 	// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data ); | 	// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data ); | ||||||
| 	Buffer.append( str ); | 	string_append_string( & Buffer, str ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::print_fmt( char const* fmt, ... ) | void Builder::print_fmt( char const* fmt, ... ) | ||||||
| @@ -43,17 +43,17 @@ void Builder::print_fmt( char const* fmt, ... ) | |||||||
| 	va_end( va ); | 	va_end( va ); | ||||||
|  |  | ||||||
| 	// log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf ); | 	// log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf ); | ||||||
| 	Buffer.append( buf, res ); | 	string_append_c_str_len( (String*) & Buffer, (char const*)buf, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::write() | void Builder::write() | ||||||
| { | { | ||||||
| 	b32 result = file_write( & File, Buffer, Buffer.length() ); | 	b32 result = file_write( & File, Buffer, string_length(Buffer) ); | ||||||
|  |  | ||||||
| 	if ( result == false ) | 	if ( result == false ) | ||||||
| 		log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); | 		log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); | ||||||
|  |  | ||||||
| 	log_fmt( "Generated: %s\n", File.filename ); | 	log_fmt( "Generated: %s\n", File.filename ); | ||||||
| 	file_close( & File ); | 	file_close( & File ); | ||||||
| 	Buffer.free(); | 	string_free(& Buffer); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								project/auxillary/gen_template.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								project/auxillary/gen_template.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
|  | #	pragma once | ||||||
|  | #	include "../gen.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | 	Explicitly generates a resolved definition of a cpp template definition. | ||||||
|  |  | ||||||
|  | 	TODO(Ed): Needs implementing for the C-library variant. | ||||||
|  | 	TODO(Ed): We need a non <token> syntax subst implemtnation for Strings for this to work. It must subst keywords directly based on template parameter names. | ||||||
|  |  | ||||||
|  | 	This is only meant to be used on relatively trivial templates, where the type or numeric is mostly a 'duck' type. | ||||||
|  | 	It cannot parse complex template parameters. | ||||||
|  |  | ||||||
|  | 	The varadic args should correspond 1:1 with the type of objects the generator expects from the template's parameters.alignas. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | CodeOperator gen_operator_template( CodeTemplate template, ... ); | ||||||
|  | CodeFn       gen_func_template( CodeTemplate template, ...  ); | ||||||
|  | Code         gen_class_struct_template( CodeTemplate template, ... ); | ||||||
|  |  | ||||||
|  | Code gen_template( CodeTemplate template, ... ); | ||||||
|  | Code gen_template( StrC template, StrC instantiation ); | ||||||
| @@ -23,9 +23,9 @@ Code scan_file( char const* path ) | |||||||
| 		GEN_FATAL("scan_file: %s is empty", path ); | 		GEN_FATAL("scan_file: %s is empty", path ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String str = String::make_reserve( GlobalAllocator, fsize ); | 	String str = string_make_reserve( GlobalAllocator, fsize ); | ||||||
| 		file_read( & file, str, fsize ); | 		file_read( & file, str, fsize ); | ||||||
| 		str.get_header().Length = fsize; | 		string_get_header(str)->Length = fsize; | ||||||
|  |  | ||||||
| 	// Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks | 	// Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks | ||||||
| 	// Its designed so that the directive should be the first thing in the file. | 	// Its designed so that the directive should be the first thing in the file. | ||||||
| @@ -39,7 +39,7 @@ Code scan_file( char const* path ) | |||||||
| 		const StrC def_intellisense = txt("GEN_INTELLISENSE_DIRECTIVES" ); | 		const StrC def_intellisense = txt("GEN_INTELLISENSE_DIRECTIVES" ); | ||||||
|  |  | ||||||
| 		bool        found_directive = false; | 		bool        found_directive = false; | ||||||
| 		char const* scanner         = str.Data; | 		char const* scanner         = (char const*)str; | ||||||
| 		s32         left            = fsize; | 		s32         left            = fsize; | ||||||
| 		while ( left ) | 		while ( left ) | ||||||
| 		{ | 		{ | ||||||
| @@ -52,7 +52,7 @@ Code scan_file( char const* path ) | |||||||
|  |  | ||||||
| 				if ( ! found_directive ) | 				if ( ! found_directive ) | ||||||
| 				{ | 				{ | ||||||
| 					if ( left && str_compare( scanner, directive_start.Ptr, directive_start.Len ) == matched ) | 					if ( left && str_compare_len( scanner, directive_start.Ptr, directive_start.Len ) == matched ) | ||||||
| 					{ | 					{ | ||||||
| 						scanner += directive_start.Len; | 						scanner += directive_start.Len; | ||||||
| 						left    -= directive_start.Len; | 						left    -= directive_start.Len; | ||||||
| @@ -60,7 +60,7 @@ Code scan_file( char const* path ) | |||||||
| 						while ( left && char_is_space( current ) ) | 						while ( left && char_is_space( current ) ) | ||||||
| 							move_fwd(); | 							move_fwd(); | ||||||
|  |  | ||||||
| 						if ( left && str_compare( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched ) | 						if ( left && str_compare_len( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched ) | ||||||
| 						{ | 						{ | ||||||
| 							scanner += def_intellisense.Len; | 							scanner += def_intellisense.Len; | ||||||
| 							left    -= def_intellisense.Len; | 							left    -= def_intellisense.Len; | ||||||
| @@ -80,7 +80,7 @@ Code scan_file( char const* path ) | |||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if ( left && str_compare( scanner, directive_end.Ptr, directive_end.Len ) == matched ) | 				if ( left && str_compare_len( scanner, directive_end.Ptr, directive_end.Len ) == matched ) | ||||||
| 				{ | 				{ | ||||||
| 					scanner += directive_end.Len; | 					scanner += directive_end.Len; | ||||||
| 					left    -= directive_end.Len; | 					left    -= directive_end.Len; | ||||||
| @@ -94,19 +94,18 @@ Code scan_file( char const* path ) | |||||||
| 						move_fwd(); | 						move_fwd(); | ||||||
|  |  | ||||||
| 					// sptr skip_size = fsize - left; | 					// sptr skip_size = fsize - left; | ||||||
| 					if ( (scanner + 2) >= ( str.Data + fsize ) ) | 					if ( (scanner + 2) >= ( (char const*) str + fsize ) ) | ||||||
| 					{ | 					{ | ||||||
| 						mem_move( str, scanner, left ); | 						mem_move( str, scanner, left ); | ||||||
| 						str.get_header().Length = left; | 						string_get_header(str)->Length = left; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					mem_move( str, scanner, left ); | 					mem_move( str, scanner, left ); | ||||||
| 					str.get_header().Length = left; | 					string_get_header(str)->Length = left; | ||||||
|  |  | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			move_fwd(); | 			move_fwd(); | ||||||
| @@ -117,7 +116,7 @@ Code scan_file( char const* path ) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	file_close( & file ); | 	file_close( & file ); | ||||||
| 	return untyped_str( str ); | 	return untyped_str( string_to_strc(str) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
|   | |||||||
| @@ -1,13 +1,17 @@ | |||||||
| #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 | ||||||
|  | #define GEN_SUPPORT_CPP_MEMBER_FEATURES 0 | ||||||
|  | #define GEN_SUPPORT_CPP_REFERENCES      0 | ||||||
| #include "gen.cpp" | #include "gen.cpp" | ||||||
|  |  | ||||||
| #include "helpers/push_ignores.inline.hpp" | #include "helpers/push_ignores.inline.hpp" | ||||||
| #include "helpers/helper.hpp" | #include "helpers/helper.hpp" | ||||||
|  |  | ||||||
| GEN_NS_BEGIN | GEN_NS_BEGIN | ||||||
|  | #include "helpers/push_container_defines.inline.hpp" | ||||||
| #include "dependencies/parsing.cpp" | #include "dependencies/parsing.cpp" | ||||||
|  | #include "helpers/pop_container_defines.inline.hpp" | ||||||
| GEN_NS_END | GEN_NS_END | ||||||
|  |  | ||||||
| #include "auxillary/builder.hpp" | #include "auxillary/builder.hpp" | ||||||
| @@ -24,20 +28,20 @@ constexpr char const* generation_notice = | |||||||
|  |  | ||||||
| void format_file( char const* path ) | void format_file( char const* path ) | ||||||
| { | { | ||||||
| 	String resolved_path = String::make(GlobalAllocator, to_str(path)); | 	String resolved_path = string_make_strc(GlobalAllocator, to_strc_from_c_str(path)); | ||||||
|  |  | ||||||
| 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | 	String style_arg = string_make_strc(GlobalAllocator, txt("-style=file:")); | ||||||
| 	style_arg.append("../scripts/.clang-format "); | 	string_append_strc( & style_arg, txt("../scripts/.clang-format ")); | ||||||
|  |  | ||||||
| 	// Need to execute clang format on the generated file to get it to match the original. | 	// Need to execute clang format on the generated file to get it to match the original. | ||||||
| 	#define clang_format      "clang-format " | 	#define clang_format      txt("clang-format ") | ||||||
| 	#define cf_format_inplace "-i " | 	#define cf_format_inplace txt("-i ") | ||||||
| 	#define cf_verbose        "-verbose " | 	#define cf_verbose        txt("-verbose ") | ||||||
| 	String command = String::make( GlobalAllocator, clang_format ); | 	String command = string_make_strc( GlobalAllocator, clang_format ); | ||||||
| 	command.append( cf_format_inplace ); | 	string_append_strc( & command, cf_format_inplace ); | ||||||
| 	command.append( cf_verbose ); | 	string_append_strc( & command, cf_verbose ); | ||||||
| 	command.append( style_arg ); | 	string_append_string( & command, style_arg ); | ||||||
| 	command.append( resolved_path ); | 	string_append_string( & command, resolved_path ); | ||||||
| 		log_fmt("\tRunning clang-format on file:\n"); | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
| 		system( command ); | 		system( command ); | ||||||
| 		log_fmt("\tclang-format finished reformatting.\n"); | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
| @@ -62,6 +66,8 @@ int gen_main() | |||||||
| { | { | ||||||
| 	gen::init(); | 	gen::init(); | ||||||
|  |  | ||||||
|  | 	// PreprocessorDefines.append("GEN_NS"); | ||||||
|  |  | ||||||
| 	Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp" ); | 	Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp" ); | ||||||
| 	Code pop_ignores  = scan_file( "helpers/pop_ignores.inline.hpp" ); | 	Code pop_ignores  = scan_file( "helpers/pop_ignores.inline.hpp" ); | ||||||
|  |  | ||||||
| @@ -141,7 +147,7 @@ int gen_main() | |||||||
| 		def_include(txt("components/types.hpp")), | 		def_include(txt("components/types.hpp")), | ||||||
| 		preprocess_endif, | 		preprocess_endif, | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		untyped_str( to_str(generation_notice) ) | 		untyped_str( to_strc_from_c_str(generation_notice) ) | ||||||
| 	)); | 	)); | ||||||
|  |  | ||||||
| 	// gen.hpp | 	// gen.hpp | ||||||
| @@ -239,7 +245,12 @@ int gen_main() | |||||||
| 		Code        untyped 	       = scan_file( "components/interface.untyped.cpp" ); | 		Code        untyped 	       = scan_file( "components/interface.untyped.cpp" ); | ||||||
|  |  | ||||||
| 		CodeBody etoktype         = gen_etoktype( "enums/ETokType.csv", "enums/AttributeTokens.csv" ); | 		CodeBody etoktype         = gen_etoktype( "enums/ETokType.csv", "enums/AttributeTokens.csv" ); | ||||||
| 		CodeNS   nspaced_etoktype = def_namespace( name(parser), def_namespace_body( args(etoktype)) ); | 		//CodeNS   nspaced_etoktype = def_namespace( name(parser), def_namespace_body( args(etoktype)) ); | ||||||
|  | 		CodeBody nspaced_etoktype = def_global_body( args( | ||||||
|  | 			untyped_str(txt("GEN_NS_PARSER_BEGIN\n")), | ||||||
|  | 			etoktype, | ||||||
|  | 			untyped_str(txt("GEN_NS_PARSER_END\n")) | ||||||
|  | 		)); | ||||||
|  |  | ||||||
| 		Builder | 		Builder | ||||||
| 		src = Builder::open( "gen/gen.cpp" ); | 		src = Builder::open( "gen/gen.cpp" ); | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -67,85 +67,117 @@ struct AST_Stmt_While; | |||||||
|  |  | ||||||
| struct AST_Struct; | struct AST_Struct; | ||||||
| struct AST_Template; | struct AST_Template; | ||||||
| struct AST_Type; | struct AST_Typename; | ||||||
| struct AST_Typedef; | struct AST_Typedef; | ||||||
| struct AST_Union; | struct AST_Union; | ||||||
| struct AST_Using; | struct AST_Using; | ||||||
| struct AST_Var; | struct AST_Var; | ||||||
|  |  | ||||||
| struct Code; | #if GEN_COMPILER_C | ||||||
| struct CodeBody; | #define Define_Code(Type) typedef AST_##Type* Code##Type | ||||||
| // These are to offer ease of use and optionally strong type safety for the AST. | #else | ||||||
| struct CodeAttributes; | #define Define_Code(Type) struct Code##Type | ||||||
| // struct CodeBaseClass; |  | ||||||
| struct CodeComment; |  | ||||||
| struct CodeClass; |  | ||||||
| struct CodeConstructor; |  | ||||||
| struct CodeDefine; |  | ||||||
| struct CodeDestructor; |  | ||||||
| struct CodeEnum; |  | ||||||
| struct CodeExec; |  | ||||||
| struct CodeExtern; |  | ||||||
| struct CodeInclude; |  | ||||||
| struct CodeFriend; |  | ||||||
| struct CodeFn; |  | ||||||
| struct CodeModule; |  | ||||||
| struct CodeNS; |  | ||||||
| struct CodeOperator; |  | ||||||
| struct CodeOpCast; |  | ||||||
| struct CodeParam; |  | ||||||
| struct CodePreprocessCond; |  | ||||||
| struct CodePragma; |  | ||||||
| struct CodeSpecifiers; |  | ||||||
|  |  | ||||||
| #if GEN_EXECUTION_EXPRESSION_SUPPORT |  | ||||||
| struct CodeExpr; |  | ||||||
| struct CodeExpr_Assign; |  | ||||||
| struct CodeExpr_Alignof; |  | ||||||
| struct CodeExpr_Binary; |  | ||||||
| struct CodeExpr_CStyleCast; |  | ||||||
| struct CodeExpr_FunctionalCast; |  | ||||||
| struct CodeExpr_CppCast; |  | ||||||
| struct CodeExpr_Element; |  | ||||||
| struct CodeExpr_ProcCall; |  | ||||||
| struct CodeExpr_Decltype; |  | ||||||
| struct CodeExpr_Comma; |  | ||||||
| struct CodeExpr_AMS; // Access Member Symbol |  | ||||||
| struct CodeExpr_Sizeof; |  | ||||||
| struct CodeExpr_Subscript; |  | ||||||
| struct CodeExpr_Ternary; |  | ||||||
| struct CodeExpr_UnaryPrefix; |  | ||||||
| struct CodeExpr_UnaryPostfix; |  | ||||||
|  |  | ||||||
| struct CodeStmt; |  | ||||||
| struct CodeStmt_Break; |  | ||||||
| struct CodeStmt_Case; |  | ||||||
| struct CodeStmt_Continue; |  | ||||||
| struct CodeStmt_Decl; |  | ||||||
| struct CodeStmt_Do; |  | ||||||
| struct CodeStmt_Expr; |  | ||||||
| struct CodeStmt_Else; |  | ||||||
| struct CodeStmt_If; |  | ||||||
| struct CodeStmt_For; |  | ||||||
| struct CodeStmt_Goto; |  | ||||||
| struct CodeStmt_Label; |  | ||||||
| struct CodeStmt_Switch; |  | ||||||
| struct CodeStmt_While; |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| struct CodeStruct; | #if GEN_COMPILER_C | ||||||
| struct CodeTemplate; | typedef AST* code; | ||||||
| struct CodeType; | #else | ||||||
| struct CodeTypedef; | struct Code; | ||||||
| struct CodeUnion; | #endif | ||||||
| struct CodeUsing; | Define_Code(Body); | ||||||
| struct CodeVar; | // These are to offer ease of use and optionally strong type safety for the AST. | ||||||
|  | Define_Code(Attributes); | ||||||
|  | // struct CodeBaseClass; | ||||||
|  | Define_Code(Comment); | ||||||
|  | Define_Code(Class); | ||||||
|  | Define_Code(Constructor); | ||||||
|  | Define_Code(Define); | ||||||
|  | Define_Code(Destructor); | ||||||
|  | Define_Code(Enum); | ||||||
|  | Define_Code(Exec); | ||||||
|  | Define_Code(Extern); | ||||||
|  | Define_Code(Include); | ||||||
|  | Define_Code(Friend); | ||||||
|  | Define_Code(Fn); | ||||||
|  | Define_Code(Module); | ||||||
|  | Define_Code(NS); | ||||||
|  | Define_Code(Operator); | ||||||
|  | Define_Code(OpCast); | ||||||
|  | Define_Code(Param); | ||||||
|  | Define_Code(PreprocessCond); | ||||||
|  | Define_Code(Pragma); | ||||||
|  | Define_Code(Specifiers); | ||||||
|  |  | ||||||
| namespace parser | #if GEN_EXECUTION_EXPRESSION_SUPPORT | ||||||
| { | Define_Code(Expr); | ||||||
|  | Define_Code(Expr_Assign); | ||||||
|  | Define_Code(Expr_Alignof); | ||||||
|  | Define_Code(Expr_Binary); | ||||||
|  | Define_Code(Expr_CStyleCast); | ||||||
|  | Define_Code(Expr_FunctionalCast); | ||||||
|  | Define_Code(Expr_CppCast); | ||||||
|  | Define_Code(Expr_Element); | ||||||
|  | Define_Code(Expr_ProcCall); | ||||||
|  | Define_Code(Expr_Decltype); | ||||||
|  | Define_Code(Expr_Comma); | ||||||
|  | Define_Code(Expr_AMS); // Access Member Symbol | ||||||
|  | Define_Code(Expr_Sizeof); | ||||||
|  | Define_Code(Expr_Subscript); | ||||||
|  | Define_Code(Expr_Ternary); | ||||||
|  | Define_Code(Expr_UnaryPrefix); | ||||||
|  | Define_Code(Expr_UnaryPostfix); | ||||||
|  |  | ||||||
|  | Define_Code(Stmt); | ||||||
|  | Define_Code(Stmt_Break); | ||||||
|  | Define_Code(Stmt_Case); | ||||||
|  | Define_Code(Stmt_Continue); | ||||||
|  | Define_Code(Stmt_Decl); | ||||||
|  | Define_Code(Stmt_Do); | ||||||
|  | Define_Code(Stmt_Expr); | ||||||
|  | Define_Code(Stmt_Else); | ||||||
|  | Define_Code(Stmt_If); | ||||||
|  | Define_Code(Stmt_For); | ||||||
|  | Define_Code(Stmt_Goto); | ||||||
|  | Define_Code(Stmt_Label); | ||||||
|  | Define_Code(Stmt_Switch); | ||||||
|  | Define_Code(Stmt_While); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | Define_Code(Struct); | ||||||
|  | Define_Code(Template); | ||||||
|  | Define_Code(Typename); | ||||||
|  | Define_Code(Typedef); | ||||||
|  | Define_Code(Union); | ||||||
|  | Define_Code(Using); | ||||||
|  | Define_Code(Var); | ||||||
|  | #undef Define_Code | ||||||
|  |  | ||||||
|  | GEN_NS_PARSER_BEGIN | ||||||
| struct Token; | struct Token; | ||||||
| } | GEN_NS_PARSER_END | ||||||
|  | typedef struct GEN_NS_PARSER Token Token; | ||||||
|  |  | ||||||
|  | #if ! GEN_COMPILER_C | ||||||
|  | template< class Type> forceinline Type tmpl_cast( Code self ) { return * rcast( Type*, & self ); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #pragma region Code Interface | ||||||
|  | void        append       (Code code, Code other ); | ||||||
|  | char const* debug_str    (Code code); | ||||||
|  | Code        duplicate    (Code code); | ||||||
|  | Code*       entry        (Code code, u32 idx ); | ||||||
|  | bool        has_entries  (Code code); | ||||||
|  | bool        is_body      (Code code); | ||||||
|  | bool        is_equal     (Code code, Code other); | ||||||
|  | bool        is_valid     (Code code); | ||||||
|  | void        set_global   (Code code); | ||||||
|  | String      to_string    (Code self ); | ||||||
|  | void        to_string    (Code self, String* result ); | ||||||
|  | char const* type_str     (Code self ); | ||||||
|  | bool        validate_body(Code self ); | ||||||
|  | #pragma endregion Code Interface | ||||||
|  |  | ||||||
|  | #if ! GEN_COMPILER_C | ||||||
| /* | /* | ||||||
| 	AST* wrapper | 	AST* wrapper | ||||||
| 	- Not constantly have to append the '*' as this is written often.. | 	- Not constantly have to append the '*' as this is written often.. | ||||||
| @@ -153,39 +185,36 @@ namespace parser | |||||||
| */ | */ | ||||||
| struct Code | struct Code | ||||||
| { | { | ||||||
| #	pragma region Statics | 	AST* ast; | ||||||
| 	// Used to identify ASTs that should always be duplicated. (Global constant ASTs) |  | ||||||
| 	static Code Global; |  | ||||||
|  |  | ||||||
| 	// Used to identify invalid generated code. |  | ||||||
| 	static Code Invalid; |  | ||||||
| #	pragma endregion Statics |  | ||||||
|  |  | ||||||
| #	define Using_Code( Typename )                                                     \ | #	define Using_Code( Typename )                                                     \ | ||||||
| 	char const* debug_str();               \ | 	char const* debug_str()                { return GEN_NS debug_str(* this); }       \ | ||||||
| 	Code        duplicate();			   \ | 	Code        duplicate()                { return GEN_NS duplicate(* this); }	      \ | ||||||
| 	bool        is_equal( Code other );    \ | 	bool        is_equal( Code other )     { return GEN_NS is_equal(* this, other); } \ | ||||||
| 	bool        is_valid();                \ | 	bool        is_body()                  { return GEN_NS is_body(* this); }         \ | ||||||
| 	void        set_global();              \ | 	bool        is_valid()                 { return GEN_NS is_valid(* this); }        \ | ||||||
| 	String      to_string();               \ | 	void        set_global()               { return GEN_NS set_global(* this); } | ||||||
| 	Typename&   operator = ( AST* other ); \ |  | ||||||
|  | #	define Using_CodeOps( Typename )                                         \ | ||||||
| 	Typename&   operator = ( Code other );                                   \ | 	Typename&   operator = ( Code other );                                   \ | ||||||
| 	bool        operator ==( Code other ); \ | 	bool        operator ==( Code other ) { return (AST*)ast == other.ast; } \ | ||||||
| 	bool        operator !=( Code other ); \ | 	bool        operator !=( Code other ) { return (AST*)ast != other.ast; } \ | ||||||
| 	operator bool(); | 	operator bool(); | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( Code ); | 	Using_Code( Code ); | ||||||
|  | 	void        append(Code other)        { return GEN_NS append(* this, other); } | ||||||
|  | 	Code*       entry(u32 idx)            { return GEN_NS entry(* this, idx); } | ||||||
|  | 	bool        has_entries()             { return GEN_NS has_entries(* this); } | ||||||
|  | 	String      to_string()               { return GEN_NS to_string(* this); } | ||||||
|  | 	void        to_string(String& result) { return GEN_NS to_string(* this, & result); } | ||||||
|  | 	char const* type_str()                { return GEN_NS type_str(* this); } | ||||||
|  | 	bool        validate_body()           { return GEN_NS validate_body(*this); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	template< class Type > | 	Using_CodeOps( Code ); | ||||||
| 	forceinline Type cast() |  | ||||||
| 	{ |  | ||||||
| 		return * rcast( Type*, this ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	AST* operator ->() | 	AST* operator ->() { return ast; } | ||||||
| 	{ |  | ||||||
| 		return ast; |  | ||||||
| 	} |  | ||||||
| 	Code& operator ++(); | 	Code& operator ++(); | ||||||
|  |  | ||||||
| 	// TODO(Ed) : Remove this overload. | 	// TODO(Ed) : Remove this overload. | ||||||
| @@ -200,7 +229,10 @@ struct Code | |||||||
| 		return *this; | 		return *this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	AST* ast; | 	       bool operator==(std::nullptr_t) const            { return ast == nullptr; } | ||||||
|  | 	       bool operator!=(std::nullptr_t) const            { return ast != nullptr; } | ||||||
|  | 	friend bool operator==(std::nullptr_t, const Code code) { return code.ast == nullptr; } | ||||||
|  | 	friend bool operator!=(std::nullptr_t, const Code code) { return code.ast != nullptr; } | ||||||
|  |  | ||||||
| #ifdef GEN_ENFORCE_STRONG_CODE_TYPES | #ifdef GEN_ENFORCE_STRONG_CODE_TYPES | ||||||
| #	define operator explicit operator | #	define operator explicit operator | ||||||
| @@ -229,232 +261,122 @@ struct Code | |||||||
| 	operator CodeSpecifiers() const; | 	operator CodeSpecifiers() const; | ||||||
| 	operator CodeStruct() const; | 	operator CodeStruct() const; | ||||||
| 	operator CodeTemplate() const; | 	operator CodeTemplate() const; | ||||||
| 	operator CodeType() const; | 	operator CodeTypename() const; | ||||||
| 	operator CodeTypedef() const; | 	operator CodeTypedef() const; | ||||||
| 	operator CodeUnion() const; | 	operator CodeUnion() const; | ||||||
| 	operator CodeUsing() const; | 	operator CodeUsing() const; | ||||||
| 	operator CodeVar() const; | 	operator CodeVar() const; | ||||||
| 	#undef operator | 	#undef operator | ||||||
| }; | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #pragma region Statics | ||||||
|  | // Used to identify ASTs that should always be duplicated. (Global constant ASTs) | ||||||
|  | extern Code Code_Global; | ||||||
|  |  | ||||||
|  | // Used to identify invalid generated code. | ||||||
|  | extern Code Code_Invalid; | ||||||
|  | #pragma endregion Statics | ||||||
|  |  | ||||||
| struct Code_POD | struct Code_POD | ||||||
| { | { | ||||||
| 	AST* ast; | 	AST* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static_assert( sizeof(Code) == sizeof(Code_POD), "ERROR: Code is not POD" ); | static_assert( sizeof(Code) == sizeof(Code_POD), "ERROR: Code is not POD" ); | ||||||
|  |  | ||||||
| // Desired width of the AST data structure. | // Desired width of the AST data structure. | ||||||
| constexpr int const AST_POD_Size = 128; | constexpr int const AST_POD_Size = 128; | ||||||
|  |  | ||||||
| /* |  | ||||||
| 	Simple AST POD with functionality to seralize into C++ syntax. |  | ||||||
| */ |  | ||||||
| struct AST |  | ||||||
| { |  | ||||||
| #	pragma region Member Functions |  | ||||||
| 	void        append     ( AST* other ); |  | ||||||
| 	char const* debug_str  (); |  | ||||||
| 	AST*        duplicate  (); |  | ||||||
| 	Code&       entry      ( u32 idx ); |  | ||||||
| 	bool        has_entries(); |  | ||||||
| 	bool        is_equal   ( AST* other ); |  | ||||||
| 	char const* type_str(); |  | ||||||
| 	bool        validate_body(); |  | ||||||
|  |  | ||||||
| 	String to_string(); |  | ||||||
|  |  | ||||||
| 	neverinline |  | ||||||
| 	void to_string( String& result ); |  | ||||||
|  |  | ||||||
| 	template< class Type > |  | ||||||
| 	forceinline Type cast() |  | ||||||
| 	{ |  | ||||||
| 		return * this; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator Code(); |  | ||||||
| 	operator CodeBody(); |  | ||||||
| 	operator CodeAttributes(); |  | ||||||
| 	// operator CodeBaseClass(); |  | ||||||
| 	operator CodeComment(); |  | ||||||
| 	operator CodeConstructor(); |  | ||||||
| 	operator CodeDestructor(); |  | ||||||
| 	operator CodeClass(); |  | ||||||
| 	operator CodeDefine(); |  | ||||||
| 	operator CodeEnum(); |  | ||||||
| 	operator CodeExec(); |  | ||||||
| 	operator CodeExtern(); |  | ||||||
| 	operator CodeInclude(); |  | ||||||
| 	operator CodeFriend(); |  | ||||||
| 	operator CodeFn(); |  | ||||||
| 	operator CodeModule(); |  | ||||||
| 	operator CodeNS(); |  | ||||||
| 	operator CodeOperator(); |  | ||||||
| 	operator CodeOpCast(); |  | ||||||
| 	operator CodeParam(); |  | ||||||
| 	operator CodePragma(); |  | ||||||
| 	operator CodePreprocessCond(); |  | ||||||
| 	operator CodeSpecifiers(); |  | ||||||
| 	operator CodeStruct(); |  | ||||||
| 	operator CodeTemplate(); |  | ||||||
| 	operator CodeType(); |  | ||||||
| 	operator CodeTypedef(); |  | ||||||
| 	operator CodeUnion(); |  | ||||||
| 	operator CodeUsing(); |  | ||||||
| 	operator CodeVar(); |  | ||||||
| #	pragma endregion Member Functions |  | ||||||
|  |  | ||||||
| constexpr static | constexpr static | ||||||
| 	int ArrSpecs_Cap = | int AST_ArrSpecs_Cap = | ||||||
| ( | ( | ||||||
| 		AST_POD_Size | 		AST_POD_Size | ||||||
| 		- sizeof(AST*) * 3 | 		- sizeof(AST*) * 3 | ||||||
| 		- sizeof(parser::Token*) | 		- sizeof(parser::Token*) | ||||||
| 		- sizeof(AST*) | 		- sizeof(AST*) | ||||||
| 		- sizeof(StringCached) | 		- sizeof(StringCached) | ||||||
| 			- sizeof(CodeT) | 		- sizeof(CodeType) | ||||||
| 		- sizeof(ModuleFlag) | 		- sizeof(ModuleFlag) | ||||||
| 		- sizeof(int) | 		- sizeof(int) | ||||||
| ) | ) | ||||||
| / sizeof(int) - 1; // -1 for 4 extra bytes | / sizeof(int) - 1; // -1 for 4 extra bytes | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | 	Simple AST POD with functionality to seralize into C++ syntax. | ||||||
|  | */ | ||||||
|  | struct AST | ||||||
|  | { | ||||||
| 	union { | 	union { | ||||||
| 		struct | 		struct | ||||||
| 		{ | 		{ | ||||||
| 			AST*      InlineCmt;       // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable | 			Code      InlineCmt;       // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable | ||||||
| 			AST*      Attributes;      // Class, Enum, Function, Struct, Typedef, Union, Using, Variable | 			Code      Attributes;      // Class, Enum, Function, Struct, Typedef, Union, Using, Variable | ||||||
| 			AST*      Specs;           // Destructor, Function, Operator, Typename, Variable | 			Code      Specs;           // Destructor, Function, Operator, Typename, Variable | ||||||
| 			union { | 			union { | ||||||
| 				AST*  InitializerList; // Constructor | 				Code  InitializerList; // Constructor | ||||||
| 				AST*  ParentType;      // Class, Struct, ParentType->Next has a possible list of interfaces. | 				Code  ParentType;      // Class, Struct, ParentType->Next has a possible list of interfaces. | ||||||
| 				AST*  ReturnType;      // Function, Operator, Typename | 				Code  ReturnType;      // Function, Operator, Typename | ||||||
| 				AST*  UnderlyingType;  // Enum, Typedef | 				Code  UnderlyingType;  // Enum, Typedef | ||||||
| 				AST*  ValueType;       // Parameter, Variable | 				Code  ValueType;       // Parameter, Variable | ||||||
| 			}; | 			}; | ||||||
| 			union { | 			union { | ||||||
| 				AST*  Macro;           // Parameter | 				Code  Macro;               // Parameter | ||||||
| 				AST*  BitfieldSize;    // Variable (Class/Struct Data Member) | 				Code  BitfieldSize;        // Variable (Class/Struct Data Member) | ||||||
| 				AST*  Params;          // Constructor, Function, Operator, Template, Typename | 				Code  Params;              // Constructor, Function, Operator, Template, Typename | ||||||
|  | 				Code  UnderlyingTypeMacro; // Enum | ||||||
| 			}; | 			}; | ||||||
| 			union { | 			union { | ||||||
| 				AST*  ArrExpr;          // Typename | 				Code  ArrExpr;          // Typename | ||||||
| 				AST*  Body;             // Class, Constructor, Destructor, Enum, Friend, Function, Namespace, Struct, Union | 				Code  Body;             // Class, Constructor, Destructor, Enum, Friend, Function, Namespace, Struct, Union | ||||||
| 				AST*  Declaration;      // Friend, Template | 				Code  Declaration;      // Friend, Template | ||||||
| 				AST*  Value;            // Parameter, Variable | 				Code  Value;            // Parameter, Variable | ||||||
| 			}; | 			}; | ||||||
| 			union { | 			union { | ||||||
| 				AST*  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) | 				Code  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) | ||||||
| 				AST*  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) | 				Code  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) | ||||||
| 				AST*  PostNameMacro;     // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) | 				Code  PostNameMacro;     // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 		StringCached  Content;          // Attributes, Comment, Execution, Include | 		StringCached  Content;          // Attributes, Comment, Execution, Include | ||||||
| 		struct { | 		struct { | ||||||
| 			SpecifierT ArrSpecs[ArrSpecs_Cap]; // Specifiers | 			Specifier  ArrSpecs[AST_ArrSpecs_Cap]; // Specifiers | ||||||
| 			AST*       NextSpecs;              // Specifiers; If ArrSpecs is full, then NextSpecs is used. | 			Code       NextSpecs;              // Specifiers; If ArrSpecs is full, then NextSpecs is used. | ||||||
| 		}; | 		}; | ||||||
| 	}; | 	}; | ||||||
| 	union { | 	union { | ||||||
| 		AST* Prev; | 		Code Prev; | ||||||
| 		AST* Front; | 		Code Front; | ||||||
| 		AST* Last; | 		Code Last; | ||||||
| 	}; | 	}; | ||||||
| 	union { | 	union { | ||||||
| 		AST* Next; | 		Code Next; | ||||||
| 		AST* Back; | 		Code Back; | ||||||
| 	}; | 	}; | ||||||
| 	parser::Token*    Token; // Reference to starting token, only avaialble if it was derived from parsing. | 	parser::Token*    Token; // Reference to starting token, only avaialble if it was derived from parsing. | ||||||
| 	AST*              Parent; | 	Code              Parent; | ||||||
| 	StringCached      Name; | 	StringCached      Name; | ||||||
| 	CodeT             Type; | 	CodeType          Type; | ||||||
| //	CodeFlag          CodeFlags; | //	CodeFlag          CodeFlags; | ||||||
| 	ModuleFlag        ModuleFlags; | 	ModuleFlag        ModuleFlags; | ||||||
| 	union { | 	union { | ||||||
| 		b32           IsFunction;  // Used by typedef to not serialize the name field. | 		b32           IsFunction;  // Used by typedef to not serialize the name field. | ||||||
| 		b32           IsParamPack; // Used by typename to know if type should be considered a parameter pack. | 		b32           IsParamPack; // Used by typename to know if type should be considered a parameter pack. | ||||||
| 		OperatorT     Op; | 		Operator      Op; | ||||||
| 		AccessSpec    ParentAccess; | 		AccessSpec    ParentAccess; | ||||||
| 		s32           NumEntries; | 		s32           NumEntries; | ||||||
| 		s32           VarConstructorInit;  // Used by variables to know that initialization is using a constructor expression instead of an assignment expression. | 		s32           VarConstructorInit;  // Used by variables to know that initialization is using a constructor expression instead of an assignment expression. | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  | static_assert( sizeof(AST) == AST_POD_Size, "ERROR: AST POD is not size of AST_POD_Size" ); | ||||||
|  |  | ||||||
| struct AST_POD | #if ! GEN_COMPILER_C | ||||||
| { | // Uses an implicitly overloaded cast from the AST to the desired code type. | ||||||
| 	union { | // Necessary if the user wants GEN_ENFORCE_STRONG_CODE_TYPES | ||||||
| 		struct | struct  InvalidCode_ImplictCaster; | ||||||
| 		{ | #define InvalidCode (InvalidCode_ImplictCaster{}) | ||||||
| 			AST*      InlineCmt;       // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable | #else | ||||||
| 			AST*      Attributes;      // Class, Enum, Function, Struct, Typedef, Union, Using, Variable | #define InvalidCode Code_Invalid | ||||||
| 			AST*      Specs;           // Destructor, Function, Operator, Typename, Variable | #endif | ||||||
| 			union { |  | ||||||
| 				AST*  InitializerList; // Constructor |  | ||||||
| 				AST*  ParentType;      // Class, Struct, ParentType->Next has a possible list of interfaces. |  | ||||||
| 				AST*  ReturnType;      // Function, Operator, Typename |  | ||||||
| 				AST*  UnderlyingType;  // Enum, Typedef |  | ||||||
| 				AST*  ValueType;       // Parameter, Variable |  | ||||||
| 			}; |  | ||||||
| 			union { |  | ||||||
| 				AST*  Macro;           // Parameter |  | ||||||
| 				AST*  BitfieldSize;    // Variable (Class/Struct Data Member) |  | ||||||
| 				AST*  Params;          // Constructor, Function, Operator, Template, Typename |  | ||||||
| 			}; |  | ||||||
| 			union { |  | ||||||
| 				AST*  ArrExpr;          // Typename |  | ||||||
| 				AST*  Body;             // Class, Constructr, Destructor, Enum, Friend, Function, Namespace, Struct, Union |  | ||||||
| 				AST*  Declaration;      // Friend, Template |  | ||||||
| 				AST*  Value;            // Parameter, Variable |  | ||||||
| 			}; |  | ||||||
| 			union { |  | ||||||
| 				AST*  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) |  | ||||||
| 				AST*  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) |  | ||||||
| 				AST*  PostNameMacro;    // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) |  | ||||||
| 			}; |  | ||||||
| 		}; |  | ||||||
| 		StringCached  Content;          // Attributes, Comment, Execution, Include |  | ||||||
| 		struct { |  | ||||||
| 			SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers |  | ||||||
| 			AST*       NextSpecs;                   // Specifiers; If ArrSpecs is full, then NextSpecs is used. |  | ||||||
| 		}; |  | ||||||
| 	}; |  | ||||||
| 	union { |  | ||||||
| 		AST* Prev; |  | ||||||
| 		AST* Front; |  | ||||||
| 		AST* Last; |  | ||||||
| 	}; |  | ||||||
| 	union { |  | ||||||
| 		AST* Next; |  | ||||||
| 		AST* Back; |  | ||||||
| 	}; |  | ||||||
| 	parser::Token*    Token; // Reference to starting token, only avaialble if it was derived from parsing. |  | ||||||
| 	AST*              Parent; |  | ||||||
| 	StringCached      Name; |  | ||||||
| 	CodeT             Type; |  | ||||||
| 	CodeFlag          CodeFlags; |  | ||||||
| 	ModuleFlag        ModuleFlags; |  | ||||||
| 	union { |  | ||||||
| 		b32           IsFunction;  // Used by typedef to not serialize the name field. |  | ||||||
| 		b32           IsParamPack; // Used by typename to know if type should be considered a parameter pack. |  | ||||||
| 		OperatorT     Op; |  | ||||||
| 		AccessSpec    ParentAccess; |  | ||||||
| 		s32           NumEntries; |  | ||||||
| 		s32           VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression. |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct test { |  | ||||||
| 	SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers |  | ||||||
| 	AST* NextSpecs;                         // Specifiers; If ArrSpecs is full, then NextSpecs is used. |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| constexpr int pls = sizeof(test); |  | ||||||
|  |  | ||||||
| // Its intended for the AST to have equivalent size to its POD. |  | ||||||
| // All extra functionality within the AST namespace should just be syntatic sugar. |  | ||||||
| static_assert( sizeof(AST)     == sizeof(AST_POD), "ERROR: AST IS NOT POD" ); |  | ||||||
| static_assert( sizeof(AST_POD) == AST_POD_Size,    "ERROR: AST POD is not size of AST_POD_Size" ); |  | ||||||
|  |  | ||||||
| // Used when the its desired when omission is allowed in a definition. | // Used when the its desired when omission is allowed in a definition. | ||||||
| #define NoCode      { nullptr } | #define NullCode    { nullptr } | ||||||
| #define CodeInvalid (* Code::Invalid.ast) // Uses an implicitly overloaded cast from the AST to the desired code type. |  | ||||||
|   | |||||||
| @@ -1,78 +1,78 @@ | |||||||
| #	define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \ | #	define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \ | ||||||
| 	case PlatformAttributes:                  \ | 	case CT_PlatformAttributes:                  \ | ||||||
| 	case Class_Body:                          \ | 	case CT_Class_Body:                          \ | ||||||
| 	case Enum_Body:                           \ | 	case CT_Enum_Body:                           \ | ||||||
| 	case Extern_Linkage:                      \ | 	case CT_Extern_Linkage:                      \ | ||||||
| 	case Function_Body:                       \ | 	case CT_Function_Body:                       \ | ||||||
| 	case Function_Fwd:                        \ | 	case CT_Function_Fwd:                        \ | ||||||
| 	case Global_Body:                         \ | 	case CT_Global_Body:                         \ | ||||||
| 	case Namespace:                           \ | 	case CT_Namespace:                           \ | ||||||
| 	case Namespace_Body:                      \ | 	case CT_Namespace_Body:                      \ | ||||||
| 	case Operator:                            \ | 	case CT_Operator:                            \ | ||||||
| 	case Operator_Fwd:                        \ | 	case CT_Operator_Fwd:                        \ | ||||||
| 	case Parameters:                          \ | 	case CT_Parameters:                          \ | ||||||
| 	case Specifiers:                          \ | 	case CT_Specifiers:                          \ | ||||||
| 	case Struct_Body:                         \ | 	case CT_Struct_Body:                         \ | ||||||
| 	case Typename: | 	case CT_Typename: | ||||||
| #	define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES | #	define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES | ||||||
|  |  | ||||||
| #	define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \ | #	define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \ | ||||||
| 	case Access_Public:                          \ | 	case CT_Access_Public:                          \ | ||||||
| 	case Access_Protected:                       \ | 	case CT_Access_Protected:                       \ | ||||||
| 	case Access_Private:                         \ | 	case CT_Access_Private:                         \ | ||||||
| 	case PlatformAttributes:                     \ | 	case CT_PlatformAttributes:                     \ | ||||||
| 	case Class_Body:                             \ | 	case CT_Class_Body:                             \ | ||||||
| 	case Enum_Body:                              \ | 	case CT_Enum_Body:                              \ | ||||||
| 	case Extern_Linkage:                         \ | 	case CT_Extern_Linkage:                         \ | ||||||
| 	case Friend:                                 \ | 	case CT_Friend:                                 \ | ||||||
| 	case Function_Body:                          \ | 	case CT_Function_Body:                          \ | ||||||
| 	case Function_Fwd:                           \ | 	case CT_Function_Fwd:                           \ | ||||||
| 	case Global_Body:                            \ | 	case CT_Global_Body:                            \ | ||||||
| 	case Namespace:                              \ | 	case CT_Namespace:                              \ | ||||||
| 	case Namespace_Body:                         \ | 	case CT_Namespace_Body:                         \ | ||||||
| 	case Operator:                               \ | 	case CT_Operator:                               \ | ||||||
| 	case Operator_Fwd:                           \ | 	case CT_Operator_Fwd:                           \ | ||||||
| 	case Operator_Member:                        \ | 	case CT_Operator_Member:                        \ | ||||||
| 	case Operator_Member_Fwd:                    \ | 	case CT_Operator_Member_Fwd:                    \ | ||||||
| 	case Parameters:                             \ | 	case CT_Parameters:                             \ | ||||||
| 	case Specifiers:                             \ | 	case CT_Specifiers:                             \ | ||||||
| 	case Struct_Body:                            \ | 	case CT_Struct_Body:                            \ | ||||||
| 	case Typename: | 	case CT_Typename: | ||||||
|  |  | ||||||
| #	define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES     \ | #	define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES     \ | ||||||
| 	case Access_Public: 				       \ | 	case CT_Access_Public:                         \ | ||||||
| 	case Access_Protected: 				       \ | 	case CT_Access_Protected:                      \ | ||||||
| 	case Access_Private: 				       \ | 	case CT_Access_Private:                        \ | ||||||
| 	case PlatformAttributes:                   \ | 	case CT_PlatformAttributes:                    \ | ||||||
| 	case Class_Body: 					       \ | 	case CT_Class_Body:                            \ | ||||||
| 	case Enum_Body: 					       \ | 	case CT_Enum_Body:                             \ | ||||||
| 	case Execution: 					       \ | 	case CT_Execution:                             \ | ||||||
| 	case Friend: 						       \ | 	case CT_Friend:                                \ | ||||||
| 	case Function_Body: 				       \ | 	case CT_Function_Body:                         \ | ||||||
| 	case Namespace_Body: 				       \ | 	case CT_Namespace_Body:                        \ | ||||||
| 	case Operator_Member: 				       \ | 	case CT_Operator_Member:                       \ | ||||||
| 	case Operator_Member_Fwd: 			       \ | 	case CT_Operator_Member_Fwd:                   \ | ||||||
| 	case Parameters: 					       \ | 	case CT_Parameters:                            \ | ||||||
| 	case Specifiers: 					       \ | 	case CT_Specifiers:                            \ | ||||||
| 	case Struct_Body: 					       \ | 	case CT_Struct_Body:                           \ | ||||||
| 	case Typename: | 	case CT_Typename: | ||||||
| #	define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES         GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES | #	define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES         GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||||
| #	define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES | #	define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||||
|  |  | ||||||
| #	define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \ | #	define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \ | ||||||
| 	case Access_Public: 				          \ | 	case CT_Access_Public:                        \ | ||||||
| 	case Access_Protected: 				          \ | 	case CT_Access_Protected:                     \ | ||||||
| 	case Access_Private: 				          \ | 	case CT_Access_Private:                       \ | ||||||
| 	case PlatformAttributes:                      \ | 	case CT_PlatformAttributes:                   \ | ||||||
| 	case Class_Body: 					          \ | 	case CT_Class_Body:                           \ | ||||||
| 	case Enum_Body: 					          \ | 	case CT_Enum_Body:                            \ | ||||||
| 	case Execution: 					          \ | 	case CT_Execution:                            \ | ||||||
| 	case Friend: 						          \ | 	case CT_Friend:                               \ | ||||||
| 	case Function_Body: 				          \ | 	case CT_Function_Body:                        \ | ||||||
| 	case Namespace_Body: 				          \ | 	case CT_Namespace_Body:                       \ | ||||||
| 	case Operator_Member: 				          \ | 	case CT_Operator_Member:                      \ | ||||||
| 	case Operator_Member_Fwd: 			          \ | 	case CT_Operator_Member_Fwd:                  \ | ||||||
| 	case Parameters: 					          \ | 	case CT_Parameters:                           \ | ||||||
| 	case Specifiers: 					          \ | 	case CT_Specifiers:                           \ | ||||||
| 	case Struct_Body: 					          \ | 	case CT_Struct_Body:                          \ | ||||||
| 	case Typename: | 	case CT_Typename: | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -3,75 +3,169 @@ | |||||||
| #include "ast.hpp" | #include "ast.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #pragma region Code Type Interface | ||||||
|  | void   append           ( CodeBody body, Code     other ); | ||||||
|  | void   append           ( CodeBody body, CodeBody other ); | ||||||
|  | String to_string        ( CodeBody body ); | ||||||
|  | void   to_string        ( CodeBody body, String* result ); | ||||||
|  | void   to_string_export ( CodeBody body, String* result ); | ||||||
|  |  | ||||||
|  | Code begin( CodeBody body); | ||||||
|  | Code end  ( CodeBody body ); | ||||||
|  |  | ||||||
|  | void   add_interface( CodeClass self, CodeType interface ); | ||||||
|  | String to_string    ( CodeClass self ); | ||||||
|  | void   to_string_def( CodeClass self, String* result ); | ||||||
|  | void   to_string_fwd( CodeClass self, String* result ); | ||||||
|  |  | ||||||
|  | void      append     (CodeParam params, CodeParam param ); | ||||||
|  | CodeParam get        (CodeParam params, s32 idx); | ||||||
|  | bool      has_entries(CodeParam params ); | ||||||
|  | String    to_string  (CodeParam params ); | ||||||
|  | void      to_string  (CodeParam params, String* result ); | ||||||
|  |  | ||||||
|  | CodeParam begin(CodeParam params); | ||||||
|  | CodeParam end  (CodeParam params); | ||||||
|  |  | ||||||
|  | bool   append   (CodeSpecifiers specifiers, Specifier spec); | ||||||
|  | s32    has      (CodeSpecifiers specifiers, Specifier spec); | ||||||
|  | s32    remove   (CodeSpecifiers specifiers, Specifier to_remove ); | ||||||
|  | String to_string(CodeSpecifiers specifiers); | ||||||
|  | void   to_string(CodeSpecifiers specifiers, String* result); | ||||||
|  |  | ||||||
|  | Specifier* begin(CodeSpecifiers specifiers ); | ||||||
|  | Specifier* end  (CodeSpecifiers specifiers); | ||||||
|  |  | ||||||
|  | void   add_interface(CodeStruct self, CodeType interface); | ||||||
|  | String to_string    (CodeStruct self); | ||||||
|  | void   to_string_fwd(CodeStruct self, String* result); | ||||||
|  | void   to_string_def(CodeStruct self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeAttributes attributes); | ||||||
|  | String to_string(CodeComment    comment ); | ||||||
|  |  | ||||||
|  | String to_string    (CodeConstructor constructor); | ||||||
|  | void   to_string_def(CodeConstructor constructor, String* result ); | ||||||
|  | void   to_string_fwd(CodeConstructor constructor, String* result ); | ||||||
|  |  | ||||||
|  | String to_string(CodeDefine define); | ||||||
|  | void   to_string(CodeDefine define, String* result); | ||||||
|  |  | ||||||
|  | String to_string    (CodeDestructor destructor); | ||||||
|  | void   to_string_def(CodeDestructor destructor, String* result ); | ||||||
|  | void   to_string_fwd(CodeDestructor destructor, String* result ); | ||||||
|  |  | ||||||
|  | String to_string          (CodeEnum self); | ||||||
|  | void   to_string_def      (CodeEnum self, String* result ); | ||||||
|  | void   to_string_fwd      (CodeEnum self, String* result ); | ||||||
|  | void   to_string_class_def(CodeEnum self, String* result ); | ||||||
|  | void   to_string_class_fwd(CodeEnum self, String* result ); | ||||||
|  |  | ||||||
|  | String to_string(CodeExec exec); | ||||||
|  |  | ||||||
|  | void to_string(CodeExtern self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeInclude include); | ||||||
|  | void   to_string(CodeInclude include, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeFriend self); | ||||||
|  | void   to_string(CodeFriend self, String* result); | ||||||
|  |  | ||||||
|  | String to_string    (CodeFn self); | ||||||
|  | void   to_string_def(CodeFn self, String* result); | ||||||
|  | void   to_string_fwd(CodeFn self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeModule self); | ||||||
|  | void   to_string(CodeModule self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeNS self); | ||||||
|  | void   to_string(CodeNS self, String* result); | ||||||
|  |  | ||||||
|  | String to_string    (CodeOperator self); | ||||||
|  | void   to_string_fwd(CodeOperator self, String* result ); | ||||||
|  | void   to_string_def(CodeOperator self, String* result ); | ||||||
|  |  | ||||||
|  | String to_string    (CodeOpCast op_cast ); | ||||||
|  | void   to_string_def(CodeOpCast op_cast, String* result ); | ||||||
|  | void   to_string_fwd(CodeOpCast op_cast, String* result ); | ||||||
|  |  | ||||||
|  | String to_string(CodePragma self); | ||||||
|  | void   to_string(CodePragma self, String* result); | ||||||
|  |  | ||||||
|  | String to_string       (CodePreprocessCond cond); | ||||||
|  | void   to_string_if    (CodePreprocessCond cond, String* result ); | ||||||
|  | void   to_string_ifdef (CodePreprocessCond cond, String* result ); | ||||||
|  | void   to_string_ifndef(CodePreprocessCond cond, String* result ); | ||||||
|  | void   to_string_elif  (CodePreprocessCond cond, String* result ); | ||||||
|  | void   to_string_else  (CodePreprocessCond cond, String* result ); | ||||||
|  | void   to_string_endif (CodePreprocessCond cond, String* result ); | ||||||
|  |  | ||||||
|  | String to_string(CodeTemplate self); | ||||||
|  | void   to_string(CodeTemplate self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeTypename self); | ||||||
|  | void   to_string(CodeTypename self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeTypedef self); | ||||||
|  | void   to_string(CodeTypedef self, String* result); | ||||||
|  |  | ||||||
|  | String to_string(CodeUnion self); | ||||||
|  | void   to_string_def(CodeUnion self, String* result); | ||||||
|  | void   to_string_fwd(CodeUnion self, String* result); | ||||||
|  |  | ||||||
|  | String to_string   (CodeUsing op_cast ); | ||||||
|  | void   to_string   (CodeUsing op_cast, String* result ); | ||||||
|  | void   to_string_ns(CodeUsing op_cast, String* result ); | ||||||
|  |  | ||||||
|  | String to_string(CodeVar self); | ||||||
|  | void   to_string(CodeVar self, String* result); | ||||||
|  | #pragma endregion Code Type Interface | ||||||
|  |  | ||||||
| #pragma region Code Types | #pragma region Code Types | ||||||
|  | // These structs are not used at all by the C vairant. | ||||||
|  | #if ! GEN_COMPILER_C | ||||||
|  | // stati_assert( GEN_COMPILER_C, "This should not be compiled with the C-library" ); | ||||||
|  |  | ||||||
|  | #define Verify_POD(Type) static_assert(size_of(Code##Type) == size_of(AST_##Type), "ERROR: Code##Type is not a POD") | ||||||
|  |  | ||||||
| struct CodeBody | struct CodeBody | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeBody ); | 	Using_Code( CodeBody ); | ||||||
|  |  | ||||||
| 	void append( Code other ) | 	void append( Code other )    { return GEN_NS append( *this, other ); } | ||||||
| 	{ | 	void append( CodeBody body ) { return GEN_NS append(*this, body); } | ||||||
| 		raw()->append( other.ast ); | 	bool has_entries()           { return GEN_NS has_entries(* this); } | ||||||
| 	} |  | ||||||
| 	void append( CodeBody body ) |  | ||||||
| 	{ |  | ||||||
| 		for ( Code entry : body ) |  | ||||||
| 		{ |  | ||||||
| 			append( entry ); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	bool has_entries() |  | ||||||
| 	{ |  | ||||||
| 		return rcast( AST*, ast )->has_entries(); |  | ||||||
| 	} |  | ||||||
| 	void to_string( String& result ); |  | ||||||
| 	void to_string_export( String& result ); |  | ||||||
| 	AST* raw() |  | ||||||
| 	{ |  | ||||||
| 		return rcast( AST*, ast ); |  | ||||||
| 	} |  | ||||||
| 	AST_Body* operator->() |  | ||||||
| 	{ |  | ||||||
| 		return ast; |  | ||||||
| 	} |  | ||||||
| 	operator Code() |  | ||||||
| 	{ |  | ||||||
| 		return * rcast( Code*, this ); |  | ||||||
| 	} |  | ||||||
| #pragma region Iterator |  | ||||||
| 	Code begin() |  | ||||||
| 	{ |  | ||||||
| 		if ( ast ) |  | ||||||
| 			return { rcast( AST*, ast)->Front }; |  | ||||||
|  |  | ||||||
| 		return { nullptr }; | 	String to_string()                        { return GEN_NS to_string(* this); } | ||||||
| 	} | 	void   to_string( String& result )        { return GEN_NS to_string(* this, & result ); } | ||||||
| 	Code end() | 	void   to_string_export( String& result ) { return GEN_NS to_string_export(* this, & result); } | ||||||
| 	{ |  | ||||||
| 		return { rcast(AST*, ast)->Back->Next }; | 	Code begin() { return GEN_NS begin(* this); } | ||||||
| 	} | 	Code end()   { return GEN_NS end(* this); } | ||||||
| #pragma endregion Iterator | #endif | ||||||
|  |  | ||||||
|  | 	Using_CodeOps( CodeBody ); | ||||||
|  | 	operator Code() { return * rcast( Code*, this ); } | ||||||
|  | 	AST_Body* operator->() { return ast; } | ||||||
|  |  | ||||||
| 	AST_Body* ast; | 	AST_Body* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct CodeClass | struct CodeClass | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeClass ); | 	Using_Code( CodeClass ); | ||||||
|  |  | ||||||
| 	void add_interface( CodeType interface ); | 	void add_interface( CodeType interface ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string_def( String& result ); | 	void   to_string_def( String& result ); | ||||||
| 	void   to_string_fwd( String& result ); | 	void   to_string_fwd( String& result ); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST* raw() | 	Using_CodeOps( CodeClass ); | ||||||
| 	{ | 	operator Code() { return * rcast( Code*, this ); } | ||||||
| 		return rcast( AST*, ast ); |  | ||||||
| 	} |  | ||||||
| 	operator Code() |  | ||||||
| 	{ |  | ||||||
| 		return * rcast( Code*, this ); |  | ||||||
| 	} |  | ||||||
| 	AST_Class* operator->() | 	AST_Class* operator->() | ||||||
| 	{ | 	{ | ||||||
| 		if ( ast == nullptr ) | 		if ( ast == nullptr ) | ||||||
| @@ -86,17 +180,17 @@ struct CodeClass | |||||||
|  |  | ||||||
| struct CodeParam | struct CodeParam | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeParam ); | 	Using_Code( CodeParam ); | ||||||
|  |  | ||||||
| 	void      append( CodeParam other ); | 	void      append( CodeParam other ); | ||||||
|  |  | ||||||
| 	CodeParam get( s32 idx ); | 	CodeParam get( s32 idx ); | ||||||
| 	bool      has_entries(); | 	bool      has_entries(); | ||||||
|  | 	String    to_string(); | ||||||
| 	void      to_string( String& result ); | 	void      to_string( String& result ); | ||||||
| 	AST* raw() | #endif | ||||||
| 	{ |  | ||||||
| 		return rcast( AST*, ast ); | 	Using_CodeOps( CodeParam ); | ||||||
| 	} |  | ||||||
| 	AST_Param* operator->() | 	AST_Param* operator->() | ||||||
| 	{ | 	{ | ||||||
| 		if ( ast == nullptr ) | 		if ( ast == nullptr ) | ||||||
| @@ -106,70 +200,27 @@ struct CodeParam | |||||||
| 		} | 		} | ||||||
| 		return ast; | 		return ast; | ||||||
| 	} | 	} | ||||||
| 	operator Code() | 	operator Code()       { return { (AST*)ast }; } | ||||||
| 	{ | 	CodeParam operator*() { return * this; } | ||||||
| 		return { (AST*)ast }; |  | ||||||
| 	} |  | ||||||
| #pragma region Iterator |  | ||||||
| 	CodeParam begin() |  | ||||||
| 	{ |  | ||||||
| 		if ( ast ) |  | ||||||
| 			return { ast }; |  | ||||||
|  |  | ||||||
| 		return { nullptr }; |  | ||||||
| 	} |  | ||||||
| 	CodeParam end() |  | ||||||
| 	{ |  | ||||||
| 		// return { (AST_Param*) rcast( AST*, ast)->Last }; |  | ||||||
| 		return { nullptr }; |  | ||||||
| 	} |  | ||||||
| 	CodeParam& operator++(); | 	CodeParam& operator++(); | ||||||
| 	CodeParam operator*() |  | ||||||
| 	{ |  | ||||||
| 		return * this; |  | ||||||
| 	} |  | ||||||
| #pragma endregion Iterator |  | ||||||
|  |  | ||||||
| 	AST_Param* ast; | 	AST_Param* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct CodeSpecifiers | struct CodeSpecifiers | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeSpecifiers ); | 	Using_Code( CodeSpecifiers ); | ||||||
|  |  | ||||||
| 	bool append( SpecifierT spec ) | 	bool   append( Specifier spec )       { return GEN_NS append(* this, spec); } | ||||||
| 	{ | 	s32    has( Specifier spec )          { return GEN_NS has(* this, spec); } | ||||||
| 		if ( ast == nullptr ) | 	s32    remove( Specifier to_remove )  { return GEN_NS remove(* this, to_remove); } | ||||||
| 		{ | 	String to_string()                    { return GEN_NS to_string(* this ); } | ||||||
| 			log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!"); | 	void   to_string( String& result )    { return GEN_NS to_string(* this, & result); } | ||||||
| 			return false; | #endif | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( raw()->NumEntries == AST::ArrSpecs_Cap ) | 	Using_CodeOps(CodeSpecifiers); | ||||||
| 		{ | 	operator Code() { return { (AST*) ast }; } | ||||||
| 			log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST::ArrSpecs_Cap ); |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		raw()->ArrSpecs[ raw()->NumEntries ] = spec; |  | ||||||
| 		raw()->NumEntries++; |  | ||||||
| 		return true; |  | ||||||
| 	} |  | ||||||
| 	s32 has( SpecifierT spec ) |  | ||||||
| 	{ |  | ||||||
| 		for ( s32 idx = 0; idx < raw()->NumEntries; idx++ ) |  | ||||||
| 		{ |  | ||||||
| 			if ( raw()->ArrSpecs[ idx ] == spec ) |  | ||||||
| 				return idx; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
| 	void to_string( String& result ); |  | ||||||
| 	AST* raw() |  | ||||||
| 	{ |  | ||||||
| 		return rcast( AST*, ast ); |  | ||||||
| 	} |  | ||||||
| 	AST_Specifiers* operator->() | 	AST_Specifiers* operator->() | ||||||
| 	{ | 	{ | ||||||
| 		if ( ast == nullptr ) | 		if ( ast == nullptr ) | ||||||
| @@ -179,44 +230,24 @@ struct CodeSpecifiers | |||||||
| 		} | 		} | ||||||
| 		return ast; | 		return ast; | ||||||
| 	} | 	} | ||||||
| 	operator Code() |  | ||||||
| 	{ |  | ||||||
| 		return { (AST*) ast }; |  | ||||||
| 	} |  | ||||||
| #pragma region Iterator |  | ||||||
| 	SpecifierT* begin() |  | ||||||
| 	{ |  | ||||||
| 		if ( ast ) |  | ||||||
| 			return & raw()->ArrSpecs[0]; |  | ||||||
|  |  | ||||||
| 		return nullptr; |  | ||||||
| 	} |  | ||||||
| 	SpecifierT* end() |  | ||||||
| 	{ |  | ||||||
| 		return raw()->ArrSpecs + raw()->NumEntries; |  | ||||||
| 	} |  | ||||||
| #pragma endregion Iterator |  | ||||||
|  |  | ||||||
| 	AST_Specifiers* ast; | 	AST_Specifiers* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct CodeStruct | struct CodeStruct | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeStruct ); | 	Using_Code( CodeStruct ); | ||||||
|  |  | ||||||
| 	void add_interface( CodeType interface ); | 	void add_interface( CodeType interface ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string(); | ||||||
| 	void   to_string_fwd( String& result ); | 	void   to_string_fwd( String& result ); | ||||||
|  | 	void   to_string_def( String& result ); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST* raw() | 	Using_CodeOps( CodeStruct ); | ||||||
| 	{ | 	operator Code() { return * rcast( Code*, this ); } | ||||||
| 		return rcast( AST*, ast ); |  | ||||||
| 	} |  | ||||||
| 	operator Code() |  | ||||||
| 	{ |  | ||||||
| 		return * rcast( Code*, this ); |  | ||||||
| 	} |  | ||||||
| 	AST_Struct* operator->() | 	AST_Struct* operator->() | ||||||
| 	{ | 	{ | ||||||
| 		if ( ast == nullptr ) | 		if ( ast == nullptr ) | ||||||
| @@ -229,28 +260,45 @@ struct CodeStruct | |||||||
| 	AST_Struct* ast; | 	AST_Struct* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define Define_CodeType( Typename )     \ | struct CodeAttributes | ||||||
| 	struct Code##Typename               \ | { | ||||||
| 	{                                   \ | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 		Using_Code( Code ## Typename ); \ | 	Using_Code(CodeAttributes); | ||||||
| 		AST*            raw();          \ | 	String to_string(); | ||||||
| 		operator        Code();         \ | #endif | ||||||
| 		AST_##Typename* operator->();   \ |  | ||||||
| 		AST_##Typename* ast;            \ | 	Using_CodeOps(CodeAttributes); | ||||||
| 	} | 	operator Code(); | ||||||
|  | 	AST_Attributes *operator->(); | ||||||
|  | 	AST_Attributes *ast; | ||||||
|  | }; | ||||||
|  |  | ||||||
| Define_CodeType( Attributes ); |  | ||||||
| // Define_CodeType( BaseClass ); | // Define_CodeType( BaseClass ); | ||||||
| Define_CodeType( Comment ); |  | ||||||
|  | struct CodeComment | ||||||
|  | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | 	Using_Code(CodeComment); | ||||||
|  | 	String to_string() { return GEN_NS to_string(* this); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	Using_CodeOps(CodeComment); | ||||||
|  | 	operator Code(); | ||||||
|  | 	AST_Comment *operator->(); | ||||||
|  | 	AST_Comment *ast; | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct CodeConstructor | struct CodeConstructor | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeConstructor ); | 	Using_Code( CodeConstructor ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string()                     { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_fwd( String& result ); | 	void   to_string_def( String& result ) { return GEN_NS to_string_def(* this, & result); } | ||||||
|  | 	void   to_string_fwd( String& result ) { return GEN_NS to_string_fwd(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*             raw(); | 	Using_CodeOps(CodeConstructor); | ||||||
| 	operator         Code(); | 	operator         Code(); | ||||||
| 	AST_Constructor* operator->(); | 	AST_Constructor* operator->(); | ||||||
| 	AST_Constructor* ast; | 	AST_Constructor* ast; | ||||||
| @@ -258,11 +306,14 @@ struct CodeConstructor | |||||||
|  |  | ||||||
| struct CodeDefine | struct CodeDefine | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeDefine ); | 	Using_Code( CodeDefine ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*        raw(); | 	Using_CodeOps(CodeDefine); | ||||||
| 	operator    Code(); | 	operator    Code(); | ||||||
| 	AST_Define* operator->(); | 	AST_Define* operator->(); | ||||||
| 	AST_Define* ast; | 	AST_Define* ast; | ||||||
| @@ -270,12 +321,15 @@ struct CodeDefine | |||||||
|  |  | ||||||
| struct CodeDestructor | struct CodeDestructor | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeDestructor ); | 	Using_Code( CodeDestructor ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string()                     { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_fwd( String& result ); | 	void   to_string_def( String& result ) { return GEN_NS to_string_def(* this, & result); } | ||||||
|  | 	void   to_string_fwd( String& result ) { return GEN_NS to_string_fwd(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*             raw(); | 	Using_CodeOps(CodeDestructor); | ||||||
| 	operator         Code(); | 	operator         Code(); | ||||||
| 	AST_Destructor* operator->(); | 	AST_Destructor* operator->(); | ||||||
| 	AST_Destructor* ast; | 	AST_Destructor* ast; | ||||||
| @@ -283,20 +337,34 @@ struct CodeDestructor | |||||||
|  |  | ||||||
| struct CodeEnum | struct CodeEnum | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeEnum ); | 	Using_Code( CodeEnum ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string()                            { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_fwd( String& result ); | 	void   to_string_def( String& result )        { return GEN_NS to_string_def(* this, & result); } | ||||||
| 	void to_string_class_def( String& result ); | 	void   to_string_fwd( String& result )        { return GEN_NS to_string_fwd(* this, & result); } | ||||||
| 	void to_string_class_fwd( String& result ); | 	void   to_string_class_def( String& result )  { return GEN_NS to_string_class_def(* this, & result); } | ||||||
|  | 	void   to_string_class_fwd( String& result )  { return GEN_NS to_string_class_fwd(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*      raw(); | 	Using_CodeOps(CodeEnum); | ||||||
| 	operator  Code(); | 	operator  Code(); | ||||||
| 	AST_Enum* operator->(); | 	AST_Enum* operator->(); | ||||||
| 	AST_Enum* ast; | 	AST_Enum* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| Define_CodeType( Exec ); | struct CodeExec | ||||||
|  | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | 	Using_Code(CodeExec); | ||||||
|  | 	String to_string() { return GEN_NS to_string(* this); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	Using_CodeOps(CodeExec); | ||||||
|  | 	operator Code(); | ||||||
|  | 	AST_Exec *operator->(); | ||||||
|  | 	AST_Exec *ast; | ||||||
|  | }; | ||||||
|  |  | ||||||
| #if GEN_EXECUTION_EXPRESSION_SUPPORT | #if GEN_EXECUTION_EXPRESSION_SUPPORT | ||||||
| struct CodeExpr | struct CodeExpr | ||||||
| @@ -506,11 +574,13 @@ struct CodeExpr_UnaryPostfix | |||||||
|  |  | ||||||
| struct CodeExtern | struct CodeExtern | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeExtern ); | 	Using_Code( CodeExtern ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	void to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*        raw(); | 	Using_CodeOps(CodeExtern); | ||||||
| 	operator    Code(); | 	operator    Code(); | ||||||
| 	AST_Extern* operator->(); | 	AST_Extern* operator->(); | ||||||
| 	AST_Extern* ast; | 	AST_Extern* ast; | ||||||
| @@ -518,11 +588,14 @@ struct CodeExtern | |||||||
|  |  | ||||||
| struct CodeInclude | struct CodeInclude | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeInclude ); | 	Using_Code( CodeInclude ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                  { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result )  { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*         raw(); | 	Using_CodeOps(CodeInclude); | ||||||
| 	operator     Code(); | 	operator     Code(); | ||||||
| 	AST_Include* operator->(); | 	AST_Include* operator->(); | ||||||
| 	AST_Include* ast; | 	AST_Include* ast; | ||||||
| @@ -530,11 +603,14 @@ struct CodeInclude | |||||||
|  |  | ||||||
| struct CodeFriend | struct CodeFriend | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeFriend ); | 	Using_Code( CodeFriend ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*        raw(); | 	Using_CodeOps(CodeFriend); | ||||||
| 	operator    Code(); | 	operator    Code(); | ||||||
| 	AST_Friend* operator->(); | 	AST_Friend* operator->(); | ||||||
| 	AST_Friend* ast; | 	AST_Friend* ast; | ||||||
| @@ -542,12 +618,15 @@ struct CodeFriend | |||||||
|  |  | ||||||
| struct CodeFn | struct CodeFn | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeFn ); | 	Using_Code( CodeFn ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string()                     { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_fwd( String& result ); | 	void   to_string_def( String& result ) { return GEN_NS to_string_def(* this, & result); } | ||||||
|  | 	void   to_string_fwd( String& result ) { return GEN_NS to_string_fwd(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*     raw(); | 	Using_CodeOps(CodeFn); | ||||||
| 	operator Code(); | 	operator Code(); | ||||||
| 	AST_Fn*  operator->(); | 	AST_Fn*  operator->(); | ||||||
| 	AST_Fn*  ast; | 	AST_Fn*  ast; | ||||||
| @@ -555,11 +634,14 @@ struct CodeFn | |||||||
|  |  | ||||||
| struct CodeModule | struct CodeModule | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeModule ); | 	Using_Code( CodeModule ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*        raw(); | 	Using_CodeOps(CodeModule); | ||||||
| 	operator    Code(); | 	operator    Code(); | ||||||
| 	AST_Module* operator->(); | 	AST_Module* operator->(); | ||||||
| 	AST_Module* ast; | 	AST_Module* ast; | ||||||
| @@ -567,11 +649,14 @@ struct CodeModule | |||||||
|  |  | ||||||
| struct CodeNS | struct CodeNS | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeNS ); | 	Using_Code( CodeNS ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*     raw(); | 	Using_CodeOps(CodeNS); | ||||||
| 	operator Code(); | 	operator Code(); | ||||||
| 	AST_NS*  operator->(); | 	AST_NS*  operator->(); | ||||||
| 	AST_NS*  ast; | 	AST_NS*  ast; | ||||||
| @@ -579,12 +664,15 @@ struct CodeNS | |||||||
|  |  | ||||||
| struct CodeOperator | struct CodeOperator | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeOperator ); | 	Using_Code( CodeOperator ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string()                     { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_fwd( String& result ); | 	void   to_string_def( String& result ) { return GEN_NS to_string_def(* this, & result); } | ||||||
|  | 	void   to_string_fwd( String& result ) { return GEN_NS to_string_fwd(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*          raw(); | 	Using_CodeOps(CodeOperator); | ||||||
| 	operator      Code(); | 	operator      Code(); | ||||||
| 	AST_Operator* operator->(); | 	AST_Operator* operator->(); | ||||||
| 	AST_Operator* ast; | 	AST_Operator* ast; | ||||||
| @@ -592,12 +680,15 @@ struct CodeOperator | |||||||
|  |  | ||||||
| struct CodeOpCast | struct CodeOpCast | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeOpCast ); | 	Using_Code( CodeOpCast ); | ||||||
|  |  | ||||||
| 	void to_string_def( String& result ); | 	String to_string()                     { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_fwd( String& result ); | 	void   to_string_def( String& result ) { return GEN_NS to_string_def(* this, & result); } | ||||||
|  | 	void   to_string_fwd( String& result ) { return GEN_NS to_string_fwd(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*        raw(); | 	Using_CodeOps(CodeOpCast); | ||||||
| 	operator    Code(); | 	operator    Code(); | ||||||
| 	AST_OpCast* operator->(); | 	AST_OpCast* operator->(); | ||||||
| 	AST_OpCast* ast; | 	AST_OpCast* ast; | ||||||
| @@ -605,11 +696,14 @@ struct CodeOpCast | |||||||
|  |  | ||||||
| struct CodePragma | struct CodePragma | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1 | ||||||
| 	Using_Code( CodePragma ); | 	Using_Code( CodePragma ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*        raw(); | 	Using_CodeOps( CodePragma ); | ||||||
| 	operator    Code(); | 	operator    Code(); | ||||||
| 	AST_Pragma* operator->(); | 	AST_Pragma* operator->(); | ||||||
| 	AST_Pragma* ast; | 	AST_Pragma* ast; | ||||||
| @@ -617,16 +711,19 @@ struct CodePragma | |||||||
|  |  | ||||||
| struct CodePreprocessCond | struct CodePreprocessCond | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodePreprocessCond ); | 	Using_Code( CodePreprocessCond ); | ||||||
|  |  | ||||||
| 	void to_string_if( String& result ); | 	String to_string()                        { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_ifdef( String& result ); | 	void   to_string_if( String& result )     { return GEN_NS to_string_if(* this, & result); } | ||||||
| 	void to_string_ifndef( String& result ); | 	void   to_string_ifdef( String& result )  { return GEN_NS to_string_ifdef(* this, & result); } | ||||||
| 	void to_string_elif( String& result ); | 	void   to_string_ifndef( String& result ) { return GEN_NS to_string_ifndef(* this, & result); } | ||||||
| 	void to_string_else( String& result ); | 	void   to_string_elif( String& result )   { return GEN_NS to_string_elif(* this, & result); } | ||||||
| 	void to_string_endif( String& result ); | 	void   to_string_else( String& result )   { return GEN_NS to_string_else(* this, & result); } | ||||||
|  | 	void   to_string_endif( String& result )  { return GEN_NS to_string_endif(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*                raw(); | 	Using_CodeOps( CodePreprocessCond ); | ||||||
| 	operator            Code(); | 	operator            Code(); | ||||||
| 	AST_PreprocessCond* operator->(); | 	AST_PreprocessCond* operator->(); | ||||||
| 	AST_PreprocessCond* ast; | 	AST_PreprocessCond* ast; | ||||||
| @@ -637,6 +734,7 @@ struct CodeStmt | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt ); | 	Using_Code( CodeStmt ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*      raw(); | 	AST*      raw(); | ||||||
| @@ -649,6 +747,7 @@ struct CodeStmt_Break | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Break ); | 	Using_Code( CodeStmt_Break ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*            raw(); | 	AST*            raw(); | ||||||
| @@ -661,6 +760,7 @@ struct CodeStmt_Case | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Case ); | 	Using_Code( CodeStmt_Case ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -673,6 +773,7 @@ struct CodeStmt_Continue | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Continue ); | 	Using_Code( CodeStmt_Continue ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*               raw(); | 	AST*               raw(); | ||||||
| @@ -685,6 +786,7 @@ struct CodeStmt_Decl | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Decl ); | 	Using_Code( CodeStmt_Decl ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -697,6 +799,7 @@ struct CodeStmt_Do | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Do ); | 	Using_Code( CodeStmt_Do ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*         raw(); | 	AST*         raw(); | ||||||
| @@ -709,6 +812,7 @@ struct CodeStmt_Expr | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Expr ); | 	Using_Code( CodeStmt_Expr ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -721,6 +825,7 @@ struct CodeStmt_Else | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Else ); | 	Using_Code( CodeStmt_Else ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -733,6 +838,7 @@ struct CodeStmt_If | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_If ); | 	Using_Code( CodeStmt_If ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*         raw(); | 	AST*         raw(); | ||||||
| @@ -745,6 +851,7 @@ struct CodeStmt_For | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_For ); | 	Using_Code( CodeStmt_For ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*          raw(); | 	AST*          raw(); | ||||||
| @@ -757,6 +864,7 @@ struct CodeStmt_Goto | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Goto ); | 	Using_Code( CodeStmt_Goto ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -769,6 +877,7 @@ struct CodeStmt_Label | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Label ); | 	Using_Code( CodeStmt_Label ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*            raw(); | 	AST*            raw(); | ||||||
| @@ -781,6 +890,7 @@ struct CodeStmt_Switch | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_Switch ); | 	Using_Code( CodeStmt_Switch ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -793,6 +903,7 @@ struct CodeStmt_While | |||||||
| { | { | ||||||
| 	Using_Code( CodeStmt_While ); | 	Using_Code( CodeStmt_While ); | ||||||
|  |  | ||||||
|  | 	String to_string(); | ||||||
| 	void   to_string( String& result ); | 	void   to_string( String& result ); | ||||||
|  |  | ||||||
| 	AST*           raw(); | 	AST*           raw(); | ||||||
| @@ -804,35 +915,44 @@ struct CodeStmt_While | |||||||
|  |  | ||||||
| struct CodeTemplate | struct CodeTemplate | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeTemplate ); | 	Using_Code( CodeTemplate ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*          raw(); | 	Using_CodeOps( CodeTemplate ); | ||||||
| 	operator      Code(); | 	operator      Code(); | ||||||
| 	AST_Template* operator->(); | 	AST_Template* operator->(); | ||||||
| 	AST_Template* ast; | 	AST_Template* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct CodeType | struct CodeTypename | ||||||
| { | { | ||||||
| 	Using_Code( CodeType ); | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | 	Using_Code( CodeTypename ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*      raw(); | 	Using_CodeOps( CodeTypename ); | ||||||
| 	operator      Code(); | 	operator      Code(); | ||||||
| 	AST_Type* operator->(); | 	AST_Typename* operator->(); | ||||||
| 	AST_Type* ast; | 	AST_Typename* ast; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct CodeTypedef | struct CodeTypedef | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeTypedef ); | 	Using_Code( CodeTypedef ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*         raw(); | 	Using_CodeOps( CodeTypedef ); | ||||||
| 	operator     Code(); | 	operator     Code(); | ||||||
| 	AST_Typedef* operator->(); | 	AST_Typedef* operator->(); | ||||||
| 	AST_Typedef* ast; | 	AST_Typedef* ast; | ||||||
| @@ -840,11 +960,14 @@ struct CodeTypedef | |||||||
|  |  | ||||||
| struct CodeUnion | struct CodeUnion | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeUnion ); | 	Using_Code( CodeUnion ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*       raw(); | 	Using_CodeOps(CodeUnion); | ||||||
| 	operator   Code(); | 	operator   Code(); | ||||||
| 	AST_Union* operator->(); | 	AST_Union* operator->(); | ||||||
| 	AST_Union* ast; | 	AST_Union* ast; | ||||||
| @@ -852,12 +975,15 @@ struct CodeUnion | |||||||
|  |  | ||||||
| struct CodeUsing | struct CodeUsing | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeUsing ); | 	Using_Code( CodeUsing ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                    { return GEN_NS to_string(* this); } | ||||||
| 	void to_string_ns( String& result ); | 	void   to_string( String& result )    { return GEN_NS to_string(* this, & result); } | ||||||
|  | 	void   to_string_ns( String& result ) { return GEN_NS to_string_ns(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*       raw(); | 	Using_CodeOps(CodeUsing); | ||||||
| 	operator   Code(); | 	operator   Code(); | ||||||
| 	AST_Using* operator->(); | 	AST_Using* operator->(); | ||||||
| 	AST_Using* ast; | 	AST_Using* ast; | ||||||
| @@ -865,11 +991,14 @@ struct CodeUsing | |||||||
|  |  | ||||||
| struct CodeVar | struct CodeVar | ||||||
| { | { | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	Using_Code( CodeVar ); | 	Using_Code( CodeVar ); | ||||||
|  |  | ||||||
| 	void to_string( String& result ); | 	String to_string()                 { return GEN_NS to_string(* this); } | ||||||
|  | 	void   to_string( String& result ) { return GEN_NS to_string(* this, & result); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	AST*     raw(); | 	Using_CodeOps(CodeVar); | ||||||
| 	operator Code(); | 	operator Code(); | ||||||
| 	AST_Var* operator->(); | 	AST_Var* operator->(); | ||||||
| 	AST_Var* ast; | 	AST_Var* ast; | ||||||
| @@ -877,5 +1006,48 @@ struct CodeVar | |||||||
|  |  | ||||||
| #undef Define_CodeType | #undef Define_CodeType | ||||||
| #undef Using_Code | #undef Using_Code | ||||||
|  | #undef Using_CodeOps | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | void to_string_export( CodeBody body, String& result ) { return to_string_export(body, & result); }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #undef Verify_POD | ||||||
|  |  | ||||||
|  | struct InvalidCode_ImplictCaster | ||||||
|  | { | ||||||
|  | 	// operator CodeBaseClass() const; | ||||||
|  |     operator Code              () const { return Code_Invalid; } | ||||||
|  |     operator CodeBody          () const { return cast(CodeBody,           Code_Invalid); } | ||||||
|  |     operator CodeAttributes    () const { return cast(CodeAttributes,     Code_Invalid); } | ||||||
|  |     operator CodeComment       () const { return cast(CodeComment,        Code_Invalid); } | ||||||
|  |     operator CodeClass         () const { return cast(CodeClass,          Code_Invalid); } | ||||||
|  |     operator CodeConstructor   () const { return cast(CodeConstructor,    Code_Invalid); } | ||||||
|  |     operator CodeDefine        () const { return cast(CodeDefine,         Code_Invalid); } | ||||||
|  |     operator CodeDestructor    () const { return cast(CodeDestructor,     Code_Invalid); } | ||||||
|  |     operator CodeExec          () const { return cast(CodeExec,           Code_Invalid); } | ||||||
|  |     operator CodeEnum          () const { return cast(CodeEnum,           Code_Invalid); } | ||||||
|  |     operator CodeExtern        () const { return cast(CodeExtern,         Code_Invalid); } | ||||||
|  |     operator CodeInclude       () const { return cast(CodeInclude,        Code_Invalid); } | ||||||
|  |     operator CodeFriend        () const { return cast(CodeFriend,         Code_Invalid); } | ||||||
|  |     operator CodeFn            () const { return cast(CodeFn,             Code_Invalid); } | ||||||
|  |     operator CodeModule        () const { return cast(CodeModule,         Code_Invalid); } | ||||||
|  |     operator CodeNS            () const { return cast(CodeNS,             Code_Invalid); } | ||||||
|  |     operator CodeOperator      () const { return cast(CodeOperator,       Code_Invalid); } | ||||||
|  |     operator CodeOpCast        () const { return cast(CodeOpCast,         Code_Invalid); } | ||||||
|  |     operator CodeParam         () const { return cast(CodeParam,          Code_Invalid); } | ||||||
|  |     operator CodePragma        () const { return cast(CodePragma,         Code_Invalid); } | ||||||
|  |     operator CodePreprocessCond() const { return cast(CodePreprocessCond, Code_Invalid); } | ||||||
|  |     operator CodeSpecifiers    () const { return cast(CodeSpecifiers,     Code_Invalid); } | ||||||
|  |     operator CodeStruct        () const { return cast(CodeStruct,         Code_Invalid); } | ||||||
|  |     operator CodeTemplate      () const { return cast(CodeTemplate,       Code_Invalid); } | ||||||
|  |     operator CodeTypename      () const { return cast(CodeTypename,       Code_Invalid); } | ||||||
|  |     operator CodeTypedef       () const { return cast(CodeTypedef,        Code_Invalid); } | ||||||
|  |     operator CodeUnion         () const { return cast(CodeUnion,          Code_Invalid); } | ||||||
|  |     operator CodeUsing         () const { return cast(CodeUsing,          Code_Invalid); } | ||||||
|  |     operator CodeVar           () const { return cast(CodeVar,            Code_Invalid); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif //if ! GEN_COMPILER_C | ||||||
|  |  | ||||||
| #pragma endregion Code Types | #pragma endregion Code Types | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -5,74 +5,74 @@ | |||||||
|  |  | ||||||
| // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | ||||||
|  |  | ||||||
| namespace ECode | enum CodeType_Def : u32 | ||||||
| { | { | ||||||
| 	enum Type : u32 | 	CT_Invalid, | ||||||
| 	{ | 	CT_Untyped, | ||||||
| 		Invalid, | 	CT_NewLine, | ||||||
| 		Untyped, | 	CT_Comment, | ||||||
| 		NewLine, | 	CT_Access_Private, | ||||||
| 		Comment, | 	CT_Access_Protected, | ||||||
| 		Access_Private, | 	CT_Access_Public, | ||||||
| 		Access_Protected, | 	CT_PlatformAttributes, | ||||||
| 		Access_Public, | 	CT_Class, | ||||||
| 		PlatformAttributes, | 	CT_Class_Fwd, | ||||||
| 		Class, | 	CT_Class_Body, | ||||||
| 		Class_Fwd, | 	CT_Constructor, | ||||||
| 		Class_Body, | 	CT_Constructor_Fwd, | ||||||
| 		Constructor, | 	CT_Destructor, | ||||||
| 		Constructor_Fwd, | 	CT_Destructor_Fwd, | ||||||
| 		Destructor, | 	CT_Enum, | ||||||
| 		Destructor_Fwd, | 	CT_Enum_Fwd, | ||||||
| 		Enum, | 	CT_Enum_Body, | ||||||
| 		Enum_Fwd, | 	CT_Enum_Class, | ||||||
| 		Enum_Body, | 	CT_Enum_Class_Fwd, | ||||||
| 		Enum_Class, | 	CT_Execution, | ||||||
| 		Enum_Class_Fwd, | 	CT_Export_Body, | ||||||
| 		Execution, | 	CT_Extern_Linkage, | ||||||
| 		Export_Body, | 	CT_Extern_Linkage_Body, | ||||||
| 		Extern_Linkage, | 	CT_Friend, | ||||||
| 		Extern_Linkage_Body, | 	CT_Function, | ||||||
| 		Friend, | 	CT_Function_Fwd, | ||||||
| 		Function, | 	CT_Function_Body, | ||||||
| 		Function_Fwd, | 	CT_Global_Body, | ||||||
| 		Function_Body, | 	CT_Module, | ||||||
| 		Global_Body, | 	CT_Namespace, | ||||||
| 		Module, | 	CT_Namespace_Body, | ||||||
| 		Namespace, | 	CT_Operator, | ||||||
| 		Namespace_Body, | 	CT_Operator_Fwd, | ||||||
| 		Operator, | 	CT_Operator_Member, | ||||||
| 		Operator_Fwd, | 	CT_Operator_Member_Fwd, | ||||||
| 		Operator_Member, | 	CT_Operator_Cast, | ||||||
| 		Operator_Member_Fwd, | 	CT_Operator_Cast_Fwd, | ||||||
| 		Operator_Cast, | 	CT_Parameters, | ||||||
| 		Operator_Cast_Fwd, | 	CT_Preprocess_Define, | ||||||
| 		Parameters, | 	CT_Preprocess_Include, | ||||||
| 		Preprocess_Define, | 	CT_Preprocess_If, | ||||||
| 		Preprocess_Include, | 	CT_Preprocess_IfDef, | ||||||
| 		Preprocess_If, | 	CT_Preprocess_IfNotDef, | ||||||
| 		Preprocess_IfDef, | 	CT_Preprocess_ElIf, | ||||||
| 		Preprocess_IfNotDef, | 	CT_Preprocess_Else, | ||||||
| 		Preprocess_ElIf, | 	CT_Preprocess_EndIf, | ||||||
| 		Preprocess_Else, | 	CT_Preprocess_Pragma, | ||||||
| 		Preprocess_EndIf, | 	CT_Specifiers, | ||||||
| 		Preprocess_Pragma, | 	CT_Struct, | ||||||
| 		Specifiers, | 	CT_Struct_Fwd, | ||||||
| 		Struct, | 	CT_Struct_Body, | ||||||
| 		Struct_Fwd, | 	CT_Template, | ||||||
| 		Struct_Body, | 	CT_Typedef, | ||||||
| 		Template, | 	CT_Typename, | ||||||
| 		Typedef, | 	CT_Union, | ||||||
| 		Typename, | 	CT_Union_Fwd, | ||||||
| 		Union, | 	CT_Union_Body, | ||||||
| 		Union_Body, | 	CT_Using, | ||||||
| 		Using, | 	CT_Using_Namespace, | ||||||
| 		Using_Namespace, | 	CT_Variable, | ||||||
| 		Variable, | 	CT_NumTypes | ||||||
| 		NumTypes |  | ||||||
| }; | }; | ||||||
|  | typedef enum CodeType_Def CodeType; | ||||||
|  |  | ||||||
| 	inline StrC to_str( Type type ) | inline StrC to_str( CodeType type ) | ||||||
| { | { | ||||||
| 	local_persist StrC lookup[] { | 	local_persist StrC lookup[] { | ||||||
| 		{ sizeof( "Invalid" ),             "Invalid"             }, | 		{ sizeof( "Invalid" ),             "Invalid"             }, | ||||||
| @@ -131,6 +131,7 @@ namespace ECode | |||||||
| 		{ sizeof( "Typedef" ),             "Typedef"             }, | 		{ sizeof( "Typedef" ),             "Typedef"             }, | ||||||
| 		{ sizeof( "Typename" ),            "Typename"            }, | 		{ sizeof( "Typename" ),            "Typename"            }, | ||||||
| 		{ sizeof( "Union" ),               "Union"               }, | 		{ sizeof( "Union" ),               "Union"               }, | ||||||
|  | 		{ sizeof( "Union_Fwd" ),           "Union_Fwd"           }, | ||||||
| 		{ sizeof( "Union_Body" ),          "Union_Body"          }, | 		{ sizeof( "Union_Body" ),          "Union_Body"          }, | ||||||
| 		{ sizeof( "Using" ),               "Using"               }, | 		{ sizeof( "Using" ),               "Using"               }, | ||||||
| 		{ sizeof( "Using_Namespace" ),     "Using_Namespace"     }, | 		{ sizeof( "Using_Namespace" ),     "Using_Namespace"     }, | ||||||
| @@ -138,7 +139,3 @@ namespace ECode | |||||||
| 	}; | 	}; | ||||||
| 	return lookup[type]; | 	return lookup[type]; | ||||||
| } | } | ||||||
|  |  | ||||||
| }    // namespace ECode |  | ||||||
|  |  | ||||||
| using CodeT = ECode::Type; |  | ||||||
|   | |||||||
| @@ -5,61 +5,60 @@ | |||||||
|  |  | ||||||
| // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | ||||||
|  |  | ||||||
| namespace EOperator | enum Operator_Def : u32 | ||||||
| { | { | ||||||
| 	enum Type : u32 | 	Op_Invalid, | ||||||
| 	{ | 	Op_Assign, | ||||||
| 		Invalid, | 	Op_Assign_Add, | ||||||
| 		Assign, | 	Op_Assign_Subtract, | ||||||
| 		Assign_Add, | 	Op_Assign_Multiply, | ||||||
| 		Assign_Subtract, | 	Op_Assign_Divide, | ||||||
| 		Assign_Multiply, | 	Op_Assign_Modulo, | ||||||
| 		Assign_Divide, | 	Op_Assign_BAnd, | ||||||
| 		Assign_Modulo, | 	Op_Assign_BOr, | ||||||
| 		Assign_BAnd, | 	Op_Assign_BXOr, | ||||||
| 		Assign_BOr, | 	Op_Assign_LShift, | ||||||
| 		Assign_BXOr, | 	Op_Assign_RShift, | ||||||
| 		Assign_LShift, | 	Op_Increment, | ||||||
| 		Assign_RShift, | 	Op_Decrement, | ||||||
| 		Increment, | 	Op_Unary_Plus, | ||||||
| 		Decrement, | 	Op_Unary_Minus, | ||||||
| 		Unary_Plus, | 	Op_UnaryNot, | ||||||
| 		Unary_Minus, | 	Op_Add, | ||||||
| 		UnaryNot, | 	Op_Subtract, | ||||||
| 		Add, | 	Op_Multiply, | ||||||
| 		Subtract, | 	Op_Divide, | ||||||
| 		Multiply, | 	Op_Modulo, | ||||||
| 		Divide, | 	Op_BNot, | ||||||
| 		Modulo, | 	Op_BAnd, | ||||||
| 		BNot, | 	Op_BOr, | ||||||
| 		BAnd, | 	Op_BXOr, | ||||||
| 		BOr, | 	Op_LShift, | ||||||
| 		BXOr, | 	Op_RShift, | ||||||
| 		LShift, | 	Op_LAnd, | ||||||
| 		RShift, | 	Op_LOr, | ||||||
| 		LAnd, | 	Op_LEqual, | ||||||
| 		LOr, | 	Op_LNot, | ||||||
| 		LEqual, | 	Op_Lesser, | ||||||
| 		LNot, | 	Op_Greater, | ||||||
| 		Lesser, | 	Op_LesserEqual, | ||||||
| 		Greater, | 	Op_GreaterEqual, | ||||||
| 		LesserEqual, | 	Op_Subscript, | ||||||
| 		GreaterEqual, | 	Op_Indirection, | ||||||
| 		Subscript, | 	Op_AddressOf, | ||||||
| 		Indirection, | 	Op_MemberOfPointer, | ||||||
| 		AddressOf, | 	Op_PtrToMemOfPtr, | ||||||
| 		MemberOfPointer, | 	Op_FunctionCall, | ||||||
| 		PtrToMemOfPtr, | 	Op_Comma, | ||||||
| 		FunctionCall, | 	Op_New, | ||||||
| 		Comma, | 	Op_NewArray, | ||||||
| 		New, | 	Op_Delete, | ||||||
| 		NewArray, | 	Op_DeleteArray, | ||||||
| 		Delete, |  | ||||||
| 		DeleteArray, |  | ||||||
| 	NumOps | 	NumOps | ||||||
| }; | }; | ||||||
|  | typedef enum Operator_Def Operator; | ||||||
|  |  | ||||||
| 	inline StrC to_str( Type op ) | inline StrC to_str( Operator op ) | ||||||
| { | { | ||||||
| 	local_persist StrC lookup[] { | 	local_persist StrC lookup[] { | ||||||
| 		{ sizeof( "INVALID" ),  "INVALID"  }, | 		{ sizeof( "INVALID" ),  "INVALID"  }, | ||||||
| @@ -112,7 +111,3 @@ namespace EOperator | |||||||
| 	}; | 	}; | ||||||
| 	return lookup[op]; | 	return lookup[op]; | ||||||
| } | } | ||||||
|  |  | ||||||
| }    // namespace EOperator |  | ||||||
|  |  | ||||||
| using OperatorT = EOperator::Type; |  | ||||||
|   | |||||||
| @@ -5,45 +5,44 @@ | |||||||
|  |  | ||||||
| // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | ||||||
|  |  | ||||||
| namespace ESpecifier | enum Specifier_Def : u32 | ||||||
| { | { | ||||||
| 	enum Type : u32 | 	Spec_Invalid, | ||||||
| 	{ | 	Spec_Consteval, | ||||||
| 		Invalid, | 	Spec_Constexpr, | ||||||
| 		Consteval, | 	Spec_Constinit, | ||||||
| 		Constexpr, | 	Spec_Explicit, | ||||||
| 		Constinit, | 	Spec_External_Linkage, | ||||||
| 		Explicit, | 	Spec_ForceInline, | ||||||
| 		External_Linkage, | 	Spec_Global, | ||||||
| 		ForceInline, | 	Spec_Inline, | ||||||
| 		Global, | 	Spec_Internal_Linkage, | ||||||
| 		Inline, | 	Spec_Local_Persist, | ||||||
| 		Internal_Linkage, | 	Spec_Mutable, | ||||||
| 		Local_Persist, | 	Spec_NeverInline, | ||||||
| 		Mutable, | 	Spec_Ptr, | ||||||
| 		NeverInline, | 	Spec_Ref, | ||||||
| 		Ptr, | 	Spec_Register, | ||||||
| 		Ref, | 	Spec_RValue, | ||||||
| 		Register, | 	Spec_Static, | ||||||
| 		RValue, | 	Spec_Thread_Local, | ||||||
| 		Static, | 	Spec_Virtual, | ||||||
| 		Thread_Local, | 	Spec_Const, | ||||||
| 		Virtual, | 	Spec_Final, | ||||||
| 		Const, | 	Spec_NoExceptions, | ||||||
| 		Final, | 	Spec_Override, | ||||||
| 		NoExceptions, | 	Spec_Pure, | ||||||
| 		Override, | 	Spec_Volatile, | ||||||
| 		Pure, | 	Spec_NumSpecifiers | ||||||
| 		Volatile, |  | ||||||
| 		NumSpecifiers |  | ||||||
| }; | }; | ||||||
|  | typedef enum Specifier_Def Specifier; | ||||||
|  |  | ||||||
| 	inline bool is_trailing( Type specifier ) | inline bool is_trailing( Specifier specifier ) | ||||||
| { | { | ||||||
| 		return specifier > Virtual; | 	return specifier > Spec_Virtual; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	inline StrC to_str( Type type ) | inline StrC to_str( Specifier type ) | ||||||
| { | { | ||||||
| 	local_persist StrC lookup[] { | 	local_persist StrC lookup[] { | ||||||
| 		{ sizeof( "INVALID" ),       "INVALID"       }, | 		{ sizeof( "INVALID" ),       "INVALID"       }, | ||||||
| @@ -76,23 +75,19 @@ namespace ESpecifier | |||||||
| 	return lookup[type]; | 	return lookup[type]; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	inline Type to_type( StrC str ) | inline Specifier to_specifier( StrC str ) | ||||||
| { | { | ||||||
| 		local_persist u32 keymap[NumSpecifiers]; | 	local_persist u32 keymap[Spec_NumSpecifiers]; | ||||||
| 		do_once_start for ( u32 index = 0; index < NumSpecifiers; index++ ) | 	do_once_start for ( u32 index = 0; index < Spec_NumSpecifiers; index++ ) | ||||||
| 	{ | 	{ | ||||||
| 			StrC enum_str = to_str( (Type)index ); | 		StrC enum_str = to_str( (Specifier)index ); | ||||||
| 		keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1 ); | 		keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1 ); | ||||||
| 	} | 	} | ||||||
| 	do_once_end u32 hash = crc32( str.Ptr, str.Len ); | 	do_once_end u32 hash = crc32( str.Ptr, str.Len ); | ||||||
| 		for ( u32 index = 0; index < NumSpecifiers; index++ ) | 	for ( u32 index = 0; index < Spec_NumSpecifiers; index++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( keymap[index] == hash ) | 		if ( keymap[index] == hash ) | ||||||
| 				return (Type)index; | 			return (Specifier)index; | ||||||
| 	} | 	} | ||||||
| 		return Invalid; | 	return Spec_Invalid; | ||||||
| } | } | ||||||
|  |  | ||||||
| }    // namespace ESpecifier |  | ||||||
|  |  | ||||||
| using SpecifierT = ESpecifier::Type; |  | ||||||
|   | |||||||
| @@ -5,115 +5,113 @@ | |||||||
|  |  | ||||||
| // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | // This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp) | ||||||
|  |  | ||||||
| namespace parser | GEN_NS_PARSER_BEGIN | ||||||
| { | #define GEN_DEFINE_ATTRIBUTE_TOKENS Entry( Tok_Attribute_API_Export, "GEN_API_Export_Code" ) Entry( Tok_Attribute_API_Import, "GEN_API_Import_Code" ) | ||||||
| 	namespace ETokType |  | ||||||
| 	{ |  | ||||||
| #define GEN_DEFINE_ATTRIBUTE_TOKENS Entry( Attribute_API_Export, "GEN_API_Export_Code" ) Entry( Attribute_API_Import, "GEN_API_Import_Code" ) |  | ||||||
|  |  | ||||||
| 		enum Type : u32 | enum TokType_Def : u32 | ||||||
| { | { | ||||||
| 			Invalid, | 	Tok_Invalid, | ||||||
| 			Access_Private, | 	Tok_Access_Private, | ||||||
| 			Access_Protected, | 	Tok_Access_Protected, | ||||||
| 			Access_Public, | 	Tok_Access_Public, | ||||||
| 			Access_MemberSymbol, | 	Tok_Access_MemberSymbol, | ||||||
| 			Access_StaticSymbol, | 	Tok_Access_StaticSymbol, | ||||||
| 			Ampersand, | 	Tok_Ampersand, | ||||||
| 			Ampersand_DBL, | 	Tok_Ampersand_DBL, | ||||||
| 			Assign_Classifer, | 	Tok_Assign_Classifer, | ||||||
| 			Attribute_Open, | 	Tok_Attribute_Open, | ||||||
| 			Attribute_Close, | 	Tok_Attribute_Close, | ||||||
| 			BraceCurly_Open, | 	Tok_BraceCurly_Open, | ||||||
| 			BraceCurly_Close, | 	Tok_BraceCurly_Close, | ||||||
| 			BraceSquare_Open, | 	Tok_BraceSquare_Open, | ||||||
| 			BraceSquare_Close, | 	Tok_BraceSquare_Close, | ||||||
| 			Capture_Start, | 	Tok_Capture_Start, | ||||||
| 			Capture_End, | 	Tok_Capture_End, | ||||||
| 			Comment, | 	Tok_Comment, | ||||||
| 			Comment_End, | 	Tok_Comment_End, | ||||||
| 			Comment_Start, | 	Tok_Comment_Start, | ||||||
| 			Char, | 	Tok_Char, | ||||||
| 			Comma, | 	Tok_Comma, | ||||||
| 			Decl_Class, | 	Tok_Decl_Class, | ||||||
| 			Decl_GNU_Attribute, | 	Tok_Decl_GNU_Attribute, | ||||||
| 			Decl_MSVC_Attribute, | 	Tok_Decl_MSVC_Attribute, | ||||||
| 			Decl_Enum, | 	Tok_Decl_Enum, | ||||||
| 			Decl_Extern_Linkage, | 	Tok_Decl_Extern_Linkage, | ||||||
| 			Decl_Friend, | 	Tok_Decl_Friend, | ||||||
| 			Decl_Module, | 	Tok_Decl_Module, | ||||||
| 			Decl_Namespace, | 	Tok_Decl_Namespace, | ||||||
| 			Decl_Operator, | 	Tok_Decl_Operator, | ||||||
| 			Decl_Struct, | 	Tok_Decl_Struct, | ||||||
| 			Decl_Template, | 	Tok_Decl_Template, | ||||||
| 			Decl_Typedef, | 	Tok_Decl_Typedef, | ||||||
| 			Decl_Using, | 	Tok_Decl_Using, | ||||||
| 			Decl_Union, | 	Tok_Decl_Union, | ||||||
| 			Identifier, | 	Tok_Identifier, | ||||||
| 			Module_Import, | 	Tok_Module_Import, | ||||||
| 			Module_Export, | 	Tok_Module_Export, | ||||||
| 			NewLine, | 	Tok_NewLine, | ||||||
| 			Number, | 	Tok_Number, | ||||||
| 			Operator, | 	Tok_Operator, | ||||||
| 			Preprocess_Hash, | 	Tok_Preprocess_Hash, | ||||||
| 			Preprocess_Define, | 	Tok_Preprocess_Define, | ||||||
| 			Preprocess_If, | 	Tok_Preprocess_If, | ||||||
| 			Preprocess_IfDef, | 	Tok_Preprocess_IfDef, | ||||||
| 			Preprocess_IfNotDef, | 	Tok_Preprocess_IfNotDef, | ||||||
| 			Preprocess_ElIf, | 	Tok_Preprocess_ElIf, | ||||||
| 			Preprocess_Else, | 	Tok_Preprocess_Else, | ||||||
| 			Preprocess_EndIf, | 	Tok_Preprocess_EndIf, | ||||||
| 			Preprocess_Include, | 	Tok_Preprocess_Include, | ||||||
| 			Preprocess_Pragma, | 	Tok_Preprocess_Pragma, | ||||||
| 			Preprocess_Content, | 	Tok_Preprocess_Content, | ||||||
| 			Preprocess_Macro, | 	Tok_Preprocess_Macro, | ||||||
| 			Preprocess_Unsupported, | 	Tok_Preprocess_Unsupported, | ||||||
| 			Spec_Alignas, | 	Tok_Spec_Alignas, | ||||||
| 			Spec_Const, | 	Tok_Spec_Const, | ||||||
| 			Spec_Consteval, | 	Tok_Spec_Consteval, | ||||||
| 			Spec_Constexpr, | 	Tok_Spec_Constexpr, | ||||||
| 			Spec_Constinit, | 	Tok_Spec_Constinit, | ||||||
| 			Spec_Explicit, | 	Tok_Spec_Explicit, | ||||||
| 			Spec_Extern, | 	Tok_Spec_Extern, | ||||||
| 			Spec_Final, | 	Tok_Spec_Final, | ||||||
| 			Spec_ForceInline, | 	Tok_Spec_ForceInline, | ||||||
| 			Spec_Global, | 	Tok_Spec_Global, | ||||||
| 			Spec_Inline, | 	Tok_Spec_Inline, | ||||||
| 			Spec_Internal_Linkage, | 	Tok_Spec_Internal_Linkage, | ||||||
| 			Spec_LocalPersist, | 	Tok_Spec_LocalPersist, | ||||||
| 			Spec_Mutable, | 	Tok_Spec_Mutable, | ||||||
| 			Spec_NeverInline, | 	Tok_Spec_NeverInline, | ||||||
| 			Spec_Override, | 	Tok_Spec_Override, | ||||||
| 			Spec_Static, | 	Tok_Spec_Static, | ||||||
| 			Spec_ThreadLocal, | 	Tok_Spec_ThreadLocal, | ||||||
| 			Spec_Volatile, | 	Tok_Spec_Volatile, | ||||||
| 			Spec_Virtual, | 	Tok_Spec_Virtual, | ||||||
| 			Star, | 	Tok_Star, | ||||||
| 			Statement_End, | 	Tok_Statement_End, | ||||||
| 			StaticAssert, | 	Tok_StaticAssert, | ||||||
| 			String, | 	Tok_String, | ||||||
| 			Type_Typename, | 	Tok_Type_Typename, | ||||||
| 			Type_Unsigned, | 	Tok_Type_Unsigned, | ||||||
| 			Type_Signed, | 	Tok_Type_Signed, | ||||||
| 			Type_Short, | 	Tok_Type_Short, | ||||||
| 			Type_Long, | 	Tok_Type_Long, | ||||||
| 			Type_bool, | 	Tok_Type_bool, | ||||||
| 			Type_char, | 	Tok_Type_char, | ||||||
| 			Type_int, | 	Tok_Type_int, | ||||||
| 			Type_double, | 	Tok_Type_double, | ||||||
| 			Type_MS_int8, | 	Tok_Type_MS_int8, | ||||||
| 			Type_MS_int16, | 	Tok_Type_MS_int16, | ||||||
| 			Type_MS_int32, | 	Tok_Type_MS_int32, | ||||||
| 			Type_MS_int64, | 	Tok_Type_MS_int64, | ||||||
| 			Type_MS_W64, | 	Tok_Type_MS_W64, | ||||||
| 			Varadic_Argument, | 	Tok_Varadic_Argument, | ||||||
| 			__Attributes_Start, | 	Tok___Attributes_Start, | ||||||
| 			Attribute_API_Export, | 	Tok_Attribute_API_Export, | ||||||
| 			Attribute_API_Import, | 	Tok_Attribute_API_Import, | ||||||
| 			NumTokens | 	Tok_NumTokens | ||||||
| }; | }; | ||||||
|  | typedef enum TokType_Def TokType; | ||||||
|  |  | ||||||
| 		inline StrC to_str( Type type ) | inline StrC to_str( TokType type ) | ||||||
| { | { | ||||||
| 	local_persist StrC lookup[] { | 	local_persist StrC lookup[] { | ||||||
| 		{ sizeof( "__invalid__" ),         "__invalid__"         }, | 		{ sizeof( "__invalid__" ),         "__invalid__"         }, | ||||||
| @@ -217,25 +215,21 @@ namespace parser | |||||||
| 	return lookup[type]; | 	return lookup[type]; | ||||||
| } | } | ||||||
|  |  | ||||||
| 		inline Type to_type( StrC str ) | inline TokType to_toktype( StrC str ) | ||||||
| { | { | ||||||
| 			local_persist u32 keymap[NumTokens]; | 	local_persist u32 keymap[Tok_NumTokens]; | ||||||
| 			do_once_start for ( u32 index = 0; index < NumTokens; index++ ) | 	do_once_start for ( u32 index = 0; index < Tok_NumTokens; index++ ) | ||||||
| 	{ | 	{ | ||||||
| 				StrC enum_str = to_str( (Type)index ); | 		StrC enum_str = to_str( (TokType)index ); | ||||||
| 		keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1 ); | 		keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1 ); | ||||||
| 	} | 	} | ||||||
| 	do_once_end u32 hash = crc32( str.Ptr, str.Len ); | 	do_once_end u32 hash = crc32( str.Ptr, str.Len ); | ||||||
| 			for ( u32 index = 0; index < NumTokens; index++ ) | 	for ( u32 index = 0; index < Tok_NumTokens; index++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( keymap[index] == hash ) | 		if ( keymap[index] == hash ) | ||||||
| 					return (Type)index; | 			return (TokType)index; | ||||||
| 	} | 	} | ||||||
| 			return Invalid; | 	return Tok_Invalid; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	}    // namespace ETokType | GEN_NS_PARSER_END | ||||||
|  |  | ||||||
| 	using TokType = ETokType::Type; |  | ||||||
|  |  | ||||||
| }    // namespace parser |  | ||||||
|   | |||||||
| @@ -97,45 +97,46 @@ extern CodeSpecifiers spec_thread_local; | |||||||
| extern CodeSpecifiers spec_virtual; | extern CodeSpecifiers spec_virtual; | ||||||
| extern CodeSpecifiers spec_volatile; | extern CodeSpecifiers spec_volatile; | ||||||
|  |  | ||||||
| extern CodeType t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance) | extern CodeTypename t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance) | ||||||
| extern CodeType t_auto; | extern CodeTypename t_auto; | ||||||
| extern CodeType t_void; | extern CodeTypename t_void; | ||||||
| extern CodeType t_int; | extern CodeTypename t_int; | ||||||
| extern CodeType t_bool; | extern CodeTypename t_bool; | ||||||
| extern CodeType t_char; | extern CodeTypename t_char; | ||||||
| extern CodeType t_wchar_t; | extern CodeTypename t_wchar_t; | ||||||
| extern CodeType t_class; | extern CodeTypename t_class; | ||||||
| extern CodeType t_typename; | extern CodeTypename t_typename; | ||||||
|  |  | ||||||
| #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| 	// Predefined typename codes. Are set to readonly and are setup during gen::init() | 	// Predefined typename codes. Are set to readonly and are setup during gen::init() | ||||||
|  |  | ||||||
| 	extern CodeType t_b32; | 	extern CodeTypename t_b32; | ||||||
|  |  | ||||||
| 	extern CodeType t_s8; | 	extern CodeTypename t_s8; | ||||||
| 	extern CodeType t_s16; | 	extern CodeTypename t_s16; | ||||||
| 	extern CodeType t_s32; | 	extern CodeTypename t_s32; | ||||||
| 	extern CodeType t_s64; | 	extern CodeTypename t_s64; | ||||||
|  |  | ||||||
| 	extern CodeType t_u8; | 	extern CodeTypename t_u8; | ||||||
| 	extern CodeType t_u16; | 	extern CodeTypename t_u16; | ||||||
| 	extern CodeType t_u32; | 	extern CodeTypename t_u32; | ||||||
| 	extern CodeType t_u64; | 	extern CodeTypename t_u64; | ||||||
|  |  | ||||||
| 	extern CodeType t_ssize; | 	extern CodeTypename t_ssize; | ||||||
| 	extern CodeType t_usize; | 	extern CodeTypename t_usize; | ||||||
|  |  | ||||||
| 	extern CodeType t_f32; | 	extern CodeTypename t_f32; | ||||||
| 	extern CodeType t_f64; | 	extern CodeTypename t_f64; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma endregion Constants | #pragma endregion Constants | ||||||
|  |  | ||||||
| #pragma region Macros | #pragma region Macros | ||||||
|  |  | ||||||
|  | #ifndef token_fmt | ||||||
| #	define gen_main main | #	define gen_main main | ||||||
|  |  | ||||||
| #	define __ NoCode | #	define __ NullCode | ||||||
|  |  | ||||||
| 	//	Convienence for defining any name used with the gen api. | 	//	Convienence for defining any name used with the gen api. | ||||||
| 	//  Lets you provide the length and string literal to the functions without the need for the DSL. | 	//  Lets you provide the length and string literal to the functions without the need for the DSL. | ||||||
| @@ -151,22 +152,23 @@ extern CodeType t_typename; | |||||||
|  |  | ||||||
| 	// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string. | 	// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string. | ||||||
| #	define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) | #	define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Macros | #pragma endregion Macros | ||||||
|  |  | ||||||
| // Used by the lexer to persistently treat all these identifiers as preprocessor defines. | // Used by the lexer to persistently treat all these identifiers as preprocessor defines. | ||||||
| // Populate with strings via gen::get_cached_string. | // Populate with strings via gen::get_cached_string. | ||||||
| // Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments. | // Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments. | ||||||
| extern Array< StringCached > PreprocessorDefines; | extern Array(StringCached) PreprocessorDefines; | ||||||
|  |  | ||||||
| #ifdef GEN_EXPOSE_BACKEND | #ifdef GEN_EXPOSE_BACKEND | ||||||
|  |  | ||||||
| 	// Global allocator used for data with process lifetime. | 	// Global allocator used for data with process lifetime. | ||||||
| 	extern AllocatorInfo  GlobalAllocator; | 	extern AllocatorInfo  GlobalAllocator; | ||||||
| 	extern Array< Arena > Global_AllocatorBuckets; | 	extern Array(Arena) Global_AllocatorBuckets; | ||||||
|  |  | ||||||
| 	extern Array< Pool >  CodePools; | 	extern Array(Pool)  CodePools; | ||||||
| 	extern Array< Arena > StringArenas; | 	extern Array(Arena) StringArenas; | ||||||
|  |  | ||||||
| 	extern StringTable StringCache; | 	extern StringTable StringCache; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,12 @@ | |||||||
|  |  | ||||||
| 	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                 ! | ||||||
|  | 	! 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 | ||||||
| @@ -17,15 +23,3 @@ | |||||||
| #ifndef GEN_ROLL_OWN_DEPENDENCIES | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
| #	include "gen.dep.hpp" | #	include "gen.dep.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef GEN_NS_BEGIN |  | ||||||
| #	ifdef GEN_DONT_USE_NAMESPACE |  | ||||||
| #		define GEN_NS |  | ||||||
| #		define GEN_NS_BEGIN |  | ||||||
| #		define GEN_NS_END |  | ||||||
| #	else |  | ||||||
| #		define GEN_NS       gen:: |  | ||||||
| #		define GEN_NS_BEGIN namespace gen { |  | ||||||
| #		define GEN_NS_END   } |  | ||||||
| #	endif |  | ||||||
| #endif |  | ||||||
|   | |||||||
| @@ -3,102 +3,174 @@ | |||||||
| #include "interface.hpp" | #include "interface.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #pragma region Code | ||||||
| inline | inline | ||||||
| void AST::append( AST* other ) | void append( Code self, Code other ) | ||||||
| { | { | ||||||
|  | 	GEN_ASSERT(self.ast  != nullptr); | ||||||
|  | 	GEN_ASSERT(other.ast != nullptr); | ||||||
|  |  | ||||||
| 	if ( other->Parent ) | 	if ( other->Parent ) | ||||||
| 		other = other->duplicate(); | 		other = duplicate(other); | ||||||
|  |  | ||||||
| 	other->Parent = this; | 	other->Parent = self; | ||||||
|  |  | ||||||
| 	if ( Front == nullptr ) | 	if ( self->Front == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		Front = other; | 		self->Front = other; | ||||||
| 		Back  = other; | 		self->Back  = other; | ||||||
|  |  | ||||||
| 		NumEntries++; | 		self->NumEntries++; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	AST* | 	Code | ||||||
| 		Current       = Back; | 	Current       = self->Back; | ||||||
| 	Current->Next = other; | 	Current->Next = other; | ||||||
| 	other->Prev   = Current; | 	other->Prev   = Current; | ||||||
| 	Back          = other; | 	self->Back    = other; | ||||||
| 	NumEntries++; | 	self->NumEntries++; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| Code& AST::entry( u32 idx ) | bool is_body(Code self) | ||||||
| { | { | ||||||
| 	AST** current = & Front; | 	GEN_ASSERT(self != nullptr); | ||||||
|  | 	switch (self->Type) | ||||||
|  | 	{ | ||||||
|  | 		case CT_Enum_Body: | ||||||
|  | 		case CT_Class_Body: | ||||||
|  | 		case CT_Union_Body: | ||||||
|  | 		case CT_Export_Body: | ||||||
|  | 		case CT_Global_Body: | ||||||
|  | 		case CT_Struct_Body: | ||||||
|  | 		case CT_Function_Body: | ||||||
|  | 		case CT_Namespace_Body: | ||||||
|  | 		case CT_Extern_Linkage_Body: | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | Code* entry( Code self, u32 idx ) | ||||||
|  | { | ||||||
|  | 	GEN_ASSERT(self.ast != nullptr); | ||||||
|  | 	Code* current = & self->Front; | ||||||
| 	while ( idx >= 0 && current != nullptr ) | 	while ( idx >= 0 && current != nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( idx == 0 ) | 		if ( idx == 0 ) | ||||||
| 			return * rcast( Code*, current); | 			return rcast( Code*, current); | ||||||
|  |  | ||||||
| 		current = & ( * current )->Next; | 		current = & ( * current )->Next; | ||||||
| 		idx--; | 		idx--; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return * rcast( Code*, current); | 	return rcast( Code*, current); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool AST::has_entries() | bool is_valid(Code self) | ||||||
| { | { | ||||||
| 	return NumEntries > 0; | 	return self.ast != nullptr && self.ast->Type != CT_Invalid; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| char const* AST::type_str() | bool has_entries(AST* self) | ||||||
| { | { | ||||||
| 	return ECode::to_str( Type ); | 	GEN_ASSERT(self != nullptr); | ||||||
|  | 	return self->NumEntries > 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| AST::operator Code() | void set_global(Code self) | ||||||
| { | { | ||||||
| 	return { this }; | 	if ( self.ast == nullptr ) | ||||||
|  | 	{ | ||||||
|  | 		log_failure("Code::set_global: Cannot set code as global, AST is null!"); | ||||||
|  | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	self->Parent.ast = Code_Global.ast; | ||||||
|  | } | ||||||
| inline | inline | ||||||
| Code& Code::operator ++() | Code& Code::operator ++() | ||||||
| { | { | ||||||
| 	if ( ast ) | 	if ( ast ) | ||||||
| 		ast = ast->Next; | 		ast = ast->Next.ast; | ||||||
|  |  | ||||||
| 	return * this; | 	return * this; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| void CodeClass::add_interface( CodeType type ) | char const* type_str(Code self) | ||||||
| { | { | ||||||
| 	CodeType possible_slot = ast->ParentType; | 	GEN_ASSERT(self != nullptr); | ||||||
|  | 	return to_str( self->Type ); | ||||||
|  | } | ||||||
|  | #pragma endregion Code | ||||||
|  |  | ||||||
|  | #pragma region CodeBody | ||||||
|  | inline | ||||||
|  | void append( CodeBody self, Code other ) | ||||||
|  | { | ||||||
|  | 	GEN_ASSERT(other.ast != nullptr); | ||||||
|  |  | ||||||
|  | 	if (is_body(other)) { | ||||||
|  | 		append( self, cast(CodeBody, other) ); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	append( cast(Code, self), other ); | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | void append( CodeBody self, CodeBody body ) | ||||||
|  | { | ||||||
|  | 	GEN_ASSERT(self.ast != nullptr); | ||||||
|  |  | ||||||
|  | 	for ( Code entry : body ) { | ||||||
|  | 		append( self, entry ); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | Code begin( CodeBody body) { | ||||||
|  | 	if ( body.ast ) | ||||||
|  | 		return { rcast( AST*, body.ast)->Front }; | ||||||
|  | 	return { nullptr }; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | Code end(CodeBody body ){ | ||||||
|  | 	return { rcast(AST*, body.ast)->Back->Next }; | ||||||
|  | } | ||||||
|  | #pragma endregion CodeBody | ||||||
|  |  | ||||||
|  | #pragma region CodeClass | ||||||
|  | inline | ||||||
|  | void add_interface( CodeClass self, CodeTypename type ) | ||||||
|  | { | ||||||
|  | 	GEN_ASSERT(self.ast !=nullptr); | ||||||
|  | 	CodeTypename possible_slot = self->ParentType; | ||||||
| 	if ( possible_slot.ast ) | 	if ( possible_slot.ast ) | ||||||
| 	{ | 	{ | ||||||
| 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | ||||||
| 		ast->ParentAccess = AccessSpec::Public; | 		self->ParentAccess = AccessSpec_Public; | ||||||
| 		// If your planning on adding a proper parent, | 		// If your planning on adding a proper parent, | ||||||
| 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	while ( possible_slot.ast != nullptr ) | 	while ( possible_slot.ast != nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		possible_slot.ast = (AST_Type*) possible_slot->Next.ast; | 		possible_slot.ast = (AST_Typename*) possible_slot->Next.ast; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	possible_slot.ast = type.ast; | 	possible_slot.ast = type.ast; | ||||||
| } | } | ||||||
|  | #pragma endregion CodeClass | ||||||
|  |  | ||||||
|  | #pragma region CodeParam | ||||||
| inline | inline | ||||||
| void CodeParam::append( CodeParam other ) | void append( CodeParam appendee, CodeParam other ) | ||||||
| { | { | ||||||
| 	AST* self  = (AST*) ast; | 	GEN_ASSERT(appendee.ast != nullptr); | ||||||
| 	AST* entry = (AST*) other.ast; | 	Code self  = cast(Code, appendee); | ||||||
|  | 	Code entry = cast(Code, other); | ||||||
|  |  | ||||||
| 	if ( entry->Parent ) | 	if ( entry->Parent ) | ||||||
| 		entry = entry->duplicate(); | 		entry = GEN_NS duplicate( entry ); | ||||||
|  |  | ||||||
| 	entry->Parent = self; | 	entry->Parent = self; | ||||||
|  |  | ||||||
| @@ -114,76 +186,177 @@ void CodeParam::append( CodeParam other ) | |||||||
| 	self->Last       = entry; | 	self->Last       = entry; | ||||||
| 	self->NumEntries++; | 	self->NumEntries++; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| CodeParam CodeParam::get( s32 idx ) | CodeParam get(CodeParam self, s32 idx ) | ||||||
| { | { | ||||||
| 	CodeParam param = *this; | 	GEN_ASSERT(self.ast != nullptr); | ||||||
|  | 	CodeParam param = * self; | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! ++ param ) | 		if ( ! ++ param ) | ||||||
| 			return { nullptr }; | 			return { nullptr }; | ||||||
|  |  | ||||||
| 		param = { (AST_Param*) param.raw()->Next }; | 		param = cast(Code, param)->Next; | ||||||
| 	} | 	} | ||||||
| 	while ( --idx ); | 	while ( --idx ); | ||||||
|  |  | ||||||
| 	return param; | 	return param; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool CodeParam::has_entries() | bool has_entries(CodeParam self) | ||||||
| { | { | ||||||
| 	return ast->NumEntries > 0; | 	GEN_ASSERT(self.ast != nullptr); | ||||||
|  | 	return self->NumEntries > 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| CodeParam& CodeParam::operator ++() | CodeParam& CodeParam::operator ++() | ||||||
| { | { | ||||||
| 	ast = ast->Next.ast; | 	ast = ast->Next.ast; | ||||||
| 	return * this; | 	return * this; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| void CodeStruct::add_interface( CodeType type ) | CodeParam begin(CodeParam params) | ||||||
| { | { | ||||||
| 	CodeType possible_slot = ast->ParentType; | 	if ( params.ast ) | ||||||
|  | 		return { params.ast }; | ||||||
|  |  | ||||||
|  | 	return { nullptr }; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | CodeParam end(CodeParam params) | ||||||
|  | { | ||||||
|  | 	// return { (AST_Param*) rcast( AST*, ast)->Last }; | ||||||
|  | 	return { nullptr }; | ||||||
|  | } | ||||||
|  | #pragma endregion CodeParam | ||||||
|  |  | ||||||
|  | #pragma region CodeSpecifiers | ||||||
|  | inline | ||||||
|  | bool append(CodeSpecifiers self, Specifier spec ) | ||||||
|  | { | ||||||
|  | 	if ( self.ast == nullptr ) | ||||||
|  | 	{ | ||||||
|  | 		log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	if ( self->NumEntries == AST_ArrSpecs_Cap ) | ||||||
|  | 	{ | ||||||
|  | 		log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST_ArrSpecs_Cap ); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	self->ArrSpecs[ self->NumEntries ] = spec; | ||||||
|  | 	self->NumEntries++; | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | s32 has(CodeSpecifiers self, Specifier spec) | ||||||
|  | { | ||||||
|  | 	GEN_ASSERT(self.ast != nullptr); | ||||||
|  | 	for ( s32 idx = 0; idx < self->NumEntries; idx++ ) { | ||||||
|  | 		if ( self->ArrSpecs[ idx ] == spec ) | ||||||
|  | 			return idx; | ||||||
|  | 	} | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | s32 remove( CodeSpecifiers self, Specifier to_remove ) | ||||||
|  | { | ||||||
|  | 	AST_Specifiers* ast = self.ast; | ||||||
|  | 	if ( ast == nullptr ) | ||||||
|  | 	{ | ||||||
|  | 		log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	if ( self->NumEntries == AST_ArrSpecs_Cap ) | ||||||
|  | 	{ | ||||||
|  | 		log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST_ArrSpecs_Cap ); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s32 result = -1; | ||||||
|  |  | ||||||
|  | 	s32 curr = 0; | ||||||
|  | 	s32 next = 0; | ||||||
|  | 	for(; next < self->NumEntries; ++ curr, ++ next) | ||||||
|  | 	{ | ||||||
|  | 		Specifier spec = self->ArrSpecs[next]; | ||||||
|  | 		if (spec == to_remove) | ||||||
|  | 		{ | ||||||
|  | 			result = next; | ||||||
|  |  | ||||||
|  | 			next ++; | ||||||
|  | 			if (next >= self->NumEntries) | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 			spec = self->ArrSpecs[next]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		self->ArrSpecs[ curr ] = spec; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (result > -1) { | ||||||
|  | 		self->NumEntries --; | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | Specifier* begin(CodeSpecifiers self) | ||||||
|  | { | ||||||
|  | 	if ( self.ast ) | ||||||
|  | 		return & self->ArrSpecs[0]; | ||||||
|  |  | ||||||
|  | 	return nullptr; | ||||||
|  | } | ||||||
|  | inline | ||||||
|  | Specifier* end(CodeSpecifiers self) | ||||||
|  | { | ||||||
|  | 	return self->ArrSpecs + self->NumEntries; | ||||||
|  | } | ||||||
|  | #pragma endregion CodeSpecifiers | ||||||
|  |  | ||||||
|  | #pragma region CodeStruct | ||||||
|  | inline | ||||||
|  | void add_interface(CodeStruct self, CodeTypename type ) | ||||||
|  | { | ||||||
|  | 	CodeTypename possible_slot = self->ParentType; | ||||||
| 	if ( possible_slot.ast ) | 	if ( possible_slot.ast ) | ||||||
| 	{ | 	{ | ||||||
| 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | ||||||
| 		ast->ParentAccess = AccessSpec::Public; | 		self->ParentAccess = AccessSpec_Public; | ||||||
| 		// If your planning on adding a proper parent, | 		// If your planning on adding a proper parent, | ||||||
| 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	while ( possible_slot.ast != nullptr ) | 	while ( possible_slot.ast != nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		possible_slot.ast = (AST_Type*) possible_slot->Next.ast; | 		possible_slot.ast = (AST_Typename*) possible_slot->Next.ast; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	possible_slot.ast = type.ast; | 	possible_slot.ast = type.ast; | ||||||
| } | } | ||||||
|  | #pragma endregion Code | ||||||
|  |  | ||||||
|  | #pragma region Interface | ||||||
| inline | inline | ||||||
| CodeBody def_body( CodeT type ) | CodeBody def_body( CodeType type ) | ||||||
| { | { | ||||||
| 	switch ( type ) | 	switch ( type ) | ||||||
| 	{ | 	{ | ||||||
| 		using namespace ECode; | 		case CT_Class_Body: | ||||||
| 		case Class_Body: | 		case CT_Enum_Body: | ||||||
| 		case Enum_Body: | 		case CT_Export_Body: | ||||||
| 		case Export_Body: | 		case CT_Extern_Linkage: | ||||||
| 		case Extern_Linkage: | 		case CT_Function_Body: | ||||||
| 		case Function_Body: | 		case CT_Global_Body: | ||||||
| 		case Global_Body: | 		case CT_Namespace_Body: | ||||||
| 		case Namespace_Body: | 		case CT_Struct_Body: | ||||||
| 		case Struct_Body: | 		case CT_Union_Body: | ||||||
| 		case Union_Body: |  | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			log_failure( "def_body: Invalid type %s", (char const*)ECode::to_str(type) ); | 			log_failure( "def_body: Invalid type %s", (char const*)to_str(type) ); | ||||||
| 			return (CodeBody)Code::Invalid; | 			return (CodeBody)Code_Invalid; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| @@ -206,3 +379,4 @@ StrC token_fmt_impl( ssize num, ... ) | |||||||
|  |  | ||||||
| 	return { result, buf }; | 	return { result, buf }; | ||||||
| } | } | ||||||
|  | #pragma endregion Interface | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ internal void deinit(); | |||||||
| internal | internal | ||||||
| void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	Arena* last = & Global_AllocatorBuckets.back(); | 	Arena* last = array_back(Global_AllocatorBuckets); | ||||||
|  |  | ||||||
| 	switch ( type ) | 	switch ( type ) | ||||||
| 	{ | 	{ | ||||||
| @@ -19,18 +19,18 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| 		{ | 		{ | ||||||
| 			if ( ( last->TotalUsed + size ) > last->TotalSize ) | 			if ( ( last->TotalUsed + size ) > last->TotalSize ) | ||||||
| 			{ | 			{ | ||||||
| 				Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); | 				Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize ); | ||||||
|  |  | ||||||
| 				if ( bucket.PhysicalStart == nullptr ) | 				if ( bucket.PhysicalStart == nullptr ) | ||||||
| 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				if ( ! Global_AllocatorBuckets.append( bucket ) ) | 				if ( ! array_append( Global_AllocatorBuckets, bucket ) ) | ||||||
| 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				last = & Global_AllocatorBuckets.back(); | 				last = array_back(Global_AllocatorBuckets); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return alloc_align( * last, size, alignment ); | 			return alloc_align( arena_allocator_info(last), size, alignment ); | ||||||
| 		} | 		} | ||||||
| 		case EAllocation_FREE: | 		case EAllocation_FREE: | ||||||
| 		{ | 		{ | ||||||
| @@ -46,15 +46,15 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| 		{ | 		{ | ||||||
| 			if ( last->TotalUsed + size > last->TotalSize ) | 			if ( last->TotalUsed + size > last->TotalSize ) | ||||||
| 			{ | 			{ | ||||||
| 				Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); | 				Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize ); | ||||||
|  |  | ||||||
| 				if ( bucket.PhysicalStart == nullptr ) | 				if ( bucket.PhysicalStart == nullptr ) | ||||||
| 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				if ( ! Global_AllocatorBuckets.append( bucket ) ) | 				if ( ! array_append( Global_AllocatorBuckets, bucket ) ) | ||||||
| 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				last = & Global_AllocatorBuckets.back(); | 				last = array_back(Global_AllocatorBuckets); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			void* result = alloc_align( last->Backing, size, alignment ); | 			void* result = alloc_align( last->Backing, size, alignment ); | ||||||
| @@ -74,78 +74,78 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| internal | internal | ||||||
| void define_constants() | void define_constants() | ||||||
| { | { | ||||||
| 	Code::Global          = make_code(); | 	Code_Global          = make_code(); | ||||||
| 	Code::Global->Name    = get_cached_string( txt("Global Code") ); | 	Code_Global->Name    = get_cached_string( txt("Global Code") ); | ||||||
| 	Code::Global->Content = Code::Global->Name; | 	Code_Global->Content = Code_Global->Name; | ||||||
|  |  | ||||||
| 	Code::Invalid = make_code(); | 	Code_Invalid = make_code(); | ||||||
| 	Code::Invalid.set_global(); | 	set_global(Code_Invalid); | ||||||
|  |  | ||||||
| 	t_empty          = (CodeType) make_code(); | 	t_empty       = (CodeTypename) make_code(); | ||||||
| 	t_empty->Type    = ECode::Typename; | 	t_empty->Type = CT_Typename; | ||||||
| 	t_empty->Name = get_cached_string( txt("") ); | 	t_empty->Name = get_cached_string( txt("") ); | ||||||
| 	t_empty.set_global(); | 	set_global(t_empty); | ||||||
|  |  | ||||||
| 	access_private       = make_code(); | 	access_private       = make_code(); | ||||||
| 	access_private->Type = ECode::Access_Private; | 	access_private->Type = CT_Access_Private; | ||||||
| 	access_private->Name = get_cached_string( txt("private:\n") ); | 	access_private->Name = get_cached_string( txt("private:\n") ); | ||||||
| 	access_private.set_global(); | 	set_global(access_private); | ||||||
|  |  | ||||||
| 	access_protected       = make_code(); | 	access_protected       = make_code(); | ||||||
| 	access_protected->Type = ECode::Access_Protected; | 	access_protected->Type = CT_Access_Protected; | ||||||
| 	access_protected->Name = get_cached_string( txt("protected:\n") ); | 	access_protected->Name = get_cached_string( txt("protected:\n") ); | ||||||
| 	access_protected.set_global(); | 	set_global(access_protected); | ||||||
|  |  | ||||||
| 	access_public       = make_code(); | 	access_public       = make_code(); | ||||||
| 	access_public->Type = ECode::Access_Public; | 	access_public->Type = CT_Access_Public; | ||||||
| 	access_public->Name = get_cached_string( txt("public:\n") ); | 	access_public->Name = get_cached_string( txt("public:\n") ); | ||||||
| 	access_public.set_global(); | 	set_global(access_public); | ||||||
|  |  | ||||||
| 	attrib_api_export = def_attributes( code(GEN_API_Export_Code)); | 	attrib_api_export = def_attributes( code(GEN_API_Export_Code)); | ||||||
| 	attrib_api_export.set_global(); | 	set_global(attrib_api_export); | ||||||
|  |  | ||||||
| 	attrib_api_import = def_attributes( code(GEN_API_Import_Code)); | 	attrib_api_import = def_attributes( code(GEN_API_Import_Code)); | ||||||
| 	attrib_api_import.set_global(); | 	set_global(attrib_api_import); | ||||||
|  |  | ||||||
| 	module_global_fragment          = make_code(); | 	module_global_fragment          = make_code(); | ||||||
| 	module_global_fragment->Type    = ECode::Untyped; | 	module_global_fragment->Type    = CT_Untyped; | ||||||
| 	module_global_fragment->Name    = get_cached_string( txt("module;") ); | 	module_global_fragment->Name    = get_cached_string( txt("module;") ); | ||||||
| 	module_global_fragment->Content = module_global_fragment->Name; | 	module_global_fragment->Content = module_global_fragment->Name; | ||||||
| 	module_global_fragment.set_global(); | 	set_global(module_global_fragment); | ||||||
|  |  | ||||||
| 	module_private_fragment          = make_code(); | 	module_private_fragment          = make_code(); | ||||||
| 	module_private_fragment->Type    = ECode::Untyped; | 	module_private_fragment->Type    = CT_Untyped; | ||||||
| 	module_private_fragment->Name    = get_cached_string( txt("module : private;") ); | 	module_private_fragment->Name    = get_cached_string( txt("module : private;") ); | ||||||
| 	module_private_fragment->Content = module_private_fragment->Name; | 	module_private_fragment->Content = module_private_fragment->Name; | ||||||
| 	module_private_fragment.set_global(); | 	set_global(module_private_fragment); | ||||||
|  |  | ||||||
| 	fmt_newline = make_code(); | 	fmt_newline = make_code(); | ||||||
| 	fmt_newline->Type = ECode::NewLine; | 	fmt_newline->Type = CT_NewLine; | ||||||
| 	fmt_newline.set_global(); | 	set_global(fmt_newline); | ||||||
| 	 | 	 | ||||||
| 	pragma_once          = (CodePragma) make_code(); | 	pragma_once          = (CodePragma) make_code(); | ||||||
| 	pragma_once->Type    = ECode::Preprocess_Pragma; | 	pragma_once->Type    = CT_Preprocess_Pragma; | ||||||
| 	pragma_once->Name    = get_cached_string( txt("once") ); | 	pragma_once->Name    = get_cached_string( txt("once") ); | ||||||
| 	pragma_once->Content = pragma_once->Name; | 	pragma_once->Content = pragma_once->Name; | ||||||
| 	pragma_once.set_global(); | 	set_global(pragma_once); | ||||||
|  |  | ||||||
| 	param_varadic            = (CodeType) make_code(); | 	param_varadic            = (CodeTypename) make_code(); | ||||||
| 	param_varadic->Type      = ECode::Parameters; | 	param_varadic->Type      = CT_Parameters; | ||||||
| 	param_varadic->Name      = get_cached_string( txt("...") ); | 	param_varadic->Name      = get_cached_string( txt("...") ); | ||||||
| 	param_varadic->ValueType = t_empty; | 	param_varadic->ValueType = t_empty; | ||||||
| 	param_varadic.set_global(); | 	set_global(param_varadic); | ||||||
|  |  | ||||||
| 	preprocess_else = (CodePreprocessCond) make_code(); | 	preprocess_else = (CodePreprocessCond) make_code(); | ||||||
| 	preprocess_else->Type = ECode::Preprocess_Else; | 	preprocess_else->Type = CT_Preprocess_Else; | ||||||
| 	preprocess_else.set_global(); | 	set_global(preprocess_else); | ||||||
|  |  | ||||||
| 	preprocess_endif = (CodePreprocessCond) make_code(); | 	preprocess_endif = (CodePreprocessCond) make_code(); | ||||||
| 	preprocess_endif->Type = ECode::Preprocess_EndIf; | 	preprocess_endif->Type = CT_Preprocess_EndIf; | ||||||
| 	preprocess_endif.set_global(); | 	set_global(preprocess_endif); | ||||||
|  |  | ||||||
| #	define def_constant_code_type( Type_ )   \ | #	define def_constant_code_type( Type_ )   \ | ||||||
| 		t_##Type_ = def_type( name(Type_) ); \ | 		t_##Type_ = def_type( name(Type_) ); \ | ||||||
| 		t_##Type_.set_global(); | 		set_global(t_##Type_); | ||||||
|  |  | ||||||
| 	def_constant_code_type( auto ); | 	def_constant_code_type( auto ); | ||||||
| 	def_constant_code_type( void ); | 	def_constant_code_type( void ); | ||||||
| @@ -180,7 +180,7 @@ void define_constants() | |||||||
|  |  | ||||||
| #	define def_constant_spec( Type_, ... )                                  \ | #	define def_constant_spec( Type_, ... )                                  \ | ||||||
| 		spec_##Type_ = def_specifiers( num_args(__VA_ARGS__), __VA_ARGS__); \ | 		spec_##Type_ = def_specifiers( num_args(__VA_ARGS__), __VA_ARGS__); \ | ||||||
| 		spec_##Type_.set_global(); | 		set_global(spec_##Type_); | ||||||
|  |  | ||||||
| #	pragma push_macro("forceinline") | #	pragma push_macro("forceinline") | ||||||
| #	pragma push_macro("global") | #	pragma push_macro("global") | ||||||
| @@ -192,33 +192,33 @@ void define_constants() | |||||||
| #	undef internal | #	undef internal | ||||||
| #	undef local_persist | #	undef local_persist | ||||||
| #	undef neverinline | #	undef neverinline | ||||||
| 	def_constant_spec( const,            ESpecifier::Const ); | 	def_constant_spec( const,            Spec_Const ); | ||||||
| 	def_constant_spec( consteval,        ESpecifier::Consteval ); | 	def_constant_spec( consteval,        Spec_Consteval ); | ||||||
| 	def_constant_spec( constexpr,        ESpecifier::Constexpr ); | 	def_constant_spec( constexpr,        Spec_Constexpr ); | ||||||
| 	def_constant_spec( constinit,        ESpecifier::Constinit ); | 	def_constant_spec( constinit,        Spec_Constinit ); | ||||||
| 	def_constant_spec( extern_linkage,   ESpecifier::External_Linkage ); | 	def_constant_spec( extern_linkage,   Spec_External_Linkage ); | ||||||
| 	def_constant_spec( final, 		     ESpecifier::Final ); | 	def_constant_spec( final, 		     Spec_Final ); | ||||||
| 	def_constant_spec( forceinline,      ESpecifier::ForceInline ); | 	def_constant_spec( forceinline,      Spec_ForceInline ); | ||||||
| 	def_constant_spec( global,           ESpecifier::Global ); | 	def_constant_spec( global,           Spec_Global ); | ||||||
| 	def_constant_spec( inline,           ESpecifier::Inline ); | 	def_constant_spec( inline,           Spec_Inline ); | ||||||
| 	def_constant_spec( internal_linkage, ESpecifier::Internal_Linkage ); | 	def_constant_spec( internal_linkage, Spec_Internal_Linkage ); | ||||||
| 	def_constant_spec( local_persist,    ESpecifier::Local_Persist ); | 	def_constant_spec( local_persist,    Spec_Local_Persist ); | ||||||
| 	def_constant_spec( mutable,          ESpecifier::Mutable ); | 	def_constant_spec( mutable,          Spec_Mutable ); | ||||||
| 	def_constant_spec( neverinline,      ESpecifier::NeverInline ); | 	def_constant_spec( neverinline,      Spec_NeverInline ); | ||||||
| 	def_constant_spec( noexcept,         ESpecifier::NoExceptions ); | 	def_constant_spec( noexcept,         Spec_NoExceptions ); | ||||||
| 	def_constant_spec( override,         ESpecifier::Override ); | 	def_constant_spec( override,         Spec_Override ); | ||||||
| 	def_constant_spec( ptr,              ESpecifier::Ptr ); | 	def_constant_spec( ptr,              Spec_Ptr ); | ||||||
| 	def_constant_spec( pure,             ESpecifier::Pure ) | 	def_constant_spec( pure,             Spec_Pure ) | ||||||
| 	def_constant_spec( ref,              ESpecifier::Ref ); | 	def_constant_spec( ref,              Spec_Ref ); | ||||||
| 	def_constant_spec( register,         ESpecifier::Register ); | 	def_constant_spec( register,         Spec_Register ); | ||||||
| 	def_constant_spec( rvalue,           ESpecifier::RValue ); | 	def_constant_spec( rvalue,           Spec_RValue ); | ||||||
| 	def_constant_spec( static_member,    ESpecifier::Static ); | 	def_constant_spec( static_member,    Spec_Static ); | ||||||
| 	def_constant_spec( thread_local,     ESpecifier::Thread_Local ); | 	def_constant_spec( thread_local,     Spec_Thread_Local ); | ||||||
| 	def_constant_spec( virtual, 		 ESpecifier::Virtual ); | 	def_constant_spec( virtual, 		 Spec_Virtual ); | ||||||
| 	def_constant_spec( volatile, 	     ESpecifier::Volatile) | 	def_constant_spec( volatile, 	     Spec_Volatile) | ||||||
|  |  | ||||||
| 	spec_local_persist = def_specifiers( 1, ESpecifier::Local_Persist ); | 	spec_local_persist = def_specifiers( 1, Spec_Local_Persist ); | ||||||
| 	spec_local_persist.set_global(); | 	set_global(spec_local_persist); | ||||||
|  |  | ||||||
| #	pragma pop_macro("forceinline") | #	pragma pop_macro("forceinline") | ||||||
| #	pragma pop_macro("global") | #	pragma pop_macro("global") | ||||||
| @@ -226,6 +226,10 @@ void define_constants() | |||||||
| #	pragma pop_macro("local_persist") | #	pragma pop_macro("local_persist") | ||||||
| #	pragma pop_macro("neverinline") | #	pragma pop_macro("neverinline") | ||||||
|  |  | ||||||
|  | #	pragma push_macro("enum_underlying") | ||||||
|  | 	array_append(PreprocessorDefines, txt("enum_underlying(")); | ||||||
|  | #	pragma pop_macro("enum_underlying") | ||||||
|  |  | ||||||
| #	undef def_constant_spec | #	undef def_constant_spec | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -235,28 +239,27 @@ void init() | |||||||
| 	{ | 	{ | ||||||
| 		GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr }; | 		GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr }; | ||||||
|  |  | ||||||
| 		Global_AllocatorBuckets = Array<Arena>::init_reserve( heap(), 128 ); | 		Global_AllocatorBuckets = array_init_reserve<Arena>( heap(), 128 ); | ||||||
|  |  | ||||||
| 		if ( Global_AllocatorBuckets == nullptr ) | 		if ( Global_AllocatorBuckets == nullptr ) | ||||||
| 			GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets"); | 			GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 		Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); | 		Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize ); | ||||||
|  |  | ||||||
| 		if ( bucket.PhysicalStart == nullptr ) | 		if ( bucket.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets"); | 			GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 		Global_AllocatorBuckets.append( bucket ); | 		array_append( Global_AllocatorBuckets, bucket ); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Setup the arrays | 	// Setup the arrays | ||||||
| 	{ | 	{ | ||||||
| 		CodePools = Array<Pool>::init_reserve( Allocator_DataArrays, InitSize_DataArrays ); | 		CodePools = array_init_reserve<Pool>( Allocator_DataArrays, InitSize_DataArrays ); | ||||||
|  |  | ||||||
| 		if ( CodePools == nullptr ) | 		if ( CodePools == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the CodePools array" ); | 			GEN_FATAL( "gen::init: Failed to initialize the CodePools array" ); | ||||||
|  |  | ||||||
| 		StringArenas = Array<Arena>::init_reserve( Allocator_DataArrays, InitSize_DataArrays ); | 		StringArenas = array_init_reserve<Arena>( Allocator_DataArrays, InitSize_DataArrays ); | ||||||
|  |  | ||||||
| 		if ( StringArenas == nullptr ) | 		if ( StringArenas == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" ); | 			GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" ); | ||||||
| @@ -264,97 +267,97 @@ void init() | |||||||
|  |  | ||||||
| 	// Setup the code pool and code entries arena. | 	// Setup the code pool and code entries arena. | ||||||
| 	{ | 	{ | ||||||
| 		Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | 		Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | ||||||
|  |  | ||||||
| 		if ( code_pool.PhysicalStart == nullptr ) | 		if ( code_pool.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the code pool" ); | 			GEN_FATAL( "gen::init: Failed to initialize the code pool" ); | ||||||
|  |  | ||||||
| 		CodePools.append( code_pool ); | 		array_append( CodePools, code_pool ); | ||||||
|  |  | ||||||
| 		LexArena = Arena::init_from_allocator( Allocator_Lexer, LexAllocator_Size ); | 		LexArena = arena_init_from_allocator( Allocator_Lexer, LexAllocator_Size ); | ||||||
|  |  | ||||||
| 		Arena string_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | 		Arena string_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | ||||||
|  |  | ||||||
| 		if ( string_arena.PhysicalStart == nullptr ) | 		if ( string_arena.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the string arena" ); | 			GEN_FATAL( "gen::init: Failed to initialize the string arena" ); | ||||||
|  |  | ||||||
| 		StringArenas.append( string_arena ); | 		array_append( StringArenas, string_arena ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Setup the hash tables | 	// Setup the hash tables | ||||||
| 	{ | 	{ | ||||||
| 		StringCache = StringTable::init( Allocator_StringTable ); | 		StringCache = hashtable_init<StringCached>(Allocator_StringTable); | ||||||
|  |  | ||||||
| 		if ( StringCache.Entries == nullptr ) | 		if ( StringCache.Entries == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the StringCache"); | 			GEN_FATAL( "gen::init: Failed to initialize the StringCache"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Preprocessor Defines | 	// Preprocessor Defines | ||||||
| 	PreprocessorDefines = Array<StringCached>::init_reserve( GlobalAllocator, kilobytes(1) ); | 	PreprocessorDefines = array_init_reserve<StringCached>( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	define_constants(); | 	define_constants(); | ||||||
| 	parser::init(); | 	GEN_NS_PARSER init(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void deinit() | void deinit() | ||||||
| { | { | ||||||
| 	usize index = 0; | 	usize index = 0; | ||||||
| 	usize left  = CodePools.num(); | 	usize left  = array_num(CodePools); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Pool* code_pool = & CodePools[index]; | 		Pool* code_pool = & CodePools[index]; | ||||||
| 		code_pool->free(); | 		pool_free(code_pool); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = StringArenas.num(); | 	left  = array_num(StringArenas); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* string_arena = & StringArenas[index]; | 		Arena* string_arena = & StringArenas[index]; | ||||||
| 		string_arena->free(); | 		arena_free(string_arena); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	StringCache.destroy(); | 	hashtable_destroy(StringCache); | ||||||
|  |  | ||||||
| 	CodePools.free(); | 	array_free( CodePools); | ||||||
| 	StringArenas.free(); | 	array_free( StringArenas); | ||||||
|  |  | ||||||
| 	LexArena.free(); | 	arena_free(& LexArena); | ||||||
|  |  | ||||||
| 	PreprocessorDefines.free(); | 	array_free(PreprocessorDefines); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = Global_AllocatorBuckets.num(); | 	left  = array_num(Global_AllocatorBuckets); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* bucket = & Global_AllocatorBuckets[ index ]; | 		Arena* bucket = & Global_AllocatorBuckets[ index ]; | ||||||
| 		bucket->free(); | 		arena_free(bucket); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	Global_AllocatorBuckets.free(); | 	array_free(Global_AllocatorBuckets); | ||||||
| 	parser::deinit(); | 	GEN_NS_PARSER deinit(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void reset() | void reset() | ||||||
| { | { | ||||||
| 	s32 index = 0; | 	s32 index = 0; | ||||||
| 	s32 left  = CodePools.num(); | 	s32 left  = array_num(CodePools); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Pool* code_pool = & CodePools[index]; | 		Pool* code_pool = & CodePools[index]; | ||||||
| 		code_pool->clear(); | 		pool_clear(code_pool); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = StringArenas.num(); | 	left  = array_num(StringArenas); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* string_arena = & StringArenas[index]; | 		Arena* string_arena = & StringArenas[index]; | ||||||
| @@ -363,28 +366,28 @@ void reset() | |||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	StringCache.clear(); | 	hashtable_clear(StringCache); | ||||||
|  |  | ||||||
| 	define_constants(); | 	define_constants(); | ||||||
| } | } | ||||||
|  |  | ||||||
| AllocatorInfo get_string_allocator( s32 str_length ) | AllocatorInfo get_string_allocator( s32 str_length ) | ||||||
| { | { | ||||||
| 	Arena* last = & StringArenas.back(); | 	Arena* last = array_back(StringArenas); | ||||||
|  |  | ||||||
| 	usize size_req = str_length + sizeof(String::Header) + sizeof(char*); | 	usize size_req = str_length + sizeof(StringHeader) + sizeof(char*); | ||||||
|  |  | ||||||
| 	if ( last->TotalUsed + ssize(size_req) > last->TotalSize ) | 	if ( last->TotalUsed + ssize(size_req) > last->TotalSize ) | ||||||
| 	{ | 	{ | ||||||
| 		Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | 		Arena new_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | ||||||
|  |  | ||||||
| 		if ( ! StringArenas.append( new_arena ) ) | 		if ( ! array_append( StringArenas, new_arena ) ) | ||||||
| 			GEN_FATAL( "gen::get_string_allocator: Failed to allocate a new string arena" ); | 			GEN_FATAL( "gen::get_string_allocator: Failed to allocate a new string arena" ); | ||||||
|  |  | ||||||
| 		last = & StringArenas.back(); | 		last = array_back(StringArenas); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return * last; | 	return arena_allocator_info(last); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Will either make or retrive a code string. | // Will either make or retrive a code string. | ||||||
| @@ -393,36 +396,36 @@ StringCached get_cached_string( StrC str ) | |||||||
| 	s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len; | 	s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len; | ||||||
| 	u64 key         = crc32( str.Ptr, hash_length ); | 	u64 key         = crc32( str.Ptr, hash_length ); | ||||||
| 	{ | 	{ | ||||||
| 		StringCached* result = StringCache.get( key ); | 		StringCached* result = hashtable_get(StringCache, key ); | ||||||
|  |  | ||||||
| 		if ( result ) | 		if ( result ) | ||||||
| 			return * result; | 			return * result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String result = String::make( get_string_allocator( str.Len ), str ); | 	StrC result = string_to_strc( string_make_strc( get_string_allocator( str.Len ), str )); | ||||||
| 	StringCache.set( key, result ); | 	hashtable_set(StringCache, key, result ); | ||||||
|  |  | ||||||
| 	return result; | 	return { str.Len, result }; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Used internally to retireve a Code object form the CodePool. | // Used internally to retireve a Code object form the CodePool. | ||||||
| Code make_code() | Code make_code() | ||||||
| { | { | ||||||
| 	Pool* allocator = & CodePools.back(); | 	Pool* allocator = array_back( CodePools); | ||||||
| 	if ( allocator->FreeList == nullptr ) | 	if ( allocator->FreeList == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | 		Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | ||||||
|  |  | ||||||
| 		if ( code_pool.PhysicalStart == nullptr ) | 		if ( code_pool.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." ); | 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." ); | ||||||
|  |  | ||||||
| 		if ( ! CodePools.append( code_pool ) ) | 		if ( ! array_append( CodePools, code_pool ) ) | ||||||
| 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." ); | 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." ); | ||||||
|  |  | ||||||
| 		allocator = & CodePools.back(); | 		allocator = array_back( CodePools); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code result { rcast( AST*, alloc( * allocator, sizeof(AST) )) }; | 	Code result { rcast( AST*, alloc( pool_allocator_info(allocator), sizeof(AST) )) }; | ||||||
| 	mem_set( result.ast, 0, sizeof(AST) ); | 	mem_set( result.ast, 0, sizeof(AST) ); | ||||||
| 	// result->Type = ECode::Invalid; | 	// result->Type = ECode::Invalid; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,77 +42,129 @@ void set_allocator_type_table  ( AllocatorInfo type_reg_allocator ); | |||||||
| CodeAttributes def_attributes( StrC content ); | CodeAttributes def_attributes( StrC content ); | ||||||
| CodeComment    def_comment   ( StrC content ); | CodeComment    def_comment   ( StrC content ); | ||||||
|  |  | ||||||
| CodeClass def_class( StrC name | struct Opts_def_struct { | ||||||
| 	, Code           body         = NoCode | 	Code           body; | ||||||
| 	, CodeType       parent       = NoCode, AccessSpec access = AccessSpec::Default | 	CodeTypename   parent; | ||||||
| 	, CodeAttributes attributes   = NoCode | 	AccessSpec     parent_access; | ||||||
| 	, ModuleFlag     mflags       = ModuleFlag::None | 	CodeAttributes attributes; | ||||||
| 	, CodeType*      interfaces   = nullptr, s32 num_interfaces = 0 ); | 	ModuleFlag     mflags; | ||||||
|  | 	CodeTypename*  interfaces; | ||||||
|  | 	s32            num_interfaces; | ||||||
|  | }; | ||||||
|  | CodeClass def_class( StrC name, Opts_def_struct otps GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeConstructor def_constructor( CodeParam params = NoCode, Code initializer_list = NoCode, Code body = NoCode ); | struct Opts_def_constructor { | ||||||
|  | 	CodeParam params; | ||||||
|  | 	Code      initializer_list; | ||||||
|  | 	Code      body; | ||||||
|  | }; | ||||||
|  | CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeDefine def_define( StrC name, StrC content ); | CodeDefine def_define( StrC name, StrC content ); | ||||||
|  |  | ||||||
| CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = NoCode ); | struct Opts_def_destructor { | ||||||
|  | 	Code           body; | ||||||
|  | 	CodeSpecifiers specifiers; | ||||||
|  | }; | ||||||
|  | CodeDestructor def_destructor( Opts_def_destructor opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeEnum def_enum( StrC name | struct Opts_def_enum { | ||||||
| 	, Code         body      = NoCode,      CodeType       type       = NoCode | 	Code           body; | ||||||
| 	, EnumT        specifier = EnumRegular, CodeAttributes attributes = NoCode | 	CodeTypename   type; | ||||||
| 	, ModuleFlag   mflags    = ModuleFlag::None ); | 	EnumT          specifier; | ||||||
|  | 	CodeAttributes attributes; | ||||||
|  | 	ModuleFlag     mflags; | ||||||
|  | }; | ||||||
|  | CodeEnum def_enum( StrC name, Opts_def_enum opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeExec   def_execution  ( StrC content ); | CodeExec   def_execution  ( StrC content ); | ||||||
| CodeExtern def_extern_link( StrC name, Code body ); | CodeExtern def_extern_link( StrC name, Code body ); | ||||||
| CodeFriend def_friend     ( Code symbol ); | CodeFriend def_friend     ( Code symbol ); | ||||||
|  |  | ||||||
| CodeFn def_function( StrC name | struct Opts_def_function { | ||||||
| 	, CodeParam      params     = NoCode, CodeType       ret_type   = NoCode, Code body = NoCode | 	CodeParam       params; | ||||||
| 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | 	CodeTypename    ret_type; | ||||||
| 	, ModuleFlag mflags     = ModuleFlag::None ); | 	Code            body; | ||||||
|  | 	CodeSpecifiers  specs; | ||||||
|  | 	CodeAttributes  attrs; | ||||||
|  | 	ModuleFlag      mflags; | ||||||
|  | }; | ||||||
|  | CodeFn def_function( StrC name, Opts_def_function opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeInclude   def_include  ( StrC content, bool foreign = false ); | struct Opts_def_include   { b32        foreign; }; | ||||||
| CodeModule    def_module   ( StrC name,            ModuleFlag mflags = ModuleFlag::None ); | struct Opts_def_module    { ModuleFlag mflags;  }; | ||||||
| CodeNS        def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None ); | struct Opts_def_namespace { ModuleFlag mflags;  }; | ||||||
|  | CodeInclude def_include  ( StrC content,         Opts_def_include   opts GEN_PARAM_DEFAULT ); | ||||||
|  | CodeModule  def_module   ( StrC name,            Opts_def_module    opts GEN_PARAM_DEFAULT ); | ||||||
|  | CodeNS      def_namespace( StrC name, Code body, Opts_def_namespace opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeOperator def_operator( OperatorT op, StrC nspace | struct Opts_def_operator { | ||||||
| 	, CodeParam      params     = NoCode, CodeType       ret_type   = NoCode, Code body = NoCode | 	CodeParam       params; | ||||||
| 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | 	CodeTypename    ret_type; | ||||||
| 	, ModuleFlag     mflags     = ModuleFlag::None ); | 	Code            body; | ||||||
|  | 	CodeSpecifiers  specifiers; | ||||||
|  | 	CodeAttributes  attributes; | ||||||
|  | 	ModuleFlag      mflags; | ||||||
|  | }; | ||||||
|  | CodeOperator def_operator( Operator op, StrC nspace, Opts_def_operator opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode ); | struct Opts_def_operator_cast { | ||||||
|  | 	Code           body; | ||||||
|  | 	CodeSpecifiers specs; | ||||||
|  | }; | ||||||
|  | CodeOpCast def_operator_cast( CodeTypename type, Opts_def_operator_cast opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeParam  def_param ( CodeType type, StrC name, Code value = NoCode ); | struct Opts_def_param { Code value; }; | ||||||
|  | CodeParam  def_param ( CodeTypename type, StrC name, Opts_def_param opts GEN_PARAM_DEFAULT ); | ||||||
| CodePragma def_pragma( StrC directive ); | CodePragma def_pragma( StrC directive ); | ||||||
|  |  | ||||||
| CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC content ); | CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC content ); | ||||||
|  |  | ||||||
| CodeSpecifiers def_specifier( SpecifierT specifier ); | CodeSpecifiers def_specifier( Specifier specifier ); | ||||||
|  |  | ||||||
| CodeStruct def_struct( StrC name | CodeStruct def_struct( StrC name, Opts_def_struct opts GEN_PARAM_DEFAULT ); | ||||||
| 	, Code           body       = NoCode |  | ||||||
| 	, CodeType       parent     = NoCode, AccessSpec access = AccessSpec::Default |  | ||||||
| 	, CodeAttributes attributes = NoCode |  | ||||||
| 	, ModuleFlag     mflags     = ModuleFlag::None |  | ||||||
| 	, CodeType*      interfaces = nullptr, s32 num_interfaces = 0 ); |  | ||||||
|  |  | ||||||
| CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag::None ); | struct Opts_def_template { ModuleFlag mflags; }; | ||||||
|  | CodeTemplate def_template( CodeParam params, Code definition, Opts_def_template opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeType    def_type   ( StrC name, Code arrayexpr = NoCode, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode ); | struct Opts_def_type { | ||||||
| CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); | 	Code           arrayexpr; | ||||||
|  | 	CodeSpecifiers specifiers; | ||||||
|  | 	CodeAttributes attributes; | ||||||
|  | }; | ||||||
|  | CodeTypename def_type( StrC name, Opts_def_type opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeUnion def_union( StrC name, Code body, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); | struct Opts_def_typedef { | ||||||
|  | 	CodeAttributes attributes; | ||||||
|  | 	ModuleFlag     mflags; | ||||||
|  | }; | ||||||
|  | CodeTypedef def_typedef( StrC name, Code type, Opts_def_typedef opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeUsing def_using( StrC name, CodeType type = NoCode | struct Opts_def_union { | ||||||
| 	, CodeAttributes attributess = NoCode | 	CodeAttributes attributes; | ||||||
| 	, ModuleFlag     mflags      = ModuleFlag::None ); | 	ModuleFlag     mflags; | ||||||
|  | }; | ||||||
|  | CodeUnion def_union( StrC name, Code body, Opts_def_union opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
|  | struct Opts_def_using { | ||||||
|  | 	CodeAttributes attributes; | ||||||
|  | 	ModuleFlag     mflags; | ||||||
|  | }; | ||||||
|  | CodeUsing def_using( StrC name, Code type, Opts_def_using opts GEN_PARAM_DEFAULT ); | ||||||
|  |  | ||||||
| CodeUsing def_using_namespace( StrC name ); | CodeUsing def_using_namespace( StrC name ); | ||||||
|  |  | ||||||
| CodeVar def_variable( CodeType type, StrC name, Code value = NoCode | struct Opts_def_variable | ||||||
| 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | { | ||||||
| 	, ModuleFlag     mflags     = ModuleFlag::None ); | 	Code           value; | ||||||
|  | 	CodeSpecifiers specifiers; | ||||||
|  | 	CodeAttributes attributes; | ||||||
|  | 	ModuleFlag     mflags; | ||||||
|  | }; | ||||||
|  | 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( CodeT type ); | CodeBody def_body( CodeTypename 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. | ||||||
| @@ -134,7 +186,7 @@ CodeBody       def_namespace_body  ( s32 num, Code* codes ); | |||||||
| CodeParam      def_params          ( s32 num, ... ); | CodeParam      def_params          ( s32 num, ... ); | ||||||
| CodeParam      def_params          ( s32 num, CodeParam* params ); | CodeParam      def_params          ( s32 num, CodeParam* params ); | ||||||
| CodeSpecifiers def_specifiers      ( s32 num, ... ); | CodeSpecifiers def_specifiers      ( s32 num, ... ); | ||||||
| CodeSpecifiers def_specifiers      ( s32 num, SpecifierT* specs ); | CodeSpecifiers def_specifiers      ( s32 num, Specifier* specs ); | ||||||
| CodeBody       def_struct_body     ( s32 num, ... ); | CodeBody       def_struct_body     ( s32 num, ... ); | ||||||
| CodeBody       def_struct_body     ( s32 num, Code* codes ); | CodeBody       def_struct_body     ( s32 num, Code* codes ); | ||||||
| CodeBody       def_union_body      ( s32 num, ... ); | CodeBody       def_union_body      ( s32 num, ... ); | ||||||
| @@ -194,7 +246,7 @@ CodeOperator    parse_operator     ( StrC operator_def    ); | |||||||
| CodeOpCast      parse_operator_cast( StrC operator_def    ); | CodeOpCast      parse_operator_cast( StrC operator_def    ); | ||||||
| CodeStruct      parse_struct       ( StrC struct_def      ); | CodeStruct      parse_struct       ( StrC struct_def      ); | ||||||
| CodeTemplate    parse_template     ( StrC template_def    ); | CodeTemplate    parse_template     ( StrC template_def    ); | ||||||
| CodeType        parse_type         ( StrC type_def        ); | CodeTypename    parse_type         ( StrC type_def        ); | ||||||
| CodeTypedef     parse_typedef      ( StrC typedef_def     ); | CodeTypedef     parse_typedef      ( StrC typedef_def     ); | ||||||
| CodeUnion       parse_union        ( StrC union_def       ); | CodeUnion       parse_union        ( StrC union_def       ); | ||||||
| CodeUsing       parse_using        ( StrC using_def       ); | CodeUsing       parse_using        ( StrC using_def       ); | ||||||
|   | |||||||
| @@ -10,58 +10,58 @@ | |||||||
|  |  | ||||||
| CodeClass parse_class( StrC def ) | CodeClass parse_class( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
| 	 | 	 | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	push_scope(); | 	push_scope(); | ||||||
| 	CodeClass result = (CodeClass) parse_class_struct( TokType::Decl_Class ); | 	CodeClass result = (CodeClass) parse_class_struct( Tok_Decl_Class ); | ||||||
| 	Context.pop(); | 	pop(& Context); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeConstructor parse_constructor( StrC def ) | CodeConstructor parse_constructor( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	// TODO(Ed): Constructors can have prefix attributes | 	// TODO(Ed): Constructors can have prefix attributes | ||||||
|  |  | ||||||
| 	CodeSpecifiers specifiers; | 	CodeSpecifiers specifiers; | ||||||
| 	SpecifierT     specs_found[ 16 ] { ESpecifier::NumSpecifiers }; | 	Specifier      specs_found[ 16 ] { Spec_NumSpecifiers }; | ||||||
| 	s32            NumSpecifiers = 0; | 	s32            NumSpecifiers = 0; | ||||||
|  |  | ||||||
| 	while ( left && currtok.is_specifier() ) | 	while ( left && is_specifier(currtok) ) | ||||||
| 	{ | 	{ | ||||||
| 		SpecifierT spec = ESpecifier::to_type( currtok ); | 		Specifier spec = to_specifier( to_str(currtok) ); | ||||||
|  |  | ||||||
| 		b32 ignore_spec = false; | 		b32 ignore_spec = false; | ||||||
|  |  | ||||||
| 		switch ( spec ) | 		switch ( spec ) | ||||||
| 		{ | 		{ | ||||||
| 			case ESpecifier::Constexpr : | 			case Spec_Constexpr : | ||||||
| 			case ESpecifier::Explicit: | 			case Spec_Explicit: | ||||||
| 			case ESpecifier::Inline : | 			case Spec_Inline : | ||||||
| 			case ESpecifier::ForceInline : | 			case Spec_ForceInline : | ||||||
| 			case ESpecifier::NeverInline : | 			case Spec_NeverInline : | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			case ESpecifier::Const : | 			case Spec_Const : | ||||||
| 				ignore_spec = true; | 				ignore_spec = true; | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			default : | 			default : | ||||||
| 				log_failure( "Invalid specifier %s for variable\n%s", ESpecifier::to_str( spec ), Context.to_string() ); | 				log_failure( "Invalid specifier %s for variable\n%s", to_str( spec ), to_string(Context) ); | ||||||
| 				Context.pop(); | 				pop(& Context); | ||||||
| 				return CodeInvalid; | 				return InvalidCode; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Every specifier after would be considered part of the type type signature | 		// Every specifier after would be considered part of the type type signature | ||||||
| @@ -86,12 +86,12 @@ CodeConstructor parse_constructor( StrC def ) | |||||||
|  |  | ||||||
| CodeDestructor parse_destructor( StrC def ) | CodeDestructor parse_destructor( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	// TODO(Ed): Destructors can have prefix attributes | 	// TODO(Ed): Destructors can have prefix attributes | ||||||
| 	// TODO(Ed): Destructors can have virtual | 	// TODO(Ed): Destructors can have virtual | ||||||
| @@ -103,14 +103,14 @@ CodeDestructor parse_destructor( StrC def ) | |||||||
|  |  | ||||||
| CodeEnum parse_enum( StrC def ) | CodeEnum parse_enum( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		Context.pop(); | 		pop(& Context); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| @@ -119,12 +119,12 @@ CodeEnum parse_enum( StrC def ) | |||||||
|  |  | ||||||
| CodeBody parse_export_body( StrC def ) | CodeBody parse_export_body( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_export_body(); | 	return parse_export_body(); | ||||||
| @@ -132,12 +132,12 @@ CodeBody parse_export_body( StrC def ) | |||||||
|  |  | ||||||
| CodeExtern parse_extern_link( StrC def ) | CodeExtern parse_extern_link( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_extern_link(); | 	return parse_extern_link(); | ||||||
| @@ -145,12 +145,12 @@ CodeExtern parse_extern_link( StrC def ) | |||||||
|  |  | ||||||
| CodeFriend parse_friend( StrC def ) | CodeFriend parse_friend( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_friend(); | 	return parse_friend(); | ||||||
| @@ -158,12 +158,12 @@ CodeFriend parse_friend( StrC def ) | |||||||
|  |  | ||||||
| CodeFn parse_function( StrC def ) | CodeFn parse_function( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return (CodeFn) parse_function(); | 	return (CodeFn) parse_function(); | ||||||
| @@ -171,28 +171,28 @@ CodeFn parse_function( StrC def ) | |||||||
|  |  | ||||||
| CodeBody parse_global_body( StrC def ) | CodeBody parse_global_body( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	push_scope(); | 	push_scope(); | ||||||
| 	CodeBody result = parse_global_nspace( ECode::Global_Body ); | 	CodeBody result = parse_global_nspace( CT_Global_Body ); | ||||||
| 	Context.pop(); | 	pop(& Context); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeNS parse_namespace( StrC def ) | CodeNS parse_namespace( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_namespace(); | 	return parse_namespace(); | ||||||
| @@ -200,12 +200,12 @@ CodeNS parse_namespace( StrC def ) | |||||||
|  |  | ||||||
| CodeOperator parse_operator( StrC def ) | CodeOperator parse_operator( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return (CodeOperator) parse_operator(); | 	return (CodeOperator) parse_operator(); | ||||||
| @@ -213,12 +213,12 @@ CodeOperator parse_operator( StrC def ) | |||||||
|  |  | ||||||
| CodeOpCast parse_operator_cast( StrC def ) | CodeOpCast parse_operator_cast( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_operator_cast(); | 	return parse_operator_cast(); | ||||||
| @@ -226,41 +226,41 @@ CodeOpCast parse_operator_cast( StrC def ) | |||||||
|  |  | ||||||
| CodeStruct parse_struct( StrC def ) | CodeStruct parse_struct( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	push_scope(); | 	push_scope(); | ||||||
| 	CodeStruct result = (CodeStruct) parse_class_struct( TokType::Decl_Struct ); | 	CodeStruct result = (CodeStruct) parse_class_struct( Tok_Decl_Struct ); | ||||||
| 	Context.pop(); | 	pop(& Context); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeTemplate parse_template( StrC def ) | CodeTemplate parse_template( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_template(); | 	return parse_template(); | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeType parse_type( StrC def ) | CodeTypename parse_type( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_type(); | 	return parse_type(); | ||||||
| @@ -268,12 +268,12 @@ CodeType parse_type( StrC def ) | |||||||
|  |  | ||||||
| CodeTypedef parse_typedef( StrC def ) | CodeTypedef parse_typedef( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_typedef(); | 	return parse_typedef(); | ||||||
| @@ -281,12 +281,12 @@ CodeTypedef parse_typedef( StrC def ) | |||||||
|  |  | ||||||
| CodeUnion parse_union( StrC def ) | CodeUnion parse_union( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_union(); | 	return parse_union(); | ||||||
| @@ -294,12 +294,12 @@ CodeUnion parse_union( StrC def ) | |||||||
|  |  | ||||||
| CodeUsing parse_using( StrC def ) | CodeUsing parse_using( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_using(); | 	return parse_using(); | ||||||
| @@ -307,12 +307,12 @@ CodeUsing parse_using( StrC def ) | |||||||
|  |  | ||||||
| CodeVar parse_variable( StrC def ) | CodeVar parse_variable( StrC def ) | ||||||
| { | { | ||||||
|  | 	GEN_USING_NS_PARSER; | ||||||
| 	check_parse_args( def ); | 	check_parse_args( def ); | ||||||
| 	using namespace parser; |  | ||||||
|  |  | ||||||
| 	TokArray toks = lex( def ); | 	TokArray toks = lex( def ); | ||||||
| 	if ( toks.Arr == nullptr ) | 	if ( toks.Arr == nullptr ) | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
|  |  | ||||||
| 	Context.Tokens = toks; | 	Context.Tokens = toks; | ||||||
| 	return parse_variable(); | 	return parse_variable(); | ||||||
|   | |||||||
| @@ -9,15 +9,13 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | |||||||
| 	ssize       remaining = buf_size; | 	ssize       remaining = buf_size; | ||||||
|  |  | ||||||
| 	local_persist | 	local_persist | ||||||
| 	Arena tok_map_arena; | 	FixedArena<TokenFmt_TokenMap_MemSize> tok_map_arena; | ||||||
|  | 	fixed_arena_init( & tok_map_arena); | ||||||
|  |  | ||||||
| 	HashTable<StrC> tok_map; |  | ||||||
| 	{ |  | ||||||
| 	local_persist | 	local_persist | ||||||
| 		char tok_map_mem[ TokenFmt_TokenMap_MemSize ]; | 	HashTable(StrC) tok_map; | ||||||
|  | 	{ | ||||||
| 		tok_map_arena = Arena::init_from_memory( tok_map_mem, sizeof(tok_map_mem) ); | 		tok_map = hashtable_init(StrC, fixed_arena_allocator_info(& tok_map_arena) ); | ||||||
| 		tok_map       = HashTable<StrC>::init( tok_map_arena ); |  | ||||||
|  |  | ||||||
| 		s32 left = num_tokens - 1; | 		s32 left = num_tokens - 1; | ||||||
|  |  | ||||||
| @@ -27,8 +25,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | |||||||
| 			StrC        value = va_arg( va, StrC ); | 			StrC        value = va_arg( va, StrC ); | ||||||
|  |  | ||||||
| 			u32 key = crc32( token, str_len(token) ); | 			u32 key = crc32( token, str_len(token) ); | ||||||
|  | 			hashtable_set( tok_map, key, value ); | ||||||
| 			tok_map.set( key, value ); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -64,7 +61,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | |||||||
| 			char const* token = fmt + 1; | 			char const* token = fmt + 1; | ||||||
|  |  | ||||||
| 			u32       key   = crc32( token, tok_len ); | 			u32       key   = crc32( token, tok_len ); | ||||||
| 			StrC*     value = tok_map.get( key ); | 			StrC*     value = hashtable_get(tok_map, key ); | ||||||
|  |  | ||||||
| 			if ( value ) | 			if ( value ) | ||||||
| 			{ | 			{ | ||||||
| @@ -94,8 +91,8 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tok_map.clear(); | 	hashtable_clear(tok_map); | ||||||
| 	tok_map_arena.free(); | 	fixed_arena_free(& tok_map_arena); | ||||||
|  |  | ||||||
| 	ssize result = buf_size - remaining; | 	ssize result = buf_size - remaining; | ||||||
|  |  | ||||||
| @@ -107,19 +104,19 @@ Code untyped_str( StrC content ) | |||||||
| 	if ( content.Len == 0 ) | 	if ( content.Len == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "untyped_str: empty string" ); | 		log_failure( "untyped_str: empty string" ); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| 	result->Name    = get_cached_string( content ); | 	result->Name    = get_cached_string( content ); | ||||||
| 	result->Type    = ECode::Untyped; | 	result->Type    = CT_Untyped; | ||||||
| 	result->Content = result->Name; | 	result->Content = result->Name; | ||||||
|  |  | ||||||
| 	if ( result->Name == nullptr ) | 	if ( result->Name == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "untyped_str: could not cache string" ); | 		log_failure( "untyped_str: could not cache string" ); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| @@ -130,7 +127,7 @@ Code untyped_fmt( char const* fmt, ...) | |||||||
| 	if ( fmt == nullptr ) | 	if ( fmt == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "untyped_fmt: null format string" ); | 		log_failure( "untyped_fmt: null format string" ); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	local_persist thread_local | 	local_persist thread_local | ||||||
| @@ -143,14 +140,14 @@ Code untyped_fmt( char const* fmt, ...) | |||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| 	result->Name    = get_cached_string( { str_len(fmt, MaxNameLength), fmt } ); | 	result->Name    = get_cached_string( { str_len_capped(fmt, MaxNameLength), fmt } ); | ||||||
| 	result->Type    = ECode::Untyped; | 	result->Type    = CT_Untyped; | ||||||
| 	result->Content = get_cached_string( { length, buf } ); | 	result->Content = get_cached_string( { length, buf } ); | ||||||
|  |  | ||||||
| 	if ( result->Name == nullptr ) | 	if ( result->Name == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "untyped_fmt: could not cache string" ); | 		log_failure( "untyped_fmt: could not cache string" ); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| @@ -161,7 +158,7 @@ Code untyped_token_fmt( s32 num_tokens, ... ) | |||||||
| 	if ( num_tokens == 0 ) | 	if ( num_tokens == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "untyped_token_fmt: zero tokens" ); | 		log_failure( "untyped_token_fmt: zero tokens" ); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	local_persist thread_local | 	local_persist thread_local | ||||||
| @@ -175,13 +172,13 @@ Code untyped_token_fmt( s32 num_tokens, ... ) | |||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| 	result->Name    = get_cached_string( { length, buf } ); | 	result->Name    = get_cached_string( { length, buf } ); | ||||||
| 	result->Type    = ECode::Untyped; | 	result->Type    = CT_Untyped; | ||||||
| 	result->Content = result->Name; | 	result->Content = result->Name; | ||||||
|  |  | ||||||
| 	if ( result->Name == nullptr ) | 	if ( result->Name == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "untyped_fmt: could not cache string" ); | 		log_failure( "untyped_fmt: could not cache string" ); | ||||||
| 		return CodeInvalid; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -72,36 +72,36 @@ global CodeSpecifiers spec_thread_local; | |||||||
| global CodeSpecifiers spec_virtual; | global CodeSpecifiers spec_virtual; | ||||||
| global CodeSpecifiers spec_volatile; | global CodeSpecifiers spec_volatile; | ||||||
|  |  | ||||||
| global CodeType t_empty; | global CodeTypename t_empty; | ||||||
| global CodeType t_auto; | global CodeTypename t_auto; | ||||||
| global CodeType t_void; | global CodeTypename t_void; | ||||||
| global CodeType t_int; | global CodeTypename t_int; | ||||||
| global CodeType t_bool; | global CodeTypename t_bool; | ||||||
| global CodeType t_char; | global CodeTypename t_char; | ||||||
| global CodeType t_wchar_t; | global CodeTypename t_wchar_t; | ||||||
| global CodeType t_class; | global CodeTypename t_class; | ||||||
| global CodeType t_typename; | global CodeTypename t_typename; | ||||||
|  |  | ||||||
| global Array< StringCached > PreprocessorDefines; | global Array(StringCached) PreprocessorDefines; | ||||||
|  |  | ||||||
| #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| global CodeType t_b32; | global CodeTypename t_b32; | ||||||
|  |  | ||||||
| global CodeType t_s8; | global CodeTypename t_s8; | ||||||
| global CodeType t_s16; | global CodeTypename t_s16; | ||||||
| global CodeType t_s32; | global CodeTypename t_s32; | ||||||
| global CodeType t_s64; | global CodeTypename t_s64; | ||||||
|  |  | ||||||
| global CodeType t_u8; | global CodeTypename t_u8; | ||||||
| global CodeType t_u16; | global CodeTypename t_u16; | ||||||
| global CodeType t_u32; | global CodeTypename t_u32; | ||||||
| global CodeType t_u64; | global CodeTypename t_u64; | ||||||
|  |  | ||||||
| global CodeType t_ssize; | global CodeTypename t_ssize; | ||||||
| global CodeType t_usize; | global CodeTypename t_usize; | ||||||
|  |  | ||||||
| global CodeType t_f32; | global CodeTypename t_f32; | ||||||
| global CodeType t_f64; | global CodeTypename t_f64; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma endregion Constants | #pragma endregion Constants | ||||||
|   | |||||||
| @@ -13,63 +13,71 @@ using LogFailType = ssize(*)(char const*, ...); | |||||||
| 	#define log_failure GEN_FATAL | 	#define log_failure GEN_FATAL | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| enum class AccessSpec : u32 | enum AccessSpec enum_underlying(u32) | ||||||
| { | { | ||||||
| 	Default, | 	AccessSpec_Default, | ||||||
| 	Private, | 	AccessSpec_Private, | ||||||
| 	Protected, | 	AccessSpec_Protected, | ||||||
| 	Public, | 	AccessSpec_Public, | ||||||
|  |  | ||||||
| 	Num_AccessSpec, | 	AccessSpec_Num_AccessSpec, | ||||||
| 	Invalid, | 	AccessSpec_Invalid, | ||||||
|  |  | ||||||
|  | 	AccessSpec_SizeDef = GEN_U32_MAX, | ||||||
| }; | }; | ||||||
|  | static_assert( size_of(AccessSpec) == size_of(u32), "AccessSpec not u32 size" ); | ||||||
|  |  | ||||||
| inline | inline | ||||||
| char const* to_str( AccessSpec type ) | char const* to_str( AccessSpec type ) | ||||||
| { | { | ||||||
| 	local_persist | 	local_persist | ||||||
| 	char const* lookup[ (u32)AccessSpec::Num_AccessSpec ] = { | 	char const* lookup[ (u32)AccessSpec_Num_AccessSpec ] = { | ||||||
| 		"", | 		"", | ||||||
| 		"private", | 		"private", | ||||||
| 		"protected", | 		"protected", | ||||||
| 		"public", | 		"public", | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	if ( type > AccessSpec::Public ) | 	if ( type > AccessSpec_Public ) | ||||||
| 		return "Invalid"; | 		return "Invalid"; | ||||||
|  |  | ||||||
| 	return lookup[ (u32)type ]; | 	return lookup[ (u32)type ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | enum CodeFlag enum_underlying(u32) | ||||||
| enum CodeFlag : u32 |  | ||||||
| { | { | ||||||
| 	None          = 0, | 	CodeFlag_None          = 0, | ||||||
| 	FunctionType  = bit(0), | 	CodeFlag_FunctionType  = bit(0), | ||||||
| 	ParamPack     = bit(1), | 	CodeFlag_ParamPack     = bit(1), | ||||||
| 	Module_Export = bit(2), | 	CodeFlag_Module_Export = bit(2), | ||||||
| 	Module_Import = bit(3), | 	CodeFlag_Module_Import = bit(3), | ||||||
|  |  | ||||||
|  | 	CodeFlag_SizeDef = GEN_U32_MAX, | ||||||
| }; | }; | ||||||
|  | static_assert( size_of(CodeFlag) == size_of(u32), "CodeFlag not u32 size" ); | ||||||
|  |  | ||||||
| // Used to indicate if enum definitoin is an enum class or regular enum. | // Used to indicate if enum definitoin is an enum class or regular enum. | ||||||
| enum class EnumT : u8 | enum EnumDecl enum_underlying(u8) | ||||||
| { | { | ||||||
| 	Regular, | 	EnumDecl_Regular, | ||||||
| 	Class | 	EnumDecl_Class, | ||||||
|  |  | ||||||
|  | 	EnumT_SizeDef = GEN_U8_MAX, | ||||||
| }; | }; | ||||||
|  | typedef u8 EnumT; | ||||||
|  |  | ||||||
| constexpr EnumT EnumClass   = EnumT::Class; | enum ModuleFlag enum_underlying(u32) | ||||||
| constexpr EnumT EnumRegular = EnumT::Regular; |  | ||||||
|  |  | ||||||
| enum class ModuleFlag : u32 |  | ||||||
| { | { | ||||||
| 	None    = 0, | 	ModuleFlag_None    = 0, | ||||||
| 	Export  = bit(0), | 	ModuleFlag_Export  = bit(0), | ||||||
| 	Import  = bit(1), | 	ModuleFlag_Import  = bit(1), | ||||||
|  |  | ||||||
| 	Num_ModuleFlags, | 	Num_ModuleFlags, | ||||||
| 	Invalid, | 	ModuleFlag_Invalid, | ||||||
|  |  | ||||||
|  | 	ModuleFlag_SizeDef = GEN_U32_MAX, | ||||||
| }; | }; | ||||||
|  | static_assert( size_of(ModuleFlag) == size_of(u32), "ModuleFlag not u32 size" ); | ||||||
|  |  | ||||||
| inline | inline | ||||||
| StrC to_str( ModuleFlag flag ) | StrC to_str( ModuleFlag flag ) | ||||||
| @@ -81,7 +89,7 @@ StrC to_str( ModuleFlag flag ) | |||||||
| 		{ sizeof("import"), "import" }, | 		{ sizeof("import"), "import" }, | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	if ( flag > ModuleFlag::Import ) | 	if ( flag > ModuleFlag_Import ) | ||||||
| 		return { sizeof("invalid"), "invalid" }; | 		return { sizeof("invalid"), "invalid" }; | ||||||
|  |  | ||||||
| 	return lookup[ (u32)flag ]; | 	return lookup[ (u32)flag ]; | ||||||
| @@ -93,15 +101,13 @@ ModuleFlag operator|( ModuleFlag A, ModuleFlag B) | |||||||
| 	return (ModuleFlag)( (u32)A | (u32)B ); | 	return (ModuleFlag)( (u32)A | (u32)B ); | ||||||
| } | } | ||||||
|  |  | ||||||
| enum class EPreprocessCond : u32 | enum EPreprocessCond enum_underlying(u32) | ||||||
| { | { | ||||||
| 	If, | 	PreprocessCond_If, | ||||||
| 	IfDef, | 	PreprocessCond_IfDef, | ||||||
| 	IfNotDef, | 	PreprocessCond_IfNotDef, | ||||||
| 	ElIf | 	PreprocessCond_ElIf, | ||||||
| }; |  | ||||||
|  |  | ||||||
| constexpr EPreprocessCond PreprocessCond_If       = EPreprocessCond::If; | 	EPreprocessCond_SizeDef = GEN_U32_MAX, | ||||||
| constexpr EPreprocessCond PreprocessCond_IfDef    = EPreprocessCond::IfDef; | }; | ||||||
| constexpr EPreprocessCond PreprocessCond_IfNotDef = EPreprocessCond::IfNotDef; | static_assert( size_of(EPreprocessCond) == size_of(u32), "EPreprocessCond not u32 size" ); | ||||||
| constexpr EPreprocessCond PreprocessCond_ElIf     = EPreprocessCond::ElIf; |  | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
| #ifdef GEN_INTELLISENSE_DIRECTIVES | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
| #	pragma once | #	pragma once | ||||||
|  | #	include "platform.hpp" | ||||||
| #	include "macros.hpp" | #	include "macros.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Basic Types | #pragma region Basic Types | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| #define GEN_U8_MIN 0u | #define GEN_U8_MIN 0u | ||||||
| #define GEN_U8_MAX 0xffu | #define GEN_U8_MAX 0xffu | ||||||
| @@ -122,13 +124,24 @@ typedef s8  b8; | |||||||
| typedef s16 b16; | typedef s16 b16; | ||||||
| typedef s32 b32; | typedef s32 b32; | ||||||
|  |  | ||||||
| using mem_ptr       = void*; | typedef void*       mem_ptr; | ||||||
| using mem_ptr_const = void const*; | typedef void const* mem_ptr_const ; | ||||||
|  |  | ||||||
|  | #if ! GEN_COMPILER_C | ||||||
|  | GEN_API_C_END | ||||||
| template<typename Type> uptr to_uptr( Type* ptr ) { return (uptr)ptr; } | template<typename Type> uptr to_uptr( Type* ptr ) { return (uptr)ptr; } | ||||||
| template<typename Type> sptr to_sptr( Type* ptr ) { return (sptr)ptr; } | template<typename Type> sptr to_sptr( Type* ptr ) { return (sptr)ptr; } | ||||||
|  |  | ||||||
| template<typename Type> mem_ptr       to_mem_ptr      ( Type ptr ) { return (mem_ptr)      ptr; } | template<typename Type> mem_ptr       to_mem_ptr      ( Type ptr ) { return (mem_ptr)      ptr; } | ||||||
| template<typename Type> mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem_ptr_const)ptr; } | template<typename Type> mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem_ptr_const)ptr; } | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  | #else | ||||||
|  | #define to_uptr( ptr ) ((uptr)(ptr)) | ||||||
|  | #define to_sptr( ptr ) ((sptr)(ptr)) | ||||||
|  |  | ||||||
|  | #define to_mem_ptr( ptr)       ((mem_ptr)ptr) | ||||||
|  | #define to_mem_ptr_const( ptr) ((mem_ptr)ptr) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Basic Types | #pragma endregion Basic Types | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -6,6 +6,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Debug | #pragma region Debug | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ) | void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ) | ||||||
| { | { | ||||||
| @@ -45,4 +46,5 @@ s32 assert_crash( char const* condition ) | |||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Debug | #pragma endregion Debug | ||||||
|   | |||||||
| @@ -56,8 +56,10 @@ | |||||||
| 	while (0) | 	while (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
| void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ); | void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ); | ||||||
| s32  assert_crash( char const* condition ); | s32  assert_crash( char const* condition ); | ||||||
| void process_exit( u32 code ); | void process_exit( u32 code ); | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Debug | #pragma endregion Debug | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region File Handling | #pragma region File Handling | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| #if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) | #if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) | ||||||
|  |  | ||||||
| @@ -36,7 +37,7 @@ wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, ssize* w_len_ ) | |||||||
| 	w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, scast( int, len), w_text, scast( int, w_len) ); | 	w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, scast( int, len), w_text, scast( int, w_len) ); | ||||||
| 	if ( w_len1 == 0 ) | 	if ( w_len1 == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		free( a, w_text ); | 		allocator_free( a, w_text ); | ||||||
| 		if ( w_len_ ) | 		if ( w_len_ ) | ||||||
| 			*w_len_ = 0; | 			*w_len_ = 0; | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -145,7 +146,7 @@ GEN_FILE_OPEN_PROC( _win32_file_open ) | |||||||
| 	w_text = _alloc_utf8_to_ucs2( heap(), filename, NULL ); | 	w_text = _alloc_utf8_to_ucs2( heap(), filename, NULL ); | ||||||
| 	handle = CreateFileW( w_text, desired_access, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL ); | 	handle = CreateFileW( w_text, desired_access, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL ); | ||||||
|  |  | ||||||
| 	free( heap(), w_text ); | 	allocator_free( heap(), w_text ); | ||||||
|  |  | ||||||
| 	if ( handle == INVALID_HANDLE_VALUE ) | 	if ( handle == INVALID_HANDLE_VALUE ) | ||||||
| 	{ | 	{ | ||||||
| @@ -340,7 +341,7 @@ FileError file_close( FileInfo* f ) | |||||||
| 		return EFileError_INVALID; | 		return EFileError_INVALID; | ||||||
|  |  | ||||||
| 	if ( f->filename ) | 	if ( f->filename ) | ||||||
| 		free( heap(), ccast( char*, f->filename )); | 		allocator_free( heap(), ccast( char*, f->filename )); | ||||||
|  |  | ||||||
| #if defined( GEN_SYSTEM_WINDOWS ) | #if defined( GEN_SYSTEM_WINDOWS ) | ||||||
| 	if ( f->fd.p == INVALID_HANDLE_VALUE ) | 	if ( f->fd.p == INVALID_HANDLE_VALUE ) | ||||||
| @@ -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<u8>::init( 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<u8>::init_reserve( allocator, size ); | 		Array<u8> arr = array_init_reserve<u8>( allocator, size ); | ||||||
| 		d->buf = arr; | 		d->buf = arr; | ||||||
|  |  | ||||||
| 		if ( ! d->buf ) | 		if ( ! d->buf ) | ||||||
| @@ -540,7 +541,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize | |||||||
| 		mem_copy( d->buf, buffer, size ); | 		mem_copy( d->buf, buffer, size ); | ||||||
| 		d->cap = size; | 		d->cap = size; | ||||||
|  |  | ||||||
| 		arr.get_header()->Num = size; | 		array_get_header(arr)->Num = size; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -610,9 +611,9 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array<u8> arr = { d->buf }; | ||||||
|  |  | ||||||
| 		if ( arr.get_header()->Capacity < usize(new_cap) ) | 		if ( array_get_header(arr)->Capacity < usize(new_cap) ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( ! arr.grow( ( s64 )( new_cap ) ) ) | 			if ( ! array_grow( & arr, ( s64 )( new_cap ) ) ) | ||||||
| 				return false; | 				return false; | ||||||
| 			d->buf = arr; | 			d->buf = arr; | ||||||
| 		} | 		} | ||||||
| @@ -626,7 +627,7 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
|  |  | ||||||
| 		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; | ||||||
| 		arr.get_header()->Capacity = new_cap; | 		array_get_header(arr)->Capacity = new_cap; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -647,12 +648,13 @@ 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 }; | ||||||
| 		arr.free(); | 		array_free(arr); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	free( allocator, d ); | 	allocator_free( allocator, d ); | ||||||
| } | } | ||||||
|  |  | ||||||
| FileOperations const memory_file_operations = { _memory_file_read, _memory_file_write, _memory_file_seek, _memory_file_close }; | FileOperations const memory_file_operations = { _memory_file_read, _memory_file_write, _memory_file_seek, _memory_file_close }; | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion File Handling | #pragma endregion File Handling | ||||||
|   | |||||||
| @@ -4,10 +4,11 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region File Handling | #pragma region File Handling | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| typedef u32 FileMode; | typedef u32 FileMode; | ||||||
|  |  | ||||||
| enum FileModeFlag | enum FileModeFlag_Def | ||||||
| { | { | ||||||
| 	EFileMode_READ   = bit( 0 ), | 	EFileMode_READ   = bit( 0 ), | ||||||
| 	EFileMode_WRITE  = bit( 1 ), | 	EFileMode_WRITE  = bit( 1 ), | ||||||
| @@ -15,16 +16,18 @@ enum FileModeFlag | |||||||
| 	EFileMode_RW     = bit( 3 ), | 	EFileMode_RW     = bit( 3 ), | ||||||
| 	GEN_FILE_MODES   = EFileMode_READ | EFileMode_WRITE | EFileMode_APPEND | EFileMode_RW, | 	GEN_FILE_MODES   = EFileMode_READ | EFileMode_WRITE | EFileMode_APPEND | EFileMode_RW, | ||||||
| }; | }; | ||||||
|  | typedef enum FileModeFlag_Def FileModeFlag; | ||||||
|  |  | ||||||
| // NOTE: Only used internally and for the file operations | // NOTE: Only used internally and for the file operations | ||||||
| enum SeekWhenceType | enum SeekWhenceType_Def | ||||||
| { | { | ||||||
| 	ESeekWhence_BEGIN   = 0, | 	ESeekWhence_BEGIN   = 0, | ||||||
| 	ESeekWhence_CURRENT = 1, | 	ESeekWhence_CURRENT = 1, | ||||||
| 	ESeekWhence_END     = 2, | 	ESeekWhence_END     = 2, | ||||||
| }; | }; | ||||||
|  | typedef enum SeekWhenceType_Def SeekWhenceType; | ||||||
|  |  | ||||||
| enum FileError | enum FileError_Def | ||||||
| { | { | ||||||
| 	EFileError_NONE, | 	EFileError_NONE, | ||||||
| 	EFileError_INVALID, | 	EFileError_INVALID, | ||||||
| @@ -37,19 +40,21 @@ enum FileError | |||||||
| 	EFileError_NAME_TOO_LONG, | 	EFileError_NAME_TOO_LONG, | ||||||
| 	EFileError_UNKNOWN, | 	EFileError_UNKNOWN, | ||||||
| }; | }; | ||||||
|  | typedef enum FileError_Def FileError; | ||||||
|  |  | ||||||
| union FileDescriptor | union FileDescriptor_Def | ||||||
| { | { | ||||||
| 	void* p; | 	void* p; | ||||||
| 	sptr  i; | 	sptr  i; | ||||||
| 	uptr  u; | 	uptr  u; | ||||||
| }; | }; | ||||||
|  | typedef union FileDescriptor_Def FileDescriptor; | ||||||
|  |  | ||||||
| typedef struct FileOperations FileOperations; | typedef struct FileOperations_Def FileOperations; | ||||||
|  |  | ||||||
| #define GEN_FILE_OPEN_PROC( name )     FileError name( FileDescriptor* fd, FileOperations* ops, FileMode mode, char const* filename ) | #define GEN_FILE_OPEN_PROC( name )     FileError name( FileDescriptor* fd, FileOperations* ops, FileMode mode, char const* filename ) | ||||||
| #define GEN_FILE_READ_AT_PROC( name )  b32 name( FileDescriptor fd, void* buffer, ssize size, s64 offset, ssize* bytes_read, b32 stop_at_newline ) | #define GEN_FILE_READ_AT_PROC( name )  b32 name( FileDescriptor fd, void* buffer, ssize size, s64 offset, ssize* bytes_read, b32 stop_at_newline ) | ||||||
| #define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, void const* buffer, ssize size, s64 offset, ssize* bytes_written ) | #define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, mem_ptr_const buffer, ssize size, s64 offset, ssize* bytes_written ) | ||||||
| #define GEN_FILE_SEEK_PROC( name )     b32 name( FileDescriptor fd, s64 offset, SeekWhenceType whence, s64* new_offset ) | #define GEN_FILE_SEEK_PROC( name )     b32 name( FileDescriptor fd, s64 offset, SeekWhenceType whence, s64* new_offset ) | ||||||
| #define GEN_FILE_CLOSE_PROC( name )    void name( FileDescriptor fd ) | #define GEN_FILE_CLOSE_PROC( name )    void name( FileDescriptor fd ) | ||||||
|  |  | ||||||
| @@ -59,35 +64,39 @@ typedef GEN_FILE_WRITE_AT_PROC( FileWriteProc ); | |||||||
| typedef GEN_FILE_SEEK_PROC( FileSeekProc ); | typedef GEN_FILE_SEEK_PROC( FileSeekProc ); | ||||||
| typedef GEN_FILE_CLOSE_PROC( FileCloseProc ); | typedef GEN_FILE_CLOSE_PROC( FileCloseProc ); | ||||||
|  |  | ||||||
| struct FileOperations | struct FileOperations_Def | ||||||
| { | { | ||||||
| 	FileReadProc*  read_at; | 	FileReadProc*  read_at; | ||||||
| 	FileWriteProc* write_at; | 	FileWriteProc* write_at; | ||||||
| 	FileSeekProc*  seek; | 	FileSeekProc*  seek; | ||||||
| 	FileCloseProc* close; | 	FileCloseProc* close; | ||||||
| }; | }; | ||||||
|  | typedef struct FileOperations_Def FileOperations; | ||||||
|  |  | ||||||
| extern FileOperations const default_file_operations; | extern FileOperations const default_file_operations; | ||||||
|  |  | ||||||
| typedef u64 FileTime; | typedef u64 FileTime; | ||||||
|  |  | ||||||
| enum DirType | enum DirType_Def | ||||||
| { | { | ||||||
| 	GEN_DIR_TYPE_FILE, | 	GEN_DIR_TYPE_FILE, | ||||||
| 	GEN_DIR_TYPE_FOLDER, | 	GEN_DIR_TYPE_FOLDER, | ||||||
| 	GEN_DIR_TYPE_UNKNOWN, | 	GEN_DIR_TYPE_UNKNOWN, | ||||||
| }; | }; | ||||||
|  | typedef enum DirType_Def DirType; | ||||||
|  |  | ||||||
| struct DirInfo; | struct DirInfo_Def; | ||||||
|  | typedef struct DirInfo_Def DirInfo; | ||||||
|  |  | ||||||
| struct DirEntry | struct DirEntry_Def | ||||||
| { | { | ||||||
| 	char const* filename; | 	char const* filename; | ||||||
| 	struct DirInfo* dir_info; | 	DirInfo*    dir_info; | ||||||
| 	u8          type; | 	u8          type; | ||||||
| }; | }; | ||||||
|  | typedef struct DirEntry_Def DirEntry; | ||||||
|  |  | ||||||
| struct DirInfo | struct DirInfo_Def | ||||||
| { | { | ||||||
| 	char const* fullpath; | 	char const* fullpath; | ||||||
| 	DirEntry*   entries;    // zpl_array | 	DirEntry*   entries;    // zpl_array | ||||||
| @@ -97,7 +106,7 @@ struct DirInfo | |||||||
| 	String buf; | 	String buf; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct FileInfo | struct FileInfo_Def | ||||||
| { | { | ||||||
| 	FileOperations ops; | 	FileOperations ops; | ||||||
| 	FileDescriptor fd; | 	FileDescriptor fd; | ||||||
| @@ -107,8 +116,9 @@ struct FileInfo | |||||||
| 	FileTime    last_write_time; | 	FileTime    last_write_time; | ||||||
| 	DirEntry*   dir; | 	DirEntry*   dir; | ||||||
| }; | }; | ||||||
|  | typedef struct FileInfo_Def FileInfo; | ||||||
|  |  | ||||||
| enum FileStandardType | enum FileStandardType_Def | ||||||
| { | { | ||||||
| 	EFileStandard_INPUT, | 	EFileStandard_INPUT, | ||||||
| 	EFileStandard_OUTPUT, | 	EFileStandard_OUTPUT, | ||||||
| @@ -116,6 +126,7 @@ enum FileStandardType | |||||||
|  |  | ||||||
| 	EFileStandard_COUNT, | 	EFileStandard_COUNT, | ||||||
| }; | }; | ||||||
|  | typedef enum FileStandardType_Def FileStandardType; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Get standard file I/O. | 	* Get standard file I/O. | ||||||
| @@ -183,6 +194,7 @@ b32 file_read_at( FileInfo* file, void* buffer, ssize size, s64 offset ); | |||||||
| 	*/ | 	*/ | ||||||
| b32 file_read_at_check( FileInfo* file, void* buffer, ssize size, s64 offset, ssize* bytes_read ); | b32 file_read_at_check( FileInfo* file, void* buffer, ssize size, s64 offset, ssize* bytes_read ); | ||||||
|  |  | ||||||
|  | typedef struct FileContents FileContents; | ||||||
| struct FileContents | struct FileContents | ||||||
| { | { | ||||||
| 	AllocatorInfo allocator; | 	AllocatorInfo allocator; | ||||||
| @@ -190,8 +202,8 @@ struct FileContents | |||||||
| 	ssize            size; | 	ssize            size; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| constexpr b32 zero_terminate    = true; | constexpr b32 file_zero_terminate    = true; | ||||||
| constexpr b32 no_zero_terminate = false; | constexpr b32 file_no_zero_terminate = false; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Reads the whole file contents | 	* Reads the whole file contents | ||||||
| @@ -257,7 +269,7 @@ b32 file_write_at( FileInfo* file, void const* buffer, ssize size, s64 offset ); | |||||||
| 	*/ | 	*/ | ||||||
| b32 file_write_at_check( FileInfo* file, void const* buffer, ssize size, s64 offset, ssize* bytes_written ); | b32 file_write_at_check( FileInfo* file, void const* buffer, ssize size, s64 offset, ssize* bytes_written ); | ||||||
|  |  | ||||||
| enum FileStreamFlags : u32 | enum FileStreamFlags_Def enum_underlying(u32) | ||||||
| { | { | ||||||
| 	/* Allows us to write to the buffer directly. Beware: you can not append a new data! */ | 	/* Allows us to write to the buffer directly. Beware: you can not append a new data! */ | ||||||
| 	EFileStream_WRITABLE = bit( 0 ), | 	EFileStream_WRITABLE = bit( 0 ), | ||||||
| @@ -265,7 +277,10 @@ enum FileStreamFlags : u32 | |||||||
| 	/* Clones the input buffer so you can write (zpl_file_write*) data into it. */ | 	/* Clones the input buffer so you can write (zpl_file_write*) data into it. */ | ||||||
| 	/* Since we work with a clone, the buffer size can dynamically grow as well. */ | 	/* Since we work with a clone, the buffer size can dynamically grow as well. */ | ||||||
| 	EFileStream_CLONE_WRITABLE = bit( 1 ), | 	EFileStream_CLONE_WRITABLE = bit( 1 ), | ||||||
|  |  | ||||||
|  | 	EFileStream_UNDERLYING = GEN_U32_MAX, | ||||||
| }; | }; | ||||||
|  | typedef enum FileStreamFlags_Def FileStreamFlags; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Opens a new memory stream | 	* Opens a new memory stream | ||||||
| @@ -381,4 +396,5 @@ b32 file_write_at_check( FileInfo* f, void const* buffer, ssize size, s64 offset | |||||||
| 	return f->ops.write_at( f->fd, buffer, size, offset, bytes_written ); | 	return f->ops.write_at( f->fd, buffer, size, offset, bytes_written ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion File Handling | #pragma endregion File Handling | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Hashing | #pragma region Hashing | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| global u32 const _crc32_table[ 256 ] = { | global u32 const _crc32_table[ 256 ] = { | ||||||
| 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, | 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, | ||||||
| @@ -87,4 +88,5 @@ u64 crc64( void const* data, ssize len ) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Hashing | #pragma endregion Hashing | ||||||
|   | |||||||
| @@ -4,8 +4,10 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Hashing | #pragma region Hashing | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| u32 crc32( void const* data, ssize len ); | u32 crc32( void const* data, ssize len ); | ||||||
| u64 crc64( void const* data, ssize len ); | u64 crc64( void const* data, ssize len ); | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Hashing | #pragma endregion Hashing | ||||||
|   | |||||||
| @@ -14,15 +14,15 @@ | |||||||
| #define local_persist static    // Local Persisting variables | #define local_persist static    // Local Persisting variables | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef api_c |  | ||||||
| #define api_c extern "C" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef bit | #ifndef bit | ||||||
| #define bit( Value )                             ( 1 << Value ) | #define bit( Value )                             ( 1 << Value ) | ||||||
| #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) | #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP | ||||||
|  | #	ifndef cast | ||||||
|  | #	define cast( type, value ) (tmpl_cast<type>( value )) | ||||||
|  | #	endif | ||||||
| #	ifndef ccast | #	ifndef ccast | ||||||
| #	define ccast( type, value ) ( const_cast< type >( (value) ) ) | #	define ccast( type, value ) ( const_cast< type >( (value) ) ) | ||||||
| #	endif | #	endif | ||||||
| @@ -35,6 +35,23 @@ | |||||||
| #	ifndef scast | #	ifndef scast | ||||||
| #	define scast( type, value ) static_cast< type >( value ) | #	define scast( type, value ) static_cast< type >( value ) | ||||||
| #	endif | #	endif | ||||||
|  | #else | ||||||
|  | #	ifndef cast | ||||||
|  | #	define cast( type, value )  ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef ccast | ||||||
|  | #	define ccast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef pcast | ||||||
|  | #	define pcast( type, value ) ( * (type*)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef rcast | ||||||
|  | #	define rcast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef scast | ||||||
|  | #	define scast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifndef stringize | #ifndef stringize | ||||||
| #define stringize_va( ... ) #__VA_ARGS__ | #define stringize_va( ... ) #__VA_ARGS__ | ||||||
| @@ -72,6 +89,10 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef num_args_impl | #ifndef num_args_impl | ||||||
|  |  | ||||||
|  | // This is essentially an arg couneter version of GEN_SELECT_ARG macros | ||||||
|  | // See section : _Generic function overloading for that usage (explains this heavier case) | ||||||
|  |  | ||||||
| #define num_args_impl( _0,                                 \ | #define num_args_impl( _0,                                 \ | ||||||
| 		_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10,   \ | 		_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10,   \ | ||||||
| 		_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,  \ | 		_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,  \ | ||||||
| @@ -123,20 +144,20 @@ | |||||||
| #define min( a, b ) ( (a < b) ? (a) : (b) ) | #define min( a, b ) ( (a < b) ? (a) : (b) ) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined( _MSC_VER ) || defined( GEN_COMPILER_TINYC ) | #if GEN_COMPILER_MSVC || GEN_COMPILER_TINYC | ||||||
| #	define offset_of( Type, element ) ( ( GEN_NS( ssize ) ) & ( ( ( Type* )0 )->element ) ) | #	define offset_of( Type, element ) ( ( GEN_NS( ssize ) ) & ( ( ( Type* )0 )->element ) ) | ||||||
| #else | #else | ||||||
| #	define offset_of( Type, element ) __builtin_offsetof( Type, element ) | #	define offset_of( Type, element ) __builtin_offsetof( Type, element ) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef        forceinline | #ifndef        forceinline | ||||||
| #	ifdef GEN_COMPILER_MSVC | #	if GEN_COMPILER_MSVC | ||||||
| #		define forceinline __forceinline | #		define forceinline __forceinline | ||||||
| #		define neverinline __declspec( noinline ) | #		define neverinline __declspec( noinline ) | ||||||
| #	elif defined(GEN_COMPILER_GCC) | #	elif GEN_COMPILER_GCC | ||||||
| #		define forceinline inline __attribute__((__always_inline__)) | #		define forceinline inline __attribute__((__always_inline__)) | ||||||
| #		define neverinline __attribute__( ( __noinline__ ) ) | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
| #	elif defined(GEN_COMPILER_CLANG) | #	elif GEN_COMPILER_CLANG | ||||||
| #	if __has_attribute(__always_inline__) | #	if __has_attribute(__always_inline__) | ||||||
| #		define forceinline inline __attribute__((__always_inline__)) | #		define forceinline inline __attribute__((__always_inline__)) | ||||||
| #		define neverinline __attribute__( ( __noinline__ ) ) | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
| @@ -151,11 +172,11 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef        neverinline | #ifndef        neverinline | ||||||
| #	ifdef GEN_COMPILER_MSVC | #	if GEN_COMPILER_MSVC | ||||||
| #		define neverinline __declspec( noinline ) | #		define neverinline __declspec( noinline ) | ||||||
| #	elif defined(GEN_COMPILER_GCC) | #	elif GEN_COMPILER_GCC | ||||||
| #		define neverinline __attribute__( ( __noinline__ ) ) | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
| #	elif defined(GEN_COMPILER_CLANG) | #	elif GEN_COMPILER_CLANG | ||||||
| #	if __has_attribute(__always_inline__) | #	if __has_attribute(__always_inline__) | ||||||
| #		define neverinline __attribute__( ( __noinline__ ) ) | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
| #	else | #	else | ||||||
| @@ -166,4 +187,212 @@ | |||||||
| #	endif | #	endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #ifndef static_assert | ||||||
|  | #undef  static_assert | ||||||
|  |     #if GEN_COMPILER_C && __STDC_VERSION__ >= 201112L | ||||||
|  |         #define static_assert(condition, message) _Static_assert(condition, message) | ||||||
|  |     #else | ||||||
|  |         #define static_assert(condition, message) typedef char static_assertion_##__LINE__[(condition)?1:-1] | ||||||
|  | 	#endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP | ||||||
|  | // Already Defined | ||||||
|  | #elif GEN_COMPILER_C && __STDC_VERSION__ >= 201112L | ||||||
|  | #	define thread_local _Thread_local | ||||||
|  | #elif GEN_COMPILER_MSVC | ||||||
|  | #	define thread_local __declspec(thread) | ||||||
|  | #elif GEN_COMPILER_CLANG | ||||||
|  | #	define thread_local __thread | ||||||
|  | #else | ||||||
|  | #	error "No thread local support" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if !defined(GEN_SUPPORT_CPP_REFERENCES) | ||||||
|  | #	define   GEN_SUPPORT_CPP_REFERENCES 1 | ||||||
|  | #endif | ||||||
|  | #if GEN_COMPILER_C && defined(GEN_SUPPORT_CPP_REFERENCES) | ||||||
|  | #	undef  GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | #	define GEN_SUPPORT_CPP_REFERENCES 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if !defined(GEN_SUPPORT_CPP_MEMBER_FEATURES) | ||||||
|  | #	define   GEN_SUPPORT_CPP_MEMBER_FEATURES 1 | ||||||
|  | #endif | ||||||
|  | #if GEN_COMPILER_C && defined(GEN_SUPPORT_CPP_MEMBER_FEATURES) | ||||||
|  | #	undef  GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #	define GEN_SUPPORT_CPP_MEMBER_FEATURES 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ! defined(typeof) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L) | ||||||
|  | #	if ! GEN_COMPILER_C | ||||||
|  | #		define typeof decltype | ||||||
|  | #	elif defined(_MSC_VER) | ||||||
|  | #		define typeof(x) __typeof__(x) | ||||||
|  | #	elif defined(__GNUC__) || defined(__clang__) | ||||||
|  | #		define typeof(x) __typeof__(x) | ||||||
|  | #	else | ||||||
|  | #		error "Compiler not supported" | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef GEN_API_C_BEGIN | ||||||
|  | #	if GEN_COMPILER_C || (GEN_COMPILER_CPP && GEN_SUPPORT_CPP_REFERENCES) | ||||||
|  | #		define GEN_API_C_BEGIN | ||||||
|  | #		define GEN_API_C_END | ||||||
|  | #	else | ||||||
|  | #		define GEN_API_C_BEGIN extern "C" { | ||||||
|  | #		define GEN_API_C_END } | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #	if __STDC_VERSION__ >= 202311L | ||||||
|  | #		define enum_underlying(type) : type | ||||||
|  | #	else | ||||||
|  | #		define enum_underlying(type) | ||||||
|  | #   endif | ||||||
|  | #else | ||||||
|  | #	define enum_underlying(type) : type | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #	ifndef nullptr | ||||||
|  | #		define nullptr NULL | ||||||
|  | #	endif | ||||||
|  |  | ||||||
|  | #	ifndef GEN_REMOVE_PTR | ||||||
|  | #		define GEN_REMOVE_PTR(type) typeof(* ( (type) NULL) ) | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ! defined(GEN_PARAM_DEFAULT) && GEN_COMPILER_CPP | ||||||
|  | #	define GEN_PARAM_DEFAULT = {} | ||||||
|  | #else | ||||||
|  | #	define GEN_PARAM_DEFAULT | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP | ||||||
|  |     #define struct_init(type, value) {value} | ||||||
|  | #else | ||||||
|  |     #define struct_init(type, value) {value} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #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. | ||||||
|  |  | ||||||
|  | // Where the signature would be defined using: | ||||||
|  | #define GEN_TYPE_TO_EXP(type) (* (type*)NULL) | ||||||
|  |  | ||||||
|  | #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. | ||||||
|  |  | ||||||
|  | // Helper macros for argument selection | ||||||
|  | #define GEN_SELECT_ARG_1( _1, ... ) _1 // <-- Of all th args passed pick _1. | ||||||
|  | #define GEN_SELECT_ARG_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2. | ||||||
|  | #define GEN_SELECT_ARG_3( _1, _2, _3, ... ) _3 // etc.. (by induction until _8, which we don't support any more beyond) | ||||||
|  | // #define GEN_SELECT_ARG_4( _1, _2, _3, _4, ... ) _4 | ||||||
|  | // #define GEN_SELECT_ARG_5( _1, _2, _3, _4, _5, ... ) _5 | ||||||
|  | // #define GEN_SELECT_ARG_6( _1, _2, _3, _4, _5, _6, ... ) _6 | ||||||
|  | // #define GEN_SELECT_ARG_7( _1, _2, _3, _4, _5, _6, _7, ... ) _7 | ||||||
|  | // #define GEN_SELECT_ARG_8( _1, _2, _3, _4, _5, _6, _7, _8, ... ) _8 | ||||||
|  |  | ||||||
|  | #define GEN_GENERIC_SEL_ENTRY_TYPE             GEN_SELECT_ARG_1 // Use the arg expansion macro to select arg 1 which should have the type. | ||||||
|  | #define GEN_GENERIC_SEL_ENTRY_FUNCTION         GEN_SELECT_ARG_2 // Use the arg expansion macro to select arg 2 which should have the function. | ||||||
|  | #define GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER  GEN_SELECT_ARG_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','. | ||||||
|  |  | ||||||
|  | #define GEN_RESOLVED_FUNCTION_CALL // Just used to indicate where the call "occurs" | ||||||
|  |  | ||||||
|  | // ---------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  | // GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( macro ) includes a _Generic slot only if the specified macro is defined (as type, function_name). | ||||||
|  | // It takes advantage of the fact that if the macro is defined, then the expanded text will contain a comma. | ||||||
|  | // Expands to ',' if it can find (type): (function) <comma_operator: ',' > | ||||||
|  | // Where GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER is specifically looking for that <comma> , | ||||||
|  | #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 | ||||||
|  | // 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. | ||||||
|  | #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, ), , ) | ||||||
|  | // Needed for the last slot as they don't allow trailing commas. | ||||||
|  | // ---------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | // Below are generated on demand for an overlaod depdendent on a type: | ||||||
|  | // ---------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  | #define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic(         \ | ||||||
|  | (selector_arg), /* Select Via Expression*/                             \ | ||||||
|  |   /* 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 )     \ | ||||||
|  |   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 ) | ||||||
|  | // ---------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | // Then each definiton of a function has an associated define: | ||||||
|  | // #define <function_id_macro> GEN_GENERIC_FUNCTION_ARG_SIGNATURE( <function_id>, <arguments> ) | ||||||
|  | #define GEN_GENERIC_FUNCTION_ARG_SIGNATURE( name_of_function, type_delimiter ) type_delimiter name_of_function | ||||||
|  |  | ||||||
|  | // Then somehwere later on | ||||||
|  | // <etc> <return_type> <function_id> ( <arguments> ) { <implementation> } | ||||||
|  |  | ||||||
|  | // Concrete example: | ||||||
|  |  | ||||||
|  | // To add support for long: | ||||||
|  | #define GEN_EXAMPLE_HASH__ARGS_SIG_1 GEN_GENERIC_FUNCTION_ARG_SIGNATURE( hash__P_long, long long ) | ||||||
|  | size_t gen_example_hash__P_long( long val ) { return val * 2654435761ull; } | ||||||
|  |  | ||||||
|  | // To add support for long long: | ||||||
|  | #define GEN_EXAMPLE_HASH__ARGS_SIG_2 GEN_GENERIC_FUNCTION_ARG_SIGNATURE( hash__P_long_long, long long ) | ||||||
|  | size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761ull; } | ||||||
|  |  | ||||||
|  | // 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. | ||||||
|  | #define hash( function_arguments ) _Generic(                      \ | ||||||
|  | (function_arguments), /* Select Via Expression*/                  \ | ||||||
|  |   /* Extendibility slots: */                                      \ | ||||||
|  |   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_3 )      \ | ||||||
|  |   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_6 )      \ | ||||||
|  |   GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 )      \ | ||||||
|  |   GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( HASH__ARGS_SIG_8 ) \ | ||||||
|  | ) GEN_RESOLVED_FUNCTION_CALL( function_arguments ) | ||||||
|  |  | ||||||
|  | // Additional Variations: | ||||||
|  |  | ||||||
|  | // If the function takes more than one argument the following is used: | ||||||
|  | #define GEN_FUNCTION_GENERIC_EXAMPLE_VARADIC( selector_arg, ... ) _Generic( \ | ||||||
|  | (selector_arg),                                                             \ | ||||||
|  | 	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_LAST(FunctionID__ARGS_SIG_N )    \ | ||||||
|  | ) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ ) | ||||||
|  |  | ||||||
|  | // If the function does not take the arugment as a parameter: | ||||||
|  | #define GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( selector_arg ) _Generic( \ | ||||||
|  | ( GEN_TYPE_TO_EXP(selector_arg) ),                                         \ | ||||||
|  | 	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_LAST(FunctionID__ARGS_SIG_N )   \ | ||||||
|  | ) GEN_RESOLVED_FUNCTION_CALL() | ||||||
|  |  | ||||||
|  | // typedef void* GEN_GenericExampleType; | ||||||
|  | // GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType ); | ||||||
|  | // END OF ------------------------ _Generic function overloading ----------------------------------------- END OF | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Macros | #pragma endregion Macros | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Memory | #pragma region Memory | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| void* mem_copy( void* dest, void const* source, ssize n ) | void* mem_copy( void* dest, void const* source, ssize n ) | ||||||
| { | { | ||||||
| @@ -334,7 +335,7 @@ ssize virtual_memory_page_size( ssize* alignment_out ) | |||||||
|  |  | ||||||
| #pragma endregion VirtualMemory | #pragma endregion VirtualMemory | ||||||
|  |  | ||||||
| void* Arena::allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | void* arena_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	Arena* arena = rcast(Arena*, allocator_data); | 	Arena* arena = rcast(Arena*, allocator_data); | ||||||
| 	void*      ptr   = NULL; | 	void*      ptr   = NULL; | ||||||
| @@ -346,7 +347,7 @@ void* Arena::allocator_proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| 		case EAllocation_ALLOC : | 		case EAllocation_ALLOC : | ||||||
| 			{ | 			{ | ||||||
| 				void* end        = pointer_add( arena->PhysicalStart, arena->TotalUsed ); | 				void* end        = pointer_add( arena->PhysicalStart, arena->TotalUsed ); | ||||||
| 				ssize    total_size = align_forward_i64( size, alignment ); | 				ssize total_size = align_forward_s64( size, alignment ); | ||||||
|  |  | ||||||
| 				// NOTE: Out of memory | 				// NOTE: Out of memory | ||||||
| 				if ( arena->TotalUsed + total_size > (ssize) arena->TotalSize ) | 				if ( arena->TotalUsed + total_size > (ssize) arena->TotalSize ) | ||||||
| @@ -384,7 +385,7 @@ void* Arena::allocator_proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| 	return ptr; | 	return ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| void* Pool::allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | void* pool_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	Pool* pool = rcast( Pool*, allocator_data); | 	Pool* pool = rcast( Pool*, allocator_data); | ||||||
| 	void* ptr  = NULL; | 	void* ptr  = NULL; | ||||||
| @@ -457,7 +458,7 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, ssize size, ss | |||||||
| 	return ptr; | 	return ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| Pool Pool::init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align ) | Pool pool_init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align ) | ||||||
| { | { | ||||||
| 	Pool pool = {}; | 	Pool pool = {}; | ||||||
|  |  | ||||||
| @@ -495,16 +496,16 @@ Pool Pool::init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size | |||||||
| 	return pool; | 	return pool; | ||||||
| } | } | ||||||
|  |  | ||||||
| void Pool::clear() | void pool_clear(Pool* pool) | ||||||
| { | { | ||||||
| 	ssize actual_block_size, block_index; | 	ssize actual_block_size, block_index; | ||||||
| 	void* curr; | 	void* curr; | ||||||
| 	uptr* end; | 	uptr* end; | ||||||
|  |  | ||||||
| 	actual_block_size = BlockSize + BlockAlign; | 	actual_block_size = pool->BlockSize + pool->BlockAlign; | ||||||
|  |  | ||||||
| 	curr = PhysicalStart; | 	curr = pool->PhysicalStart; | ||||||
| 	for ( block_index = 0; block_index < NumBlocks - 1; block_index++ ) | 	for ( block_index = 0; block_index < pool->NumBlocks - 1; block_index++ ) | ||||||
| 	{ | 	{ | ||||||
| 		uptr* next = ( uptr* ) curr; | 		uptr* next = ( uptr* ) curr; | ||||||
| 		*next      = ( uptr  ) curr + actual_block_size; | 		*next      = ( uptr  ) curr + actual_block_size; | ||||||
| @@ -514,7 +515,8 @@ void Pool::clear() | |||||||
| 	end  =  ( uptr* ) curr; | 	end  =  ( uptr* ) curr; | ||||||
| 	*end =  ( uptr )  NULL; | 	*end =  ( uptr )  NULL; | ||||||
|  |  | ||||||
| 	FreeList = PhysicalStart; | 	pool->FreeList = pool->PhysicalStart; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Memory | #pragma endregion Memory | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ void swap( Type& a, Type& b ) | |||||||
| 	b = tmp; | 	b = tmp; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| //! Checks if value is power of 2. | //! Checks if value is power of 2. | ||||||
| b32 is_power_of_two( ssize x ); | b32 is_power_of_two( ssize x ); | ||||||
|  |  | ||||||
| @@ -29,7 +31,7 @@ b32 is_power_of_two( ssize x ); | |||||||
| void* align_forward( void* ptr, ssize alignment ); | void* align_forward( void* ptr, ssize alignment ); | ||||||
|  |  | ||||||
| //! Aligns value to a specified alignment. | //! Aligns value to a specified alignment. | ||||||
| s64 align_forward_i64( s64 value, ssize alignment ); | s64 align_forward_by_value( s64 value, ssize alignment ); | ||||||
|  |  | ||||||
| //! Moves pointer forward by bytes. | //! Moves pointer forward by bytes. | ||||||
| void* pointer_add( void* ptr, ssize bytes ); | void* pointer_add( void* ptr, ssize bytes ); | ||||||
| @@ -62,24 +64,23 @@ void zero_size( void* ptr, ssize size ); | |||||||
| //! Clears up an array. | //! Clears up an array. | ||||||
| #define zero_array( a, count ) zero_size( ( a ), size_of( *( a ) ) * count ) | #define zero_array( a, count ) zero_size( ( a ), size_of( *( a ) ) * count ) | ||||||
|  |  | ||||||
| enum AllocType : u8 | enum AllocType_Def //enum_underlying(u8) | ||||||
| { | { | ||||||
| 	EAllocation_ALLOC, | 	EAllocation_ALLOC, | ||||||
| 	EAllocation_FREE, | 	EAllocation_FREE, | ||||||
| 	EAllocation_FREE_ALL, | 	EAllocation_FREE_ALL, | ||||||
| 	EAllocation_RESIZE, | 	EAllocation_RESIZE, | ||||||
| }; | }; | ||||||
|  | typedef enum AllocType_Def AllocType; | ||||||
|  |  | ||||||
| using AllocatorProc = void* ( void* allocator_data, AllocType type | typedef void*(AllocatorProc)( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); | ||||||
| 	, ssize size, ssize alignment |  | ||||||
| 	, void* old_memory, ssize old_size |  | ||||||
| 	, u64 flags ); |  | ||||||
|  |  | ||||||
| struct AllocatorInfo | struct AllocatorInfo_Def | ||||||
| { | { | ||||||
| 	AllocatorProc* Proc; | 	AllocatorProc* Proc; | ||||||
| 	void*          Data; | 	void*          Data; | ||||||
| }; | }; | ||||||
|  | typedef struct AllocatorInfo_Def AllocatorInfo; | ||||||
|  |  | ||||||
| enum AllocFlag | enum AllocFlag | ||||||
| { | { | ||||||
| @@ -101,7 +102,7 @@ void* alloc( AllocatorInfo a, ssize size ); | |||||||
| void* alloc_align( AllocatorInfo a, ssize size, ssize alignment ); | void* alloc_align( AllocatorInfo a, ssize size, ssize alignment ); | ||||||
|  |  | ||||||
| //! Free allocated memory. | //! Free allocated memory. | ||||||
| void free( AllocatorInfo a, void* ptr ); | void allocator_free( AllocatorInfo a, void* ptr ); | ||||||
|  |  | ||||||
| //! Free all memory allocated by an allocator. | //! Free all memory allocated by an allocator. | ||||||
| void free_all( AllocatorInfo a ); | void free_all( AllocatorInfo a ); | ||||||
| @@ -135,7 +136,7 @@ void* default_resize_align( AllocatorInfo a, void* ptr, ssize old_size, ssize ne | |||||||
| void* heap_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); | void* heap_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); | ||||||
|  |  | ||||||
| //! The heap allocator backed by operating system's memory manager. | //! The heap allocator backed by operating system's memory manager. | ||||||
| constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; } | constexpr AllocatorInfo heap( void ) { AllocatorInfo allocator = { heap_allocator_proc, nullptr }; return allocator; } | ||||||
|  |  | ||||||
| //! Helper to allocate memory using heap allocator. | //! Helper to allocate memory using heap allocator. | ||||||
| #define malloc( sz ) alloc( heap(), sz ) | #define malloc( sz ) alloc( heap(), sz ) | ||||||
| @@ -143,11 +144,12 @@ constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; | |||||||
| //! Helper to free memory allocated by heap allocator. | //! Helper to free memory allocated by heap allocator. | ||||||
| #define mfree( ptr ) free( heap(), ptr ) | #define mfree( ptr ) free( heap(), ptr ) | ||||||
|  |  | ||||||
| struct VirtualMemory | struct VirtualMemory_Def | ||||||
| { | { | ||||||
| 	void*  data; | 	void*  data; | ||||||
| 	ssize size; | 	ssize size; | ||||||
| }; | }; | ||||||
|  | typedef struct VirtualMemory_Def VirtualMemory; | ||||||
|  |  | ||||||
| //! Initialize virtual memory from existing data. | //! Initialize virtual memory from existing data. | ||||||
| VirtualMemory vm_from_memory( void* data, ssize size ); | VirtualMemory vm_from_memory( void* data, ssize size ); | ||||||
| @@ -165,34 +167,100 @@ b32 vm_free( VirtualMemory vm ); | |||||||
| VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ); | VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ); | ||||||
|  |  | ||||||
| //! Purge virtual memory. | //! Purge virtual memory. | ||||||
| b32 gen_vm_purge( VirtualMemory vm ); | b32 vm_purge( VirtualMemory vm ); | ||||||
|  |  | ||||||
| //! Retrieve VM's page size and alignment. | //! Retrieve VM's page size and alignment. | ||||||
| ssize gen_virtual_memory_page_size( ssize* alignment_out ); | ssize virtual_memory_page_size( ssize* alignment_out ); | ||||||
|  |  | ||||||
| struct Arena | #pragma region Arena | ||||||
| { | struct Arena_Def; | ||||||
| 	static | typedef struct Arena_Def Arena; | ||||||
| 	void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); |  | ||||||
|  |  | ||||||
| 	static | AllocatorInfo arena_allocator_info( Arena* arena ); | ||||||
| 	Arena init_from_memory( void* start, ssize size ) |  | ||||||
|  | // Remove static keyword and rename allocator_proc | ||||||
|  | void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags); | ||||||
|  |  | ||||||
|  | // Add these declarations after the Arena struct | ||||||
|  | Arena arena_init_from_allocator(AllocatorInfo backing, ssize size); | ||||||
|  | Arena arena_init_from_memory   ( void* start, ssize size ); | ||||||
|  |  | ||||||
|  | Arena arena_init_sub      (Arena* parent, ssize size); | ||||||
|  | ssize arena_alignment_of  (Arena* arena, ssize alignment); | ||||||
|  | void  arena_check         (Arena* arena); | ||||||
|  | void  arena_free          (Arena* arena); | ||||||
|  | ssize arena_size_remaining(Arena* arena, ssize alignment); | ||||||
|  |  | ||||||
|  | struct Arena_Def | ||||||
| { | { | ||||||
| 		return | 	AllocatorInfo Backing; | ||||||
|  | 	void*         PhysicalStart; | ||||||
|  | 	ssize         TotalSize; | ||||||
|  | 	ssize         TotalUsed; | ||||||
|  | 	ssize         TempCount; | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline operator AllocatorInfo() { return GEN_NS arena_allocator_info(this); } | ||||||
|  |  | ||||||
|  | 	forceinline static void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) { return GEN_NS arena_allocator_proc( allocator_data, type, size, alignment, old_memory, old_size, flags ); } | ||||||
|  | 	forceinline static Arena init_from_memory( void* start, ssize size )                                                                                      { return GEN_NS arena_init_from_memory( start, size ); } | ||||||
|  | 	forceinline static Arena init_from_allocator( AllocatorInfo backing, ssize size )                                                                         { return GEN_NS arena_init_from_allocator( backing, size ); } | ||||||
|  | 	forceinline static Arena init_sub( Arena& parent, ssize size )                                                                                            { return GEN_NS arena_init_from_allocator( parent.Backing, size ); } | ||||||
|  | 	forceinline        ssize alignment_of( ssize alignment )                                                                                                  { return GEN_NS arena_alignment_of(this, alignment); } | ||||||
|  | 	forceinline        void  free()                                                                                                                           { return GEN_NS arena_free(this);  } | ||||||
|  | 	forceinline        ssize size_remaining( ssize alignment )                                                                                                { return GEN_NS arena_size_remaining(this, alignment); } | ||||||
|  |  | ||||||
|  | // This id is defined by Unreal for asserts | ||||||
|  | #pragma push_macro("check") | ||||||
|  | #undef check | ||||||
|  | 	forceinline void check() { GEN_NS arena_check(this); } | ||||||
|  | #pragma pop_macro("check") | ||||||
|  |  | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | GEN_API_C_END | ||||||
|  | forceinline AllocatorInfo allocator_info(Arena& arena )                 { return arena_allocator_info(& arena); } | ||||||
|  | forceinline Arena         init_sub      (Arena& parent, ssize size)     { return arena_init_sub( & parent, size); } | ||||||
|  | forceinline ssize         alignment_of  (Arena& arena, ssize alignment) { return arena_alignment_of( & arena, alignment); } | ||||||
|  | forceinline void          free          (Arena& arena)                  { return arena_free(& arena); } | ||||||
|  | forceinline ssize         size_remaining(Arena& arena, ssize alignment) { return arena_size_remaining(& arena, alignment); } | ||||||
|  |  | ||||||
|  | // This id is defined by Unreal for asserts | ||||||
|  | #pragma push_macro("check") | ||||||
|  | #undef check | ||||||
|  | forceinline void check(Arena& arena) { return arena_check(& arena); }; | ||||||
|  | #pragma pop_macro("check") | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | AllocatorInfo arena_allocator_info( Arena* arena ) { | ||||||
|  | 	GEN_ASSERT(arena != nullptr); | ||||||
|  | 	AllocatorInfo info = { arena_allocator_proc, arena }; | ||||||
|  | 	return info; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | Arena arena_init_from_memory( void* start, ssize size ) | ||||||
| { | { | ||||||
|  | 	Arena arena = { | ||||||
| 		{ nullptr, nullptr }, | 		{ nullptr, nullptr }, | ||||||
| 		start, | 		start, | ||||||
| 		size, | 		size, | ||||||
| 		0, | 		0, | ||||||
| 		0 | 		0 | ||||||
| 	}; | 	}; | ||||||
|  | 	return arena; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	Arena init_from_allocator( AllocatorInfo backing, ssize size ) | Arena arena_init_from_allocator(AllocatorInfo backing, ssize size) { | ||||||
| 	{ | 	Arena result = { | ||||||
| 		Arena result = |  | ||||||
| 		{ |  | ||||||
| 		backing, | 		backing, | ||||||
| 		alloc(backing, size), | 		alloc(backing, size), | ||||||
| 		size, | 		size, | ||||||
| @@ -202,19 +270,21 @@ struct Arena | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	Arena init_sub( Arena& parent, ssize size ) | Arena arena_init_sub(Arena* parent, ssize size) { | ||||||
| 	{ | 	GEN_ASSERT(parent != nullptr); | ||||||
| 		return init_from_allocator( parent.Backing, size ); | 	return arena_init_from_allocator(parent->Backing, size); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	ssize alignment_of( ssize alignment ) | inline | ||||||
|  | ssize arena_alignment_of(Arena* arena, ssize alignment) | ||||||
| { | { | ||||||
|  | 	GEN_ASSERT(arena != nullptr); | ||||||
| 	ssize alignment_offset, result_pointer, mask; | 	ssize alignment_offset, result_pointer, mask; | ||||||
| 	GEN_ASSERT(is_power_of_two(alignment)); | 	GEN_ASSERT(is_power_of_two(alignment)); | ||||||
|  |  | ||||||
| 	alignment_offset = 0; | 	alignment_offset = 0; | ||||||
| 		result_pointer   = (ssize) PhysicalStart + TotalUsed; | 	result_pointer  = (ssize)arena->PhysicalStart + arena->TotalUsed; | ||||||
| 	mask            = alignment - 1; | 	mask            = alignment - 1; | ||||||
|  |  | ||||||
| 	if (result_pointer & mask) | 	if (result_pointer & mask) | ||||||
| @@ -223,68 +293,88 @@ struct Arena | |||||||
| 	return alignment_offset; | 	return alignment_offset; | ||||||
| } | } | ||||||
|  |  | ||||||
| // This id is defined by Unreal for asserts | inline | ||||||
| #pragma push_macro("check") | void arena_check(Arena* arena) | ||||||
| #undef check |  | ||||||
| 	void check() |  | ||||||
| { | { | ||||||
| 		GEN_ASSERT( TempCount == 0 ); |     GEN_ASSERT(arena != nullptr ); | ||||||
|  |     GEN_ASSERT(arena->TempCount == 0); | ||||||
| } | } | ||||||
| #pragma pop_macro("check") |  | ||||||
|  |  | ||||||
| 	void free() | inline | ||||||
|  | void arena_free(Arena* arena) | ||||||
| { | { | ||||||
| 		if ( Backing.Proc ) | 	GEN_ASSERT(arena != nullptr); | ||||||
|  | 	if (arena->Backing.Proc) | ||||||
| 	{ | 	{ | ||||||
| 			gen::free( Backing, PhysicalStart ); | 		allocator_free(arena->Backing, arena->PhysicalStart); | ||||||
| 			PhysicalStart = nullptr; | 		arena->PhysicalStart = nullptr; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 	ssize size_remaining( ssize alignment ) | inline | ||||||
|  | ssize arena_size_remaining(Arena* arena, ssize alignment) | ||||||
| { | { | ||||||
| 		ssize result = TotalSize - ( TotalUsed + alignment_of( alignment ) ); | 	GEN_ASSERT(arena != nullptr); | ||||||
|  | 	ssize result = arena->TotalSize - (arena->TotalUsed + arena_alignment_of(arena, alignment)); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  | #pragma endregion Arena | ||||||
|  |  | ||||||
| 	AllocatorInfo Backing; | GEN_API_C_END | ||||||
| 	void*         PhysicalStart; |  | ||||||
| 	ssize            TotalSize; |  | ||||||
| 	ssize            TotalUsed; |  | ||||||
| 	ssize            TempCount; |  | ||||||
|  |  | ||||||
| 	operator AllocatorInfo() | #pragma region FixedArena | ||||||
| 	{ | template<s32 Size> | ||||||
| 		return { allocator_proc, this }; | struct FixedArena; | ||||||
| 	} |  | ||||||
| }; | template<s32 Size> FixedArena<Size> fixed_arena_init(); | ||||||
|  | template<s32 Size> AllocatorInfo    fixed_arena_allocator_info(FixedArena<Size>* fixed_arena ); | ||||||
|  | template<s32 Size> ssize            fixed_arena_size_remaining(FixedArena<Size>* fixed_arena, ssize alignment); | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | template<s32 Size> AllocatorInfo    allocator_info( FixedArena<Size>& fixed_arena )                { return allocator_info(& fixed_arena); } | ||||||
|  | template<s32 Size> ssize            size_remaining(FixedArena<Size>& fixed_arena, ssize alignment) { return size_remaining( & fixed_arena, alignment); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Just a wrapper around using an arena with memory associated with its scope instead of from an allocator. | // Just a wrapper around using an arena with memory associated with its scope instead of from an allocator. | ||||||
| // Used for static segment or stack allocations. | // Used for static segment or stack allocations. | ||||||
| template< s32 Size > | template< s32 Size > | ||||||
| struct FixedArena | struct FixedArena | ||||||
| { | { | ||||||
| 	static |  | ||||||
| 	FixedArena init() |  | ||||||
| 	{ |  | ||||||
| 		FixedArena result = { Arena::init_from_memory( result.memory, Size ), {0} }; |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ssize size_remaining( ssize alignment ) |  | ||||||
| 	{ |  | ||||||
| 		return arena.size_remaining( alignment ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator AllocatorInfo() |  | ||||||
| 	{ |  | ||||||
| 		return { Arena::allocator_proc, &arena }; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Arena arena; |  | ||||||
| 	char  memory[Size]; | 	char  memory[Size]; | ||||||
|  | 	Arena arena; | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); } | ||||||
|  |  | ||||||
|  | 	forceinline static FixedArena init()                          { FixedArena result; GEN_NS fixed_arena_init<Size>(result); return result; } | ||||||
|  | 	forceinline ssize             size_remaining(ssize alignment) { GEN_NS size_remaining(this, alignment); } | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | AllocatorInfo fixed_arena_allocator_info( FixedArena<Size>* fixed_arena ) { | ||||||
|  | 	GEN_ASSERT(fixed_arena); | ||||||
|  | 	return { arena_allocator_proc, & fixed_arena->arena }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | void fixed_arena_init(FixedArena<Size>* result) { | ||||||
|  |     zero_size(& result->memory[0], Size); | ||||||
|  |     result->arena = arena_init_from_memory(& result->memory[0], Size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | void fixed_arena_free(FixedArena<Size>* fixed_arena) { | ||||||
|  | 	arena_free( & fixed_arena->arena); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | ssize fixed_arena_size_remaining(FixedArena<Size>* fixed_arena, ssize alignment) { | ||||||
|  |     return size_remaining(fixed_arena->arena, alignment); | ||||||
|  | } | ||||||
|  |  | ||||||
| using Arena_1KB   = FixedArena< kilobytes( 1 ) >; | using Arena_1KB   = FixedArena< kilobytes( 1 ) >; | ||||||
| using Arena_4KB   = FixedArena< kilobytes( 4 ) >; | using Arena_4KB   = FixedArena< kilobytes( 4 ) >; | ||||||
| using Arena_8KB   = FixedArena< kilobytes( 8 ) >; | using Arena_8KB   = FixedArena< kilobytes( 8 ) >; | ||||||
| @@ -297,31 +387,32 @@ using Arena_512KB = FixedArena< kilobytes( 512 ) >; | |||||||
| using Arena_1MB   = FixedArena< megabytes( 1 ) >; | using Arena_1MB   = FixedArena< megabytes( 1 ) >; | ||||||
| using Arena_2MB   = FixedArena< megabytes( 2 ) >; | using Arena_2MB   = FixedArena< megabytes( 2 ) >; | ||||||
| using Arena_4MB   = FixedArena< megabytes( 4 ) >; | using Arena_4MB   = FixedArena< megabytes( 4 ) >; | ||||||
|  | #pragma endregion FixedArena | ||||||
|  |  | ||||||
| struct Pool | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  | #pragma region Pool | ||||||
|  | struct Pool_Def; | ||||||
|  | typedef struct Pool_Def Pool; | ||||||
|  |  | ||||||
|  | void* pool_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags); | ||||||
|  |  | ||||||
|  | Pool          pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size); | ||||||
|  | Pool          pool_init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align); | ||||||
|  | AllocatorInfo pool_allocator_info(Pool* pool); | ||||||
|  | void          pool_clear(Pool* pool); | ||||||
|  | void          pool_free(Pool* pool); | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | GEN_API_C_END | ||||||
|  | AllocatorInfo allocator_info(Pool& pool) { return pool_allocator_info(& pool); } | ||||||
|  | void          clear(Pool& pool)          { return pool_clear(& pool); } | ||||||
|  | void          free(Pool& pool)           { return pool_free(& pool); } | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | struct Pool_Def | ||||||
| { | { | ||||||
| 	static |  | ||||||
| 	void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Pool init( AllocatorInfo backing, ssize num_blocks, ssize block_size ) |  | ||||||
| 	{ |  | ||||||
| 		return init_align( backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Pool init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align ); |  | ||||||
|  |  | ||||||
| 	void clear(); |  | ||||||
|  |  | ||||||
| 	void free() |  | ||||||
| 	{ |  | ||||||
| 		if ( Backing.Proc ) |  | ||||||
| 		{ |  | ||||||
| 			gen::free( Backing, PhysicalStart ); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	AllocatorInfo Backing; | 	AllocatorInfo Backing; | ||||||
| 	void*         PhysicalStart; | 	void*         PhysicalStart; | ||||||
| 	void*         FreeList; | 	void*         FreeList; | ||||||
| @@ -330,12 +421,37 @@ struct Pool | |||||||
| 	ssize         TotalSize; | 	ssize         TotalSize; | ||||||
| 	ssize         NumBlocks; | 	ssize         NumBlocks; | ||||||
|  |  | ||||||
| 	operator AllocatorInfo() | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	{ | #pragma region Member Mapping | ||||||
| 		return { allocator_proc, this }; |     forceinline operator AllocatorInfo() { return GEN_NS pool_allocator_info(this); } | ||||||
| 	} |  | ||||||
|  |     forceinline static void* allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags) { return GEN_NS pool_allocator_proc(allocator_data, type, size, alignment, old_memory, old_size, flags); } | ||||||
|  |     forceinline static Pool  init(AllocatorInfo backing, ssize num_blocks, ssize block_size)                                                                { return GEN_NS pool_init(backing, num_blocks, block_size); } | ||||||
|  |     forceinline static Pool  init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align)                                       { return GEN_NS pool_init_align(backing, num_blocks, block_size, block_align); } | ||||||
|  |     forceinline        void  clear() { GEN_NS pool_clear( this); } | ||||||
|  |     forceinline        void  free()  { GEN_NS pool_free( this); } | ||||||
|  | #pragma endregion | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | AllocatorInfo pool_allocator_info(Pool* pool) { | ||||||
|  | 	AllocatorInfo info = { pool_allocator_proc, pool }; | ||||||
|  | 	return info; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size) { | ||||||
|  |    return pool_init_align(backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void pool_free(Pool* pool) { | ||||||
|  |    if(pool->Backing.Proc) { | ||||||
|  |        allocator_free(pool->Backing, pool->PhysicalStart); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | #pragma endregion Pool | ||||||
|  |  | ||||||
| inline | inline | ||||||
| b32 is_power_of_two( ssize x ) { | b32 is_power_of_two( ssize x ) { | ||||||
| @@ -354,7 +470,7 @@ mem_ptr align_forward( void* ptr, ssize alignment ) | |||||||
| 	return to_mem_ptr(forward); | 	return to_mem_ptr(forward); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline s64 align_forward_i64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; } | inline s64 align_forward_s64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; } | ||||||
|  |  | ||||||
| inline void*       pointer_add      ( void*       ptr, ssize bytes ) { return rcast(void*,         rcast( u8*,        ptr) + bytes ); } | inline void*       pointer_add      ( void*       ptr, ssize bytes ) { return rcast(void*,         rcast( u8*,        ptr) + bytes ); } | ||||||
| inline void const* pointer_add_const( void const* ptr, ssize bytes ) { return rcast(void const*, rcast( u8 const*,  ptr) + bytes ); } | inline void const* pointer_add_const( void const* ptr, ssize bytes ) { return rcast(void const*, rcast( u8 const*,  ptr) + bytes ); } | ||||||
| @@ -512,7 +628,7 @@ void* alloc( AllocatorInfo a, ssize size ) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| void free( AllocatorInfo a, void* ptr ) { | void allocator_free( AllocatorInfo a, void* ptr ) { | ||||||
| 	if ( ptr != nullptr ) | 	if ( ptr != nullptr ) | ||||||
| 		a.Proc( a.Data, EAllocation_FREE, 0, 0, ptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | 		a.Proc( a.Data, EAllocation_FREE, 0, 0, ptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | ||||||
| } | } | ||||||
| @@ -540,7 +656,7 @@ void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, s | |||||||
|  |  | ||||||
| 	if ( new_size == 0 ) | 	if ( new_size == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		free( a, old_memory ); | 		allocator_free( a, old_memory ); | ||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -558,7 +674,7 @@ void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, s | |||||||
| 			return nullptr; | 			return nullptr; | ||||||
|  |  | ||||||
| 		mem_move( new_memory, old_memory, min( new_size, old_size ) ); | 		mem_move( new_memory, old_memory, min( new_size, old_size ) ); | ||||||
| 		free( a, old_memory ); | 		allocator_free( a, old_memory ); | ||||||
| 		return new_memory; | 		return new_memory; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -568,4 +684,6 @@ void zero_size( void* ptr, ssize size ) { | |||||||
| 	mem_set( ptr, 0, size ); | 	mem_set( ptr, 0, size ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Memory | #pragma endregion Memory | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| #ifdef GEN_INTELLISENSE_DIRECTIVES | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
| #	pragma once | #	pragma once | ||||||
|  | #	include "parsing.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region ADT | #pragma region ADT | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| #define _adt_fprintf( s_, fmt_, ... )                      \ | #define _adt_fprintf( s_, fmt_, ... )                      \ | ||||||
| 	do                                                     \ | 	do                                                     \ | ||||||
| @@ -23,7 +25,7 @@ u8 adt_make_branch( ADT_Node* node, AllocatorInfo backing, char const* name, b32 | |||||||
| 	node->type   = type; | 	node->type   = type; | ||||||
| 	node->name   = name; | 	node->name   = name; | ||||||
| 	node->parent = parent; | 	node->parent = parent; | ||||||
| 	node->nodes  = Array<ADT_Node>::init( backing ); | 	node->nodes  = array_init<ADT_Node>( backing ); | ||||||
|  |  | ||||||
| 	if ( ! node->nodes ) | 	if ( ! node->nodes ) | ||||||
| 		return EADT_ERROR_OUT_OF_MEMORY; | 		return EADT_ERROR_OUT_OF_MEMORY; | ||||||
| @@ -36,12 +38,12 @@ u8 adt_destroy_branch( ADT_Node* node ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node ); | 	GEN_ASSERT_NOT_NULL( node ); | ||||||
| 	if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes ) | 	if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( ssize i = 0; i < scast(ssize, node->nodes.num()); ++i ) | 		for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); ++i ) | ||||||
| 		{ | 		{ | ||||||
| 			adt_destroy_branch( node->nodes + i ); | 			adt_destroy_branch( node->nodes + i ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		node->nodes.free(); | 		array_free(node->nodes); | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @@ -66,7 +68,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search ) | |||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) | 	for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | ||||||
| 		{ | 		{ | ||||||
| @@ -76,7 +78,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search ) | |||||||
|  |  | ||||||
| 	if ( deep_search ) | 	if ( deep_search ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) | 		for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ ) | ||||||
| 		{ | 		{ | ||||||
| 			ADT_Node* res = adt_find( node->nodes + i, name, deep_search ); | 			ADT_Node* res = adt_find( node->nodes + i, name, deep_search ); | ||||||
|  |  | ||||||
| @@ -132,7 +134,7 @@ internal ADT_Node* _adt_get_value( ADT_Node* node, char const* value ) | |||||||
|  |  | ||||||
| internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value ) | internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value ) | ||||||
| { | { | ||||||
| 	for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) | 	for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | ||||||
| 		{ | 		{ | ||||||
| @@ -207,7 +209,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 			/* run a value comparison against any child that is an object node */ | 			/* run a value comparison against any child that is an object node */ | ||||||
| 			else if ( node->type == EADT_TYPE_ARRAY ) | 			else if ( node->type == EADT_TYPE_ARRAY ) | ||||||
| 			{ | 			{ | ||||||
| 				for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) | 				for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ ) | ||||||
| 				{ | 				{ | ||||||
| 					ADT_Node* child = &node->nodes[ i ]; | 					ADT_Node* child = &node->nodes[ i ]; | ||||||
| 					if ( child->type != EADT_TYPE_OBJECT ) | 					if ( child->type != EADT_TYPE_OBJECT ) | ||||||
| @@ -225,7 +227,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 		/* [value] */ | 		/* [value] */ | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) | 			for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ ) | ||||||
| 			{ | 			{ | ||||||
| 				ADT_Node* child = &node->nodes[ i ]; | 				ADT_Node* child = &node->nodes[ i ]; | ||||||
| 				if ( _adt_get_value( child, l_b2 ) ) | 				if ( _adt_get_value( child, l_b2 ) ) | ||||||
| @@ -257,7 +259,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		ssize idx = ( ssize )str_to_i64( buf, NULL, 10 ); | 		ssize idx = ( ssize )str_to_i64( buf, NULL, 10 ); | ||||||
| 		if ( idx >= 0 && idx < scast(ssize, node->nodes.num()) ) | 		if ( idx >= 0 && idx < scast(ssize, array_num(node->nodes)) ) | ||||||
| 		{ | 		{ | ||||||
| 			found_node = &node->nodes[ idx ]; | 			found_node = &node->nodes[ idx ]; | ||||||
|  |  | ||||||
| @@ -282,15 +284,16 @@ ADT_Node* adt_alloc_at( ADT_Node* parent, ssize index ) | |||||||
| 	if ( ! parent->nodes ) | 	if ( ! parent->nodes ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	if ( index < 0 || index > scast(ssize, parent->nodes.num()) ) | 	if ( index < 0 || index > scast(ssize, array_num(parent->nodes)) ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	ADT_Node o = { 0 }; | 	ADT_Node o = { 0 }; | ||||||
| 	o.parent   = parent; | 	o.parent   = parent; | ||||||
| 	if ( ! parent->nodes.append_at( o, index ) ) | 	if ( ! array_append_at( parent->nodes, o, index ) ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	return parent->nodes + index; | 	ADT_Node* node = & parent->nodes[index]; | ||||||
|  | 	return node; | ||||||
| } | } | ||||||
|  |  | ||||||
| ADT_Node* adt_alloc( ADT_Node* parent ) | ADT_Node* adt_alloc( ADT_Node* parent ) | ||||||
| @@ -303,7 +306,7 @@ ADT_Node* adt_alloc( ADT_Node* parent ) | |||||||
| 	if ( ! parent->nodes ) | 	if ( ! parent->nodes ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	return adt_alloc_at( parent, parent->nodes.num() ); | 	return adt_alloc_at( parent, array_num(parent->nodes) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing ) | b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing ) | ||||||
| @@ -357,7 +360,7 @@ ADT_Node* adt_move_node( ADT_Node* node, ADT_Node* new_parent ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node ); | 	GEN_ASSERT_NOT_NULL( node ); | ||||||
| 	GEN_ASSERT_NOT_NULL( new_parent ); | 	GEN_ASSERT_NOT_NULL( new_parent ); | ||||||
| 	GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT ); | 	GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT ); | ||||||
| 	return adt_move_node_at( node, new_parent, new_parent->nodes.num() ); | 	return adt_move_node_at( node, new_parent, array_num(new_parent->nodes) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node ) | void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node ) | ||||||
| @@ -381,7 +384,7 @@ void adt_remove_node( ADT_Node* node ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node->parent ); | 	GEN_ASSERT_NOT_NULL( node->parent ); | ||||||
| 	ADT_Node* parent = node->parent; | 	ADT_Node* parent = node->parent; | ||||||
| 	ssize        index  = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | 	ssize        index  = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | ||||||
| 	parent->nodes.remove_at( index ); | 	array_remove_at( parent->nodes, index ); | ||||||
| } | } | ||||||
|  |  | ||||||
| ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) | ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) | ||||||
| @@ -389,7 +392,7 @@ ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) | |||||||
| 	ADT_Node* o = adt_alloc( parent ); | 	ADT_Node* o = adt_alloc( parent ); | ||||||
| 	if ( ! o ) | 	if ( ! o ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if ( adt_set_obj( o, name, parent->nodes.get_header()->Allocator ) ) | 	if ( adt_set_obj( o, name, array_get_header(parent->nodes)->Allocator ) ) | ||||||
| 	{ | 	{ | ||||||
| 		adt_remove_node( o ); | 		adt_remove_node( o ); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -402,7 +405,9 @@ ADT_Node* adt_append_arr( ADT_Node* parent, char const* name ) | |||||||
| 	ADT_Node* o = adt_alloc( parent ); | 	ADT_Node* o = adt_alloc( parent ); | ||||||
| 	if ( ! o ) | 	if ( ! o ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if ( adt_set_arr( o, name, parent->nodes.get_header()->Allocator ) ) |  | ||||||
|  | 	ArrayHeader* node_header = array_get_header(parent->nodes); | ||||||
|  | 	if ( adt_set_arr( o, name, node_header->Allocator ) ) | ||||||
| 	{ | 	{ | ||||||
| 		adt_remove_node( o ); | 		adt_remove_node( o ); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -447,7 +452,7 @@ char* adt_parse_number_strict( ADT_Node* node, char* base_str ) | |||||||
| 	while ( *e ) | 	while ( *e ) | ||||||
| 		++e; | 		++e; | ||||||
|  |  | ||||||
| 	while ( *p && ( str_find( "eE.+-", *p ) || char_is_hex_digit( *p ) ) ) | 	while ( *p && ( char_first_occurence( "eE.+-", *p ) || char_is_hex_digit( *p ) ) ) | ||||||
| 	{ | 	{ | ||||||
| 		++p; | 		++p; | ||||||
| 	} | 	} | ||||||
| @@ -476,7 +481,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
| 	u8        node_props = 0; | 	u8        node_props = 0; | ||||||
|  |  | ||||||
| 	/* skip false positives and special cases */ | 	/* skip false positives and special cases */ | ||||||
| 	if ( ! ! str_find( "eE", *p ) || ( ! ! str_find( ".+-", *p ) && ! char_is_hex_digit( *( p + 1 ) ) && *( p + 1 ) != '.' ) ) | 	if ( ! ! char_first_occurence( "eE", *p ) || ( ! ! char_first_occurence( ".+-", *p ) && ! char_is_hex_digit( *( p + 1 ) ) && *( p + 1 ) != '.' ) ) | ||||||
| 	{ | 	{ | ||||||
| 		return ++base_str; | 		return ++base_str; | ||||||
| 	} | 	} | ||||||
| @@ -507,7 +512,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! str_compare( e, "0x", 2 ) || ! str_compare( e, "0X", 2 ) ) | 		if ( ! str_compare_len( e, "0x", 2 ) || ! str_compare_len( e, "0X", 2 ) ) | ||||||
| 		{ | 		{ | ||||||
| 			node_props = EADT_PROPS_IS_HEX; | 			node_props = EADT_PROPS_IS_HEX; | ||||||
| 		} | 		} | ||||||
| @@ -552,7 +557,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
| 	char expbuf[ 6 ] = { 0 }; | 	char expbuf[ 6 ] = { 0 }; | ||||||
| 	ssize   expi        = 0; | 	ssize   expi        = 0; | ||||||
|  |  | ||||||
| 	if ( *e && ! ! str_find( "eE", *e ) ) | 	if ( *e && ! ! char_first_occurence( "eE", *e ) ) | ||||||
| 	{ | 	{ | ||||||
| 		++e; | 		++e; | ||||||
| 		if ( *e == '+' || *e == '-' || char_is_digit( *e ) ) | 		if ( *e == '+' || *e == '-' || char_is_digit( *e ) ) | ||||||
| @@ -748,7 +753,7 @@ ADT_Error adt_print_string( FileInfo* file, ADT_Node* node, char const* escaped_ | |||||||
| 	{ | 	{ | ||||||
| 		p = str_skip_any( p, escaped_chars ); | 		p = str_skip_any( p, escaped_chars ); | ||||||
| 		_adt_fprintf( file, "%.*s", pointer_diff( b, p ), b ); | 		_adt_fprintf( file, "%.*s", pointer_diff( b, p ), b ); | ||||||
| 		if ( *p && ! ! str_find( escaped_chars, *p ) ) | 		if ( *p && ! ! char_first_occurence( escaped_chars, *p ) ) | ||||||
| 		{ | 		{ | ||||||
| 			_adt_fprintf( file, "%s%c", escape_symbol, *p ); | 			_adt_fprintf( file, "%s%c", escape_symbol, *p ); | ||||||
| 			p++; | 			p++; | ||||||
| @@ -946,12 +951,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( columnIndex >= scast(ssize, root->nodes.num()) ) | 		if ( columnIndex >= scast(ssize, array_num(root->nodes)) ) | ||||||
| 		{ | 		{ | ||||||
| 			adt_append_arr( root, NULL ); | 			adt_append_arr( root, NULL ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		root->nodes[ columnIndex ].nodes.append( rowItem ); | 		array_append( root->nodes[ columnIndex ].nodes, rowItem ); | ||||||
|  |  | ||||||
| 		if ( delimiter == delim ) | 		if ( delimiter == delim ) | ||||||
| 		{ | 		{ | ||||||
| @@ -979,7 +984,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 	} | 	} | ||||||
| 	while ( *currentChar ); | 	while ( *currentChar ); | ||||||
|  |  | ||||||
| 	if ( root->nodes.num() == 0 ) | 	if (array_num( root->nodes) == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		GEN_CSV_ASSERT( "unexpected end of input. stream is empty." ); | 		GEN_CSV_ASSERT( "unexpected end of input. stream is empty." ); | ||||||
| 		error = ECSV_Error__UNEXPECTED_END_OF_INPUT; | 		error = ECSV_Error__UNEXPECTED_END_OF_INPUT; | ||||||
| @@ -989,12 +994,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 	/* consider first row as a header. */ | 	/* consider first row as a header. */ | ||||||
| 	if ( has_header ) | 	if ( has_header ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( ssize i = 0; i < scast(ssize, root->nodes.num()); i++ ) | 		for ( ssize i = 0; i < scast(ssize, array_num(root->nodes)); i++ ) | ||||||
| 		{ | 		{ | ||||||
| 			CSV_Object* col = root->nodes + i; | 			CSV_Object* col = root->nodes + i; | ||||||
| 			CSV_Object* hdr = col->nodes; | 			CSV_Object* hdr = col->nodes; | ||||||
| 			col->name       = hdr->string; | 			col->name       = hdr->string; | ||||||
| 			col->nodes.remove_at( 0 ); | 			array_remove_at(col->nodes, 0 ); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1057,11 +1062,11 @@ void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delimiter ) | |||||||
| 	GEN_ASSERT_NOT_NULL( file ); | 	GEN_ASSERT_NOT_NULL( file ); | ||||||
| 	GEN_ASSERT_NOT_NULL( obj ); | 	GEN_ASSERT_NOT_NULL( obj ); | ||||||
| 	GEN_ASSERT( obj->nodes ); | 	GEN_ASSERT( obj->nodes ); | ||||||
| 	ssize cols = obj->nodes.num(); | 	ssize cols = array_num(obj->nodes); | ||||||
| 	if ( cols == 0 ) | 	if ( cols == 0 ) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	ssize rows = obj->nodes[ 0 ].nodes.num(); | 	ssize rows = array_num(obj->nodes[ 0 ].nodes); | ||||||
| 	if ( rows == 0 ) | 	if ( rows == 0 ) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| @@ -1102,10 +1107,10 @@ String csv_write_string_delimiter( AllocatorInfo a, CSV_Object* obj, char delimi | |||||||
|  |  | ||||||
| 	ssize  fsize; | 	ssize  fsize; | ||||||
| 	u8*    buf    = file_stream_buf( &tmp, &fsize ); | 	u8*    buf    = file_stream_buf( &tmp, &fsize ); | ||||||
| 	String output = String::make_length( a, ( char* )buf, fsize ); | 	String output = string_make_length( a, ( char* )buf, fsize ); | ||||||
| 	file_close( &tmp ); | 	file_close( &tmp ); | ||||||
| 	return output; | 	return output; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion CSV | #pragma endregion CSV | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region ADT | #pragma region ADT | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| enum ADT_Type : u32 | enum ADT_Type : u32 | ||||||
| { | { | ||||||
| @@ -83,7 +84,7 @@ struct ADT_Node | |||||||
| 	union | 	union | ||||||
| 	{ | 	{ | ||||||
| 		char const*     string; | 		char const*     string; | ||||||
| 		Array<ADT_Node> nodes;    ///< zpl_array | 		Array(ADT_Node) nodes;    ///< zpl_array | ||||||
|  |  | ||||||
| 		struct | 		struct | ||||||
| 		{ | 		{ | ||||||
| @@ -429,4 +430,5 @@ String csv_write_string( AllocatorInfo a, CSV_Object* obj ) | |||||||
| 	return csv_write_string_delimiter( a, obj, ',' ); | 	return csv_write_string_delimiter( a, obj, ',' ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion CSV | #pragma endregion CSV | ||||||
|   | |||||||
| @@ -76,13 +76,18 @@ | |||||||
| /* Platform compiler */ | /* Platform compiler */ | ||||||
|  |  | ||||||
| #if defined( _MSC_VER ) | #if defined( _MSC_VER ) | ||||||
|  | #	define GEN_COMPILER_CLANG 0 | ||||||
| #	define GEN_COMPILER_MSVC  1 | #	define GEN_COMPILER_MSVC  1 | ||||||
|  | #	define GEN_COMPILER_GCC   0 | ||||||
| #elif defined( __GNUC__ ) | #elif defined( __GNUC__ ) | ||||||
|  | #	define GEN_COMPILER_CLANG 0 | ||||||
|  | #	define GEN_COMPILER_MSVC  0 | ||||||
| #	define GEN_COMPILER_GCC   1 | #	define GEN_COMPILER_GCC   1 | ||||||
| #elif defined( __clang__ ) | #elif defined( __clang__ ) | ||||||
| #	define GEN_COMPILER_CLANG 1 | #	define GEN_COMPILER_CLANG 1 | ||||||
| #elif defined( __MINGW32__ ) | #	define GEN_COMPILER_MSVC  0 | ||||||
| #	define GEN_COMPILER_MINGW 1 | #	define GEN_COMPILER_GCC   1 | ||||||
|  | #else | ||||||
| #	error Unknown compiler | #	error Unknown compiler | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -101,6 +106,26 @@ | |||||||
| #  define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) | #  define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if !defined(GEN_COMPILER_C) | ||||||
|  | #	ifdef __cplusplus | ||||||
|  | #		define GEN_COMPILER_C   0 | ||||||
|  | #		define GEN_COMPILER_CPP 1 | ||||||
|  | #	else | ||||||
|  | #		if defined(__STDC__) | ||||||
|  | #			define GEN_COMPILER_C   1 | ||||||
|  | #		    define GEN_COMPILER_CPP 0 | ||||||
|  | #		else | ||||||
|  |             // Fallback for very old C compilers | ||||||
|  | #			define GEN_COMPILER_C   1 | ||||||
|  | #		    define GEN_COMPILER_CPP 0 | ||||||
|  | #		endif | ||||||
|  | #   endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #pragma message("GENCPP: Detected C") | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Platform Detection | #pragma endregion Platform Detection | ||||||
|  |  | ||||||
| #pragma region Mandatory Includes | #pragma region Mandatory Includes | ||||||
| @@ -112,13 +137,36 @@ | |||||||
| #		include <intrin.h> | #		include <intrin.h> | ||||||
| #	endif | #	endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #include <assert.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Mandatory Includes | #pragma endregion Mandatory Includes | ||||||
|  |  | ||||||
| #ifdef GEN_DONT_USE_NAMESPACE | #if GEN_DONT_USE_NAMESPACE || GEN_COMPILER_C | ||||||
|  | #	if GEN_COMPILER_C | ||||||
|  | #		define GEN_NS_PARSER_BEGIN | ||||||
|  | #		define GEN_NS_PARSER_END | ||||||
|  | #		define GEN_USING_NS_PARSER | ||||||
|  | #		define GEN_NS_PARSER | ||||||
| #		define GEN_NS | #		define GEN_NS | ||||||
| #		define GEN_NS_BEGIN | #		define GEN_NS_BEGIN | ||||||
| #		define GEN_NS_END | #		define GEN_NS_END | ||||||
| #	else | #	else | ||||||
|  | #		define GEN_NS_PARSER_BEGIN namespace parser { | ||||||
|  | #		define GEN_NS_PARSER_END   } | ||||||
|  | #		define GEN_USING_NS_PARSER using namespace parser | ||||||
|  | #		define GEN_NS_PARSER       parser:: | ||||||
|  | #		define GEN_NS              :: | ||||||
|  | #		define GEN_NS_BEGIN | ||||||
|  | #		define GEN_NS_END | ||||||
|  | #	endif | ||||||
|  | #else | ||||||
|  | #	define GEN_NS_PARSER_BEGIN namespace parser { | ||||||
|  | #	define GEN_NS_PARSER_END   } | ||||||
|  | #	define GEN_NS_PARSER       parser:: | ||||||
|  | #	define GEN_USING_NS_PARSER using namespace parser | ||||||
| #	define GEN_NS              gen:: | #	define GEN_NS              gen:: | ||||||
| #	define GEN_NS_BEGIN        namespace gen { | #	define GEN_NS_BEGIN        namespace gen { | ||||||
| #	define GEN_NS_END          } | #	define GEN_NS_END          } | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Printing | #pragma region Printing | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| enum | enum | ||||||
| { | { | ||||||
| @@ -420,9 +421,18 @@ neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_lis | |||||||
|  |  | ||||||
| 			case 'S': | 			case 'S': | ||||||
| 			{ | 			{ | ||||||
|  | 				if ( *(fmt + 1) == 'C' ) | ||||||
|  | 				{ | ||||||
|  | 					++ fmt; | ||||||
|  | 					StrC gen_str   = va_arg( va, StrC); | ||||||
|  | 					info.precision = gen_str.Len; | ||||||
|  | 					len            = _print_string( text, remaining, &info, gen_str.Ptr ); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				String gen_str = String { va_arg( va, char*) }; | 				String gen_str = String { va_arg( va, char*) }; | ||||||
|  |  | ||||||
| 				info.precision = gen_str.length(); | 				info.precision = string_length(gen_str); | ||||||
| 				len            = _print_string( text, remaining, &info, gen_str ); | 				len            = _print_string( text, remaining, &info, gen_str ); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| @@ -540,7 +550,7 @@ char* str_fmt_buf( char const* fmt, ... ) | |||||||
| 	return str; | 	return str; | ||||||
| } | } | ||||||
|  |  | ||||||
| ssize str_fmt_file_va( struct FileInfo* f, char const* fmt, va_list va ) | ssize str_fmt_file_va( FileInfo* f, char const* fmt, va_list va ) | ||||||
| { | { | ||||||
| 	local_persist thread_local char buf[ GEN_PRINTF_MAXLEN ]; | 	local_persist thread_local char buf[ GEN_PRINTF_MAXLEN ]; | ||||||
| 	ssize                              len = str_fmt_va( buf, size_of( buf ), fmt, va ); | 	ssize                              len = str_fmt_va( buf, size_of( buf ), fmt, va ); | ||||||
| @@ -548,7 +558,7 @@ ssize str_fmt_file_va( struct FileInfo* f, char const* fmt, va_list va ) | |||||||
| 	return res ? len : -1; | 	return res ? len : -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| ssize str_fmt_file( struct FileInfo* f, char const* fmt, ... ) | ssize str_fmt_file( FileInfo* f, char const* fmt, ... ) | ||||||
| { | { | ||||||
| 	ssize      res; | 	ssize      res; | ||||||
| 	va_list va; | 	va_list va; | ||||||
| @@ -588,4 +598,5 @@ ssize str_fmt_out_err( char const* fmt, ... ) | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Printing | #pragma endregion Printing | ||||||
|   | |||||||
| @@ -5,11 +5,14 @@ | |||||||
|  |  | ||||||
| #pragma region Printing | #pragma region Printing | ||||||
|  |  | ||||||
| struct FileInfo; | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  | typedef struct FileInfo_Def FileInfo; | ||||||
|  |  | ||||||
| #ifndef GEN_PRINTF_MAXLEN | #ifndef GEN_PRINTF_MAXLEN | ||||||
| #	define GEN_PRINTF_MAXLEN kilobytes(128) | #	define GEN_PRINTF_MAXLEN kilobytes(128) | ||||||
| #endif | #endif | ||||||
|  | typedef char PrintF_Buffer[GEN_PRINTF_MAXLEN]; | ||||||
|  |  | ||||||
| // NOTE: A locally persisting buffer is used internally | // NOTE: A locally persisting buffer is used internally | ||||||
| char*  str_fmt_buf       ( char const* fmt, ... ); | char*  str_fmt_buf       ( char const* fmt, ... ); | ||||||
| @@ -38,4 +41,6 @@ ssize log_fmt(char const* fmt, ...) | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Printing | #pragma endregion Printing | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region String Ops | #pragma region String Ops | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| internal | internal | ||||||
| ssize _scan_zpl_i64( const char* text, s32 base, s64* value ) | ssize _scan_zpl_i64( const char* text, s32 base, s64* value ) | ||||||
| @@ -19,7 +20,7 @@ ssize _scan_zpl_i64( const char* text, s32 base, s64* value ) | |||||||
| 		text++; | 		text++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( base == 16 && str_compare( text, "0x", 2 ) == 0 ) | 	if ( base == 16 && str_compare_len( text, "0x", 2 ) == 0 ) | ||||||
| 		text += 2; | 		text += 2; | ||||||
|  |  | ||||||
| 	for ( ;; ) | 	for ( ;; ) | ||||||
| @@ -61,7 +62,7 @@ s64 str_to_i64( const char* str, char** end_ptr, s32 base ) | |||||||
|  |  | ||||||
| 	if ( ! base ) | 	if ( ! base ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ( str_len( str ) > 2 ) && ( str_compare( str, "0x", 2 ) == 0 ) ) | 		if ( ( str_len( str ) > 2 ) && ( str_compare_len( str, "0x", 2 ) == 0 ) ) | ||||||
| 			base = 16; | 			base = 16; | ||||||
| 		else | 		else | ||||||
| 			base = 10; | 			base = 10; | ||||||
| @@ -212,4 +213,5 @@ f64 str_to_f64( const char* str, char** end_ptr ) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion String Ops | #pragma endregion String Ops | ||||||
|   | |||||||
| @@ -5,8 +5,9 @@ | |||||||
|  |  | ||||||
| #pragma region String Ops | #pragma region String Ops | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| const char* char_first_occurence( const char* str, char c ); | const char* char_first_occurence( const char* str, char c ); | ||||||
| constexpr auto str_find = &char_first_occurence; |  | ||||||
|  |  | ||||||
| b32   char_is_alpha( char c ); | b32   char_is_alpha( char c ); | ||||||
| b32   char_is_alphanumeric( char c ); | b32   char_is_alphanumeric( char c ); | ||||||
| @@ -20,11 +21,11 @@ s32  digit_to_int( char c ); | |||||||
| s32  hex_digit_to_int( char c ); | s32  hex_digit_to_int( char c ); | ||||||
|  |  | ||||||
| s32         str_compare( const char* s1, const char* s2 ); | s32         str_compare( const char* s1, const char* s2 ); | ||||||
| s32         str_compare( const char* s1, const char* s2, ssize len ); | s32         str_compare_len( const char* s1, const char* s2, ssize len ); | ||||||
| char*       str_copy( char* dest, const char* source, ssize len ); | char*       str_copy( char* dest, const char* source, ssize len ); | ||||||
| ssize       str_copy_nulpad( char* dest, const char* source, ssize len ); | ssize       str_copy_nulpad( char* dest, const char* source, ssize len ); | ||||||
| ssize       str_len( const char* str ); | ssize       str_len( const char* str ); | ||||||
| ssize       str_len( const char* str, ssize max_len ); | ssize       str_len_capped( const char* str, ssize max_len ); | ||||||
| char*       str_reverse( char* str );    // NOTE: ASCII only | char*       str_reverse( char* str );    // NOTE: ASCII only | ||||||
| char const* str_skip( char const* str, char c ); | char const* str_skip( char const* str, char c ); | ||||||
| char const* str_skip_any( char const* str, char const* char_list ); | char const* str_skip_any( char const* str, char const* char_list ); | ||||||
| @@ -133,7 +134,7 @@ s32 str_compare( const char* s1, const char* s2 ) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| s32 str_compare( const char* s1, const char* s2, ssize len ) | s32 str_compare_len( const char* s1, const char* s2, ssize len ) | ||||||
| { | { | ||||||
| 	for ( ; len > 0; s1++, s2++, len-- ) | 	for ( ; len > 0; s1++, s2++, len-- ) | ||||||
| 	{ | 	{ | ||||||
| @@ -205,7 +206,7 @@ ssize str_len( const char* str ) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| ssize str_len( const char* str, ssize max_len ) | ssize str_len_capped( const char* str, ssize max_len ) | ||||||
| { | { | ||||||
| 	const char* end = rcast(const char*, mem_find( str, 0, max_len )); | 	const char* end = rcast(const char*, mem_find( str, 0, max_len )); | ||||||
| 	if ( end ) | 	if ( end ) | ||||||
| @@ -241,7 +242,7 @@ char const* str_skip( char const* str, char c ) | |||||||
| inline | inline | ||||||
| char const* str_skip_any( char const* str, char const* char_list ) | char const* str_skip_any( char const* str, char const* char_list ) | ||||||
| { | { | ||||||
| 	char const* closest_ptr     = rcast( char const*, pointer_add_const( rcast(void const*, str), str_len( str ) )); | 	char const* closest_ptr     = rcast( char const*, pointer_add_const( rcast(mem_ptr_const, str), str_len( str ) )); | ||||||
| 	ssize       char_list_count = str_len( char_list ); | 	ssize       char_list_count = str_len( char_list ); | ||||||
| 	for ( ssize i = 0; i < char_list_count; i++ ) | 	for ( ssize i = 0; i < char_list_count; i++ ) | ||||||
| 	{ | 	{ | ||||||
| @@ -285,4 +286,6 @@ void str_to_upper( char* str ) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion String Ops | #pragma endregion String Ops | ||||||
|   | |||||||
| @@ -4,20 +4,11 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region String | #pragma region String | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| String String::fmt( AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ... ) | String string_make_length( AllocatorInfo allocator, char const* str, ssize length ) | ||||||
| { | { | ||||||
| 	va_list va; | 	constexpr ssize header_size = sizeof( StringHeader ); | ||||||
| 	va_start( va, fmt ); |  | ||||||
| 	str_fmt_va( buf, buf_size, fmt, va ); |  | ||||||
| 	va_end( va ); |  | ||||||
|  |  | ||||||
| 	return make( allocator, buf ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| String String::make_length( AllocatorInfo allocator, char const* str, ssize length ) |  | ||||||
| { |  | ||||||
| 	constexpr ssize header_size = sizeof( Header ); |  | ||||||
|  |  | ||||||
| 	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 ); | ||||||
| @@ -25,8 +16,8 @@ String String::make_length( AllocatorInfo allocator, char const* str, ssize leng | |||||||
| 	if ( allocation == nullptr ) | 	if ( allocation == nullptr ) | ||||||
| 		return { nullptr }; | 		return { nullptr }; | ||||||
|  |  | ||||||
| 	Header& | 	StringHeader& | ||||||
| 	header = * rcast(Header*, allocation); | 	header = * rcast(StringHeader*, allocation); | ||||||
| 	header = { allocator, length, length }; | 	header = { allocator, length, length }; | ||||||
|  |  | ||||||
| 	String  result = { rcast( char*, allocation) + header_size }; | 	String  result = { rcast( char*, allocation) + header_size }; | ||||||
| @@ -41,9 +32,9 @@ String String::make_length( AllocatorInfo allocator, char const* str, ssize leng | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| String String::make_reserve( AllocatorInfo allocator, ssize capacity ) | String string_make_reserve( AllocatorInfo allocator, ssize capacity ) | ||||||
| { | { | ||||||
| 	constexpr ssize header_size = sizeof( Header ); | 	constexpr ssize 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 ); | ||||||
| @@ -53,8 +44,8 @@ String String::make_reserve( AllocatorInfo allocator, ssize capacity ) | |||||||
|  |  | ||||||
| 	mem_set( allocation, 0, alloc_size ); | 	mem_set( allocation, 0, alloc_size ); | ||||||
|  |  | ||||||
| 	Header* | 	StringHeader* | ||||||
| 		header            = rcast(Header*, allocation); | 	header            = rcast(StringHeader*, allocation); | ||||||
| 	header->Allocator = allocator; | 	header->Allocator = allocator; | ||||||
| 	header->Capacity  = capacity; | 	header->Capacity  = capacity; | ||||||
| 	header->Length    = 0; | 	header->Length    = 0; | ||||||
| @@ -63,68 +54,5 @@ String String::make_reserve( AllocatorInfo allocator, ssize capacity ) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| String String::fmt_buf( AllocatorInfo allocator, char const* fmt, ... ) | GEN_API_C_END | ||||||
| { |  | ||||||
| 	local_persist thread_local |  | ||||||
| 	char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; |  | ||||||
|  |  | ||||||
| 	va_list va; |  | ||||||
| 	va_start( va, fmt ); |  | ||||||
| 	str_fmt_va( buf, GEN_PRINTF_MAXLEN, fmt, va ); |  | ||||||
| 	va_end( va ); |  | ||||||
|  |  | ||||||
| 	return make( allocator, buf ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool String::append_fmt( char const* fmt, ... ) |  | ||||||
| { |  | ||||||
| 	ssize   res; |  | ||||||
| 	char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; |  | ||||||
|  |  | ||||||
| 	va_list va; |  | ||||||
| 	va_start( va, fmt ); |  | ||||||
| 	res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1; |  | ||||||
| 	va_end( va ); |  | ||||||
|  |  | ||||||
| 	return append( buf, res ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool String::make_space_for( char const* str, ssize add_len ) |  | ||||||
| { |  | ||||||
| 	ssize available = avail_space(); |  | ||||||
|  |  | ||||||
| 	// NOTE: Return if there is enough space left |  | ||||||
| 	if ( available >= add_len ) |  | ||||||
| 	{ |  | ||||||
| 		return true; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		ssize new_len, old_size, new_size; |  | ||||||
|  |  | ||||||
| 		void* ptr; |  | ||||||
| 		void* new_ptr; |  | ||||||
|  |  | ||||||
| 		AllocatorInfo allocator = get_header().Allocator; |  | ||||||
| 		Header*       header	= nullptr; |  | ||||||
|  |  | ||||||
| 		new_len  = grow_formula( length() + add_len ); |  | ||||||
| 		ptr      = & get_header(); |  | ||||||
| 		old_size = size_of( Header ) + length() + 1; |  | ||||||
| 		new_size = size_of( Header ) + new_len + 1; |  | ||||||
|  |  | ||||||
| 		new_ptr = resize( allocator, ptr, old_size, new_size ); |  | ||||||
|  |  | ||||||
| 		if ( new_ptr == nullptr ) |  | ||||||
| 			return false; |  | ||||||
|  |  | ||||||
| 		header            = rcast( Header*, new_ptr); |  | ||||||
| 		header->Allocator = allocator; |  | ||||||
| 		header->Capacity  = new_len; |  | ||||||
|  |  | ||||||
| 		Data = rcast( char*, header + 1 ); |  | ||||||
|  |  | ||||||
| 		return true; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| #pragma endregion String | #pragma endregion String | ||||||
|   | |||||||
| @@ -5,255 +5,619 @@ | |||||||
|  |  | ||||||
| #pragma region Strings | #pragma region Strings | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  | struct StrC_Def; | ||||||
|  | typedef struct StrC_Def StrC; | ||||||
|  |  | ||||||
|  | bool        strc_are_equal           (StrC lhs, StrC rhs); | ||||||
|  | char const* strc_back                (StrC str); | ||||||
|  | bool        strc_contains            (StrC str, StrC substring); | ||||||
|  | StrC        strc_duplicate           (StrC str, AllocatorInfo allocator); | ||||||
|  | b32         strc_starts_with         (StrC str, StrC substring); | ||||||
|  | StrC        strc_to_str              (char const* bad_string); | ||||||
|  | StrC        strc_visualize_whitespace(StrC str, AllocatorInfo allocator); | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| // Constant string with length. | // Constant string with length. | ||||||
| struct StrC | struct StrC_Def | ||||||
| { | { | ||||||
| 	ssize       Len; | 	ssize       Len; | ||||||
| 	char const* Ptr; | 	char const* Ptr; | ||||||
|  |  | ||||||
| 	operator char const* ()               const { return Ptr; } | #if GEN_COMPILER_CPP | ||||||
| 	char const& operator[]( ssize index ) const { return Ptr[index]; } | 	forceinline operator char const* ()               const { return Ptr; } | ||||||
|  | 	forceinline char const& operator[]( ssize index ) const { return Ptr[index]; } | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | 	forceinline bool        is_equal            (StrC rhs)                const { return GEN_NS strc_are_equal(* this, rhs); } | ||||||
|  | 	forceinline char const* back                ()                        const { return GEN_NS strc_back(* this); } | ||||||
|  | 	forceinline bool        contains            (StrC substring)          const { return GEN_NS strc_contains(* this, substring); } | ||||||
|  | 	forceinline StrC        duplicate           (AllocatorInfo allocator) const { return GEN_NS strc_duplicate(* this, allocator); } | ||||||
|  | 	forceinline b32         starts_with         (StrC substring)          const { return GEN_NS strc_starts_with(* this, substring); } | ||||||
|  | 	forceinline StrC        visualize_whitespace(AllocatorInfo allocator) const { return GEN_NS strc_visualize_whitespace(* this, allocator); } | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) ) | #define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) ) | ||||||
|  |  | ||||||
|  | #ifndef txt | ||||||
|  | #	if GEN_COMPILER_CPP | ||||||
| #		define txt( text )          StrC { sizeof( text ) - 1, ( text ) } | #		define txt( text )          StrC { sizeof( text ) - 1, ( text ) } | ||||||
|  | #	else | ||||||
|  | #		define txt( text )         (StrC){ sizeof( text ) - 1, ( text ) } | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  | forceinline char const* strc_begin(StrC str)                   { return str.Ptr; } | ||||||
|  | forceinline char const* strc_end  (StrC str)                   { return str.Ptr + str.Len; } | ||||||
|  | forceinline char const* strc_next (StrC str, char const* iter) { return iter + 1; } | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP | ||||||
|  | forceinline char const* begin(StrC str)                   { return str.Ptr; } | ||||||
|  | forceinline char const* end  (StrC str)                   { return str.Ptr + str.Len; } | ||||||
|  | forceinline char const* next (StrC str, char const* iter) { return iter + 1; } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| inline | inline | ||||||
| StrC to_str( char const* str ) | bool strc_are_equal(StrC lhs, StrC rhs) | ||||||
| { | { | ||||||
| 	return { str_len( str ), str }; | 	if (lhs.Len != rhs.Len) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx < lhs.Len; ++idx) | ||||||
|  | 		if (lhs.Ptr[idx] != rhs.Ptr[idx]) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | char const* strc_back(StrC str) { | ||||||
|  | 	return & str.Ptr[str.Len - 1]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool strc_contains(StrC str, StrC substring) | ||||||
|  | { | ||||||
|  | 	if (substring.Len > str.Len) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	ssize main_len = str.Len; | ||||||
|  | 	ssize sub_len  = substring.Len; | ||||||
|  | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
|  | 	{ | ||||||
|  | 		if (str_compare_len(str.Ptr + idx, substring.Ptr, sub_len) == 0) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 strc_starts_with(StrC str, StrC substring) { | ||||||
|  | 	if (substring.Len > str.Len) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	b32 result = str_compare_len(str.Ptr, substring.Ptr, substring.Len) == 0; | ||||||
|  | 		return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | StrC to_strc_from_c_str( char const* bad_str ) { | ||||||
|  | 	StrC result = { str_len( bad_str ), bad_str }; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| // Dynamic String | // Dynamic String | ||||||
| // This is directly based off the ZPL string api. | // This is directly based off the ZPL string api. | ||||||
| // They used a header pattern | // They used a header pattern | ||||||
| // I kept it for simplicty of porting but its not necessary to keep it that way. | // I kept it for simplicty of porting but its not necessary to keep it that way. | ||||||
| struct String | #pragma region String | ||||||
| { |         struct StringHeader_Def; | ||||||
| 	struct Header | typedef struct StringHeader_Def StringHeader; | ||||||
| 	{ |  | ||||||
|  | #if GEN_COMPILER_C || ! GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | typedef char* String; | ||||||
|  | #else | ||||||
|  | struct String; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  | forceinline usize string_grow_formula(usize value); | ||||||
|  |  | ||||||
|  | String        string_make_c_str          (AllocatorInfo allocator, char const*  str); | ||||||
|  | String        string_make_strc           (AllocatorInfo allocator, StrC         str); | ||||||
|  | String        string_make_reserve        (AllocatorInfo allocator, ssize        capacity); | ||||||
|  | String        string_make_length         (AllocatorInfo allocator, char const*  str,   ssize length); | ||||||
|  | String        string_fmt                 (AllocatorInfo allocator, char*        buf,   ssize buf_size,  char const* fmt, ...); | ||||||
|  | String        string_fmt_buf             (AllocatorInfo allocator, char const*  fmt, ...); | ||||||
|  | String        string_join                (AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue); | ||||||
|  | bool          string_are_equal           (String const lhs, String const rhs); | ||||||
|  | bool          string_are_equal_strc      (String const lhs, StrC rhs); | ||||||
|  | bool          string_make_space_for      (String*      str, char const*  to_append, ssize add_len); | ||||||
|  | bool          string_append_char         (String*      str, char         c); | ||||||
|  | bool          string_append_c_str        (String*      str, char const*  str_to_append); | ||||||
|  | bool          string_append_c_str_len    (String*      str, char const*  str_to_append, ssize length); | ||||||
|  | bool          string_append_strc         (String*      str, StrC         str_to_append); | ||||||
|  | bool          string_append_string       (String*      str, String const other); | ||||||
|  | bool          string_append_fmt          (String*      str, char const*  fmt, ...); | ||||||
|  | ssize         string_avail_space         (String const str); | ||||||
|  | char*         string_back                (String       str); | ||||||
|  | bool          string_contains_strc       (String const str, StrC         substring); | ||||||
|  | bool          string_contains_string     (String const str, String const substring); | ||||||
|  | ssize         string_capacity            (String const str); | ||||||
|  | void          string_clear               (String       str); | ||||||
|  | String        string_duplicate           (String const str, AllocatorInfo allocator); | ||||||
|  | void          string_free                (String*      str); | ||||||
|  | StringHeader* string_get_header          (String       str); | ||||||
|  | ssize         string_length              (String const str); | ||||||
|  | b32           string_starts_with_strc    (String const str, StrC   substring); | ||||||
|  | b32           string_starts_with_string  (String const str, String substring); | ||||||
|  | void          string_skip_line           (String       str); | ||||||
|  | void          string_strip_space         (String       str); | ||||||
|  | StrC          string_to_strc             (String       str); | ||||||
|  | void          string_trim                (String       str, char const* cut_set); | ||||||
|  | void          string_trim_space          (String       str); | ||||||
|  | String        string_visualize_whitespace(String const str); | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
|  | struct StringHeader_Def { | ||||||
| 	AllocatorInfo Allocator; | 	AllocatorInfo Allocator; | ||||||
| 	ssize         Capacity; | 	ssize         Capacity; | ||||||
| 	ssize         Length; | 	ssize         Length; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| 	static | #if GEN_COMPILER_CPP && GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	usize grow_formula( usize value ) | struct String | ||||||
| { | { | ||||||
|  | 	char* Data; | ||||||
|  |  | ||||||
|  | 	forceinline operator char*()             { return Data; } | ||||||
|  | 	forceinline operator char const*() const { return Data; } | ||||||
|  | 	forceinline operator StrC()        const { return { string_length(* this), Data }; } | ||||||
|  |  | ||||||
|  | 	String const& operator=(String const& other) const { | ||||||
|  | 		if (this == &other) | ||||||
|  | 			return *this; | ||||||
|  |  | ||||||
|  | 		String* this_ = ccast(String*, this); | ||||||
|  | 		this_->Data = other.Data; | ||||||
|  |  | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	forceinline char&       operator[](ssize index)       { return Data[index]; } | ||||||
|  | 	forceinline char const& operator[](ssize index) const { return Data[index]; } | ||||||
|  |  | ||||||
|  | 	       forceinline bool operator==(std::nullptr_t) const             { return     Data == nullptr; } | ||||||
|  | 	       forceinline bool operator!=(std::nullptr_t) const             { return     Data != nullptr; } | ||||||
|  | 	friend forceinline bool operator==(std::nullptr_t, const String str) { return str.Data == nullptr; } | ||||||
|  | 	friend forceinline bool operator!=(std::nullptr_t, const String str) { return str.Data != nullptr; } | ||||||
|  |  | ||||||
|  | 	forceinline char* begin() const { return Data; } | ||||||
|  | 	forceinline char* end()   const { return Data + string_length(* this); } | ||||||
|  |  | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline static String make(AllocatorInfo allocator, char const* str)                { return string_make_c_str(allocator, str); } | ||||||
|  | 	forceinline static String make(AllocatorInfo allocator, StrC str)                       { return string_make_strc(allocator, str); } | ||||||
|  | 	forceinline static String make_reserve(AllocatorInfo allocator, ssize cap)              { return string_make_reserve(allocator, cap); } | ||||||
|  | 	forceinline static String make_length(AllocatorInfo a, char const* s, ssize l)          { return string_make_length(a, s, l); } | ||||||
|  | 	forceinline static String join(AllocatorInfo a, char const** p, ssize n, char const* g) { return string_join(a, p, n, g); } | ||||||
|  | 	forceinline static usize  grow_formula(usize value)                                     { return string_grow_formula(value); } | ||||||
|  |  | ||||||
|  | 	static | ||||||
|  | 	String fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | ||||||
|  | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		ssize res = str_fmt_va(buf, buf_size, fmt, va) - 1; | ||||||
|  | 		va_end(va); | ||||||
|  | 		return string_make_length(allocator, buf, res); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static | ||||||
|  | 	String fmt_buf(AllocatorInfo allocator, char const* fmt, ...) { | ||||||
|  | 		local_persist thread_local | ||||||
|  | 		char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
|  | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		ssize res = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va) - 1; | ||||||
|  | 		va_end(va); | ||||||
|  | 		return string_make_length(allocator, buf, res); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	forceinline bool          make_space_for(char const* str, ssize add_len) { return string_make_space_for(this, str, add_len); } | ||||||
|  | 	forceinline bool          append(char c)                                 { return string_append_char(this, c); } | ||||||
|  | 	forceinline bool          append(char const* str)                        { return string_append_c_str(this, str); } | ||||||
|  | 	forceinline bool          append(char const* str, ssize length)          { return string_append_c_str_len(this, str, length); } | ||||||
|  | 	forceinline bool          append(StrC str)                               { return string_append_strc(this, str); } | ||||||
|  | 	forceinline bool          append(const String other)                     { return string_append_string(this, other); } | ||||||
|  | 	forceinline ssize         avail_space() const                            { return string_avail_space(* this); } | ||||||
|  | 	forceinline char*         back()                                         { return string_back(* this); } | ||||||
|  | 	forceinline bool          contains(StrC substring) const                 { return string_contains_strc(* this, substring); } | ||||||
|  | 	forceinline bool          contains(String const& substring) const        { return string_contains_string(* this, substring); } | ||||||
|  | 	forceinline ssize         capacity() const                               { return string_capacity(* this); } | ||||||
|  | 	forceinline void          clear()                                        {        string_clear(* this); } | ||||||
|  | 	forceinline String        duplicate(AllocatorInfo allocator) const       { return string_duplicate(* this, allocator); } | ||||||
|  | 	forceinline void          free()                                         {        string_free(this); } | ||||||
|  | 	forceinline bool          is_equal(String const& other) const            { return string_are_equal(* this, other); } | ||||||
|  | 	forceinline bool          is_equal(StrC other) const                     { return string_are_equal_strc(* this, other); } | ||||||
|  | 	forceinline ssize         length() const                                 { return string_length(* this); } | ||||||
|  | 	forceinline b32           starts_with(StrC substring) const              { return string_starts_with_strc(* this, substring); } | ||||||
|  | 	forceinline b32           starts_with(String substring) const            { return string_starts_with_string(* this, substring); } | ||||||
|  | 	forceinline void          skip_line()                                    {        string_skip_line(* this); } | ||||||
|  | 	forceinline void          strip_space()                                  {        string_strip_space(* this); } | ||||||
|  | 	forceinline StrC          to_strc()                                      { return { string_length(*this), Data}; } | ||||||
|  | 	forceinline void          trim(char const* cut_set)                      {        string_trim(* this, cut_set); } | ||||||
|  | 	forceinline void          trim_space()                                   {        string_trim_space(* this); } | ||||||
|  | 	forceinline String        visualize_whitespace() const                   { return string_visualize_whitespace(* this); } | ||||||
|  | 	forceinline StringHeader& get_header()                                   { return * string_get_header(* this); } | ||||||
|  |  | ||||||
|  | 	bool append_fmt(char const* fmt, ...) { | ||||||
|  | 		ssize res; | ||||||
|  | 		char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | ||||||
|  | 		va_end(va); | ||||||
|  |  | ||||||
|  | 		return string_append_c_str_len(this, buf, res); | ||||||
|  | 	} | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  | forceinline char* string_begin(String str)                   { return ((char*) str); } | ||||||
|  | forceinline char* string_end  (String str)                   { return ((char*) str + string_length(str)); } | ||||||
|  | forceinline char* string_next (String str, char const* iter) { return ((char*) iter + 1); } | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP && 0 | ||||||
|  | forceinline char* begin(String str)             { return ((char*) str); } | ||||||
|  | forceinline char* end  (String str)             { return ((char*) str + string_length(str)); } | ||||||
|  | forceinline char* next (String str, char* iter) { return ((char*) iter + 1); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | forceinline bool  make_space_for(String& str, char const* to_append, ssize add_len); | ||||||
|  | forceinline bool  append(String& str, char c); | ||||||
|  | forceinline bool  append(String& str, char const* str_to_append); | ||||||
|  | forceinline bool  append(String& str, char const* str_to_append, ssize length); | ||||||
|  | forceinline bool  append(String& str, StrC str_to_append); | ||||||
|  | forceinline bool  append(String& str, const String other); | ||||||
|  | forceinline bool  append_fmt(String& str, char const* fmt, ...); | ||||||
|  | forceinline char& back(String& str); | ||||||
|  | forceinline void  clear(String& str); | ||||||
|  | forceinline void  free(String& str); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | usize string_grow_formula(usize value) { | ||||||
| 	// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. | 	// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. | ||||||
| 	return 4 * value + 8; | 	return 4 * value + 8; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | forceinline | ||||||
| 	String make( AllocatorInfo allocator, char const* str ) | String string_make_c_str(AllocatorInfo allocator, char const* str) { | ||||||
| 	{ |  | ||||||
| 	ssize length = str ? str_len(str) : 0; | 	ssize length = str ? str_len(str) : 0; | ||||||
| 		return make_length( allocator, str, length ); | 	return string_make_length(allocator, str, length); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | forceinline | ||||||
| 	String make( AllocatorInfo allocator, StrC str ) | String string_make_strc(AllocatorInfo allocator, StrC str) { | ||||||
| 	{ | 	return string_make_length(allocator, str.Ptr, str.Len); | ||||||
| 		return make_length( allocator, str.Ptr, str.Len ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	String make_reserve( AllocatorInfo allocator, ssize capacity ); | String string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | ||||||
|  | 	va_list va; | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	ssize res = str_fmt_va(buf, buf_size, fmt, va) - 1; | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
| 	static | 	return string_make_length(allocator, buf, res); | ||||||
| 	String make_length( AllocatorInfo allocator, char const* str, ssize length ); | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	String fmt( AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ... ); | String string_fmt_buf(AllocatorInfo allocator, char const* fmt, ...) | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	String fmt_buf( AllocatorInfo allocator, char const* fmt, ... ); |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	String join( AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue ) |  | ||||||
| { | { | ||||||
| 		String result = make( allocator, "" ); | 	local_persist thread_local | ||||||
|  | 	PrintF_Buffer buf = struct_init(PrintF_Buffer, {0}); | ||||||
|  |  | ||||||
|  | 	va_list va; | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	ssize res = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va) -1; | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	return string_make_length(allocator, buf, res); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue) | ||||||
|  | { | ||||||
|  | 	String result = string_make_c_str(allocator, ""); | ||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx < num_parts; ++idx) | 	for (ssize idx = 0; idx < num_parts; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 			result.append( parts[ idx ] ); | 		string_append_c_str(& result, parts[idx]); | ||||||
|  |  | ||||||
| 		if (idx < num_parts - 1) | 		if (idx < num_parts - 1) | ||||||
| 				result.append( glue ); | 			string_append_c_str(& result, glue); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | forceinline | ||||||
| 	bool are_equal( String lhs, String rhs ) | bool string_append_char(String* str, char c) { | ||||||
|  | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	return string_append_c_str_len( str, (char const*)& c, (ssize)1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | bool string_append_c_str(String* str, char const* str_to_append) { | ||||||
|  | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	return string_append_c_str_len(str, str_to_append, str_len(str_to_append)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool string_append_c_str_len(String* str, char const* str_to_append, ssize append_length) | ||||||
| { | { | ||||||
| 		if ( lhs.length() != rhs.length() ) | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	if ( rcast(sptr, str_to_append) > 0) | ||||||
|  | 	{ | ||||||
|  | 		ssize curr_len = string_length(* str); | ||||||
|  |  | ||||||
|  | 		if ( ! string_make_space_for(str, str_to_append, append_length)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		for ( ssize idx = 0; idx < lhs.length(); ++idx ) | 		StringHeader* header = string_get_header(* str); | ||||||
|  |  | ||||||
|  | 		char* Data = * str; | ||||||
|  | 		mem_copy( Data + curr_len, str_to_append, append_length); | ||||||
|  |  | ||||||
|  | 		Data[curr_len + append_length] = '\0'; | ||||||
|  |  | ||||||
|  | 		header->Length = curr_len + append_length; | ||||||
|  | 	} | ||||||
|  | 	return str_to_append != nullptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | bool string_append_strc(String* str, StrC str_to_append) { | ||||||
|  | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	return string_append_c_str_len(str, str_to_append.Ptr, str_to_append.Len); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | bool string_append_string(String* str, String const other) { | ||||||
|  | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	return string_append_c_str_len(str, (char const*)other, string_length(other)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool string_append_fmt(String* str, char const* fmt, ...) { | ||||||
|  | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	ssize res; | ||||||
|  | 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 	va_list va; | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	return string_append_c_str_len(str, (char const*)buf, res); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool string_are_equal_string(String const lhs, String const rhs) | ||||||
|  | { | ||||||
|  | 	if (string_length(lhs) != string_length(rhs)) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx < string_length(lhs); ++idx) | ||||||
| 		if (lhs[idx] != rhs[idx]) | 		if (lhs[idx] != rhs[idx]) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	bool are_equal( String lhs, StrC rhs ) | bool string_are_equal_strc(String const lhs, StrC rhs) | ||||||
| { | { | ||||||
| 		if ( lhs.length() != (rhs.Len) ) | 	if (string_length(lhs) != (rhs.Len)) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 		for ( ssize idx = 0; idx < lhs.length(); ++idx ) | 	for (ssize idx = 0; idx < string_length(lhs); ++idx) | ||||||
| 			if ( lhs[idx] != rhs[idx] ) | 		if (lhs[idx] != rhs.Ptr[idx]) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	bool make_space_for( char const* str, ssize add_len ); | forceinline | ||||||
|  | ssize string_avail_space(String const str) { | ||||||
| 	bool append( char c ) | 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
| 	{ | 	return header->Capacity - header->Length; | ||||||
| 		return append( & c, 1 ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	bool append( char const* str ) | forceinline | ||||||
| 	{ | char* string_back(String str) { | ||||||
| 		return append( str, str_len( str ) ); | 	return & (str)[string_length(str) - 1]; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	bool append( char const* str, ssize length ) | inline | ||||||
|  | bool string_contains_StrC(String const str, StrC substring) | ||||||
| { | { | ||||||
| 		if ( sptr(str) > 0 ) | 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
| 		{ |  | ||||||
| 			ssize curr_len = this->length(); |  | ||||||
|  |  | ||||||
| 			if ( ! make_space_for( str, length ) ) | 	if (substring.Len > header->Length) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 			Header& header = get_header(); | 	ssize main_len = header->Length; | ||||||
|  | 	ssize sub_len  = substring.Len; | ||||||
|  |  | ||||||
| 			mem_copy( Data + curr_len, str, length ); | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
|  |  | ||||||
| 			Data[ curr_len + length ] = '\0'; |  | ||||||
|  |  | ||||||
| 			header.Length = curr_len + length; |  | ||||||
| 		} |  | ||||||
| 		return str != nullptr; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool append( StrC str) |  | ||||||
| 	{ | 	{ | ||||||
| 		return append( str.Ptr, str.Len ); | 		if (str_compare_len(str + idx, substring.Ptr, sub_len) == 0) | ||||||
|  | 			return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool append( const String other ) | 	return false; | ||||||
| 	{ |  | ||||||
| 		return append( other.Data, other.length() ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	bool append_fmt( char const* fmt, ... ); | inline | ||||||
|  | bool string_contains_string(String const str, String const substring) | ||||||
| 	ssize avail_space() const |  | ||||||
| { | { | ||||||
| 		Header const& | 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |  | ||||||
|  |  | ||||||
| 		return header.Capacity - header.Length; | 	if (string_length(substring) > header->Length) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	ssize main_len = header->Length; | ||||||
|  | 	ssize sub_len  = string_length(substring); | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
|  | 	{ | ||||||
|  | 		if (str_compare_len(str + idx, substring, sub_len) == 0) | ||||||
|  | 			return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	char& back() | 	return false; | ||||||
| 	{ |  | ||||||
| 		return Data[ length() - 1 ]; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	ssize capacity() const | forceinline | ||||||
| 	{ | ssize string_capacity(String const str) { | ||||||
| 		Header const& |    StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |    return header->Capacity; | ||||||
|  |  | ||||||
| 		return header.Capacity; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void clear() | forceinline | ||||||
| 	{ | void string_clear(String str) { | ||||||
| 		get_header().Length = 0; |    string_get_header(str)->Length = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	String duplicate( AllocatorInfo allocator ) const | forceinline | ||||||
| 	{ | String string_duplicate(String const str, AllocatorInfo allocator) { | ||||||
| 		return make_length( allocator, Data, length() ); |    return string_make_length(allocator, str, string_length(str)); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void free() | forceinline | ||||||
| 	{ | void string_free(String* str) { | ||||||
| 		if ( ! Data ) | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	if (! (* str)) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 		Header& header = get_header(); | 	StringHeader* header = string_get_header(* str); | ||||||
|  | 	allocator_free(header->Allocator, header); | ||||||
| 		gen::free( header.Allocator, & header ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	Header& get_header() | forceinline | ||||||
| 	{ | StringHeader* string_get_header(String str) { | ||||||
| 		return *(Header*)(Data - sizeof(Header)); |    return (StringHeader*)(scast(char*, str) - sizeof(StringHeader)); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	ssize length() const | forceinline | ||||||
|  | ssize string_length(String const str) | ||||||
| { | { | ||||||
| 		Header const& |    StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |    return header->Length; | ||||||
|  |  | ||||||
| 		return header.Length; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	b32 starts_with( StrC substring ) const | inline | ||||||
|  | bool string_make_space_for(String* str, char const* to_append, ssize add_len) | ||||||
| { | { | ||||||
| 		if (substring.Len > length()) | 	ssize available = string_avail_space(* str); | ||||||
|  |  | ||||||
|  | 	if (available >= add_len) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		ssize new_len, old_size, new_size; | ||||||
|  | 		void* ptr; | ||||||
|  | 		void* new_ptr; | ||||||
|  |  | ||||||
|  | 		AllocatorInfo allocator = string_get_header(* str)->Allocator; | ||||||
|  | 		StringHeader* header    = nullptr; | ||||||
|  |  | ||||||
|  | 		new_len  = string_grow_formula(string_length(* str) + add_len); | ||||||
|  | 		ptr      = string_get_header(* str); | ||||||
|  | 		old_size = size_of(StringHeader) + string_length(* str) + 1; | ||||||
|  | 		new_size = size_of(StringHeader) + new_len + 1; | ||||||
|  |  | ||||||
|  | 		new_ptr = resize(allocator, ptr, old_size, new_size); | ||||||
|  |  | ||||||
|  | 		if (new_ptr == nullptr) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		b32 result = str_compare(Data, substring.Ptr, substring.Len ) == 0; | 		header = rcast(StringHeader*, new_ptr); | ||||||
|  | 		header->Allocator = allocator; | ||||||
|  | 		header->Capacity  = new_len; | ||||||
|  |  | ||||||
|  | 		char** Data = rcast(char**, str); | ||||||
|  | 		* Data = rcast(char*, header + 1); | ||||||
|  |  | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | b32 string_starts_with_strc(String const str, StrC substring) { | ||||||
|  | 	if (substring.Len > string_length(str)) | ||||||
|  | 	return false; | ||||||
|  |  | ||||||
|  | 	b32 result = str_compare_len(str, substring.Ptr, substring.Len) == 0; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	b32 starts_with( String substring ) const | forceinline | ||||||
| 	{ | b32 string_starts_with_string(String const str, String substring) { | ||||||
| 		if (substring.length() > length()) | 	if (string_length(substring) > string_length(str)) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 		b32 result = str_compare(Data, substring, substring.length() - 1 ) == 0; | 	b32 result = str_compare_len(str, substring, string_length(substring) - 1) == 0; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void skip_line() | inline | ||||||
|  | void string_skip_line(String str) | ||||||
| { | { | ||||||
| #define current (*scanner) | #define current (*scanner) | ||||||
| 		char* scanner = Data; | 	char* scanner = str; | ||||||
| 		while ( current != '\r' && current != '\n' ) | 	while (current != '\r' && current != '\n') { | ||||||
| 		{ |  | ||||||
|  		++scanner; |  		++scanner; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 		s32 new_length = scanner - Data; | 	s32 new_length = scanner - str; | ||||||
|  |  | ||||||
| 		if ( current == '\r' ) | 	if (current == '\r') { | ||||||
| 		{ |  | ||||||
| 		new_length += 1; | 		new_length += 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 		mem_move( Data, scanner, new_length ); | 	mem_move((char*)str, scanner, new_length); | ||||||
|  |  | ||||||
| 		Header* header = & get_header(); | 	StringHeader* header = string_get_header(str); | ||||||
| 	header->Length = new_length; | 	header->Length = new_length; | ||||||
| #undef current | #undef current | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void strip_space() | inline | ||||||
|  | void strip_space(String str) | ||||||
| { | { | ||||||
| 		char* write_pos = Data; |    char* write_pos = str; | ||||||
| 		char* read_pos  = Data; |    char* read_pos  = str; | ||||||
|  |  | ||||||
|    while (* read_pos) |    while (* read_pos) | ||||||
|    { |    { | ||||||
| @@ -268,15 +632,22 @@ struct String | |||||||
|    write_pos[0] = '\0';  // Null-terminate the modified string |    write_pos[0] = '\0';  // Null-terminate the modified string | ||||||
|  |  | ||||||
|    // Update the length if needed |    // Update the length if needed | ||||||
| 		get_header().Length = write_pos - Data; |    string_get_header(str)->Length = write_pos - str; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void trim( char const* cut_set ) | forceinline | ||||||
|  | StrC string_to_strc(String str) { | ||||||
|  | 	StrC result = { string_length(str), (char const*)str }; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void trim(String str, char const* cut_set) | ||||||
| { | { | ||||||
| 	ssize len = 0; | 	ssize len = 0; | ||||||
|  |  | ||||||
| 		char* start_pos = Data; | 	char* start_pos = str; | ||||||
| 		char* end_pos   = Data + length() - 1; | 	char* end_pos   = scast(char*, str) + string_length(str) - 1; | ||||||
|  |  | ||||||
| 	while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos)) | 	while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos)) | ||||||
| 	start_pos++; | 	start_pos++; | ||||||
| @@ -286,130 +657,106 @@ struct String | |||||||
|  |  | ||||||
| 	len = scast(ssize, (start_pos > end_pos) ? 0 : ((end_pos - start_pos) + 1)); | 	len = scast(ssize, (start_pos > end_pos) ? 0 : ((end_pos - start_pos) + 1)); | ||||||
|  |  | ||||||
| 		if ( Data != start_pos ) | 	if (str != start_pos) | ||||||
| 			mem_move( Data, start_pos, len ); | 		mem_move(str, start_pos, len); | ||||||
|  |  | ||||||
| 		Data[ len ] = '\0'; | 	str[len] = '\0'; | ||||||
|  |  | ||||||
| 		get_header().Length = len; |    string_get_header(str)->Length = len; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void trim_space() | forceinline | ||||||
| 	{ | void trim_space(String str) { | ||||||
| 		return trim( " \t\r\n\v\f" ); |    trim(str, " \t\r\n\v\f"); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	// Debug function that provides a copy of the string with whitespace characters visualized. | inline | ||||||
| 	String visualize_whitespace() const | String visualize_whitespace(String const str) | ||||||
| { | { | ||||||
| 		Header* header = (Header*)(Data - sizeof(Header)); | 	StringHeader* header = (StringHeader*)(scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  | 	String        result = string_make_reserve(header->Allocator, string_length(str) * 2); // Assume worst case for space requirements. | ||||||
|  |  | ||||||
| 		String result = make_reserve(header->Allocator, length() * 2); // Assume worst case for space requirements. | 	for (char const* c = string_begin(str); c != string_end(str); c = string_next(str, c)) | ||||||
|  | 	switch ( * c ) | ||||||
| 		for ( char c : *this ) |  | ||||||
| 		{ |  | ||||||
| 			switch ( c ) |  | ||||||
| 	{ | 	{ | ||||||
| 		case ' ': | 		case ' ': | ||||||
| 					result.append( txt("·") ); | 			string_append_strc(& result, txt("·")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\t': | 		case '\t': | ||||||
| 					result.append( txt("→") ); | 			string_append_strc(& result, txt("→")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\n': | 		case '\n': | ||||||
| 					result.append( txt("↵") ); | 			string_append_strc(& result, txt("↵")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\r': | 		case '\r': | ||||||
| 					result.append( txt("⏎") ); | 			string_append_strc(& result, txt("⏎")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\v': | 		case '\v': | ||||||
| 					result.append( txt("⇕") ); | 			string_append_strc(& result, txt("⇕")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\f': | 		case '\f': | ||||||
| 					result.append( txt("⌂") ); | 			string_append_strc(& result, txt("⌂")); | ||||||
| 		break; | 		break; | ||||||
| 		default: | 		default: | ||||||
| 					result.append(c); | 			string_append_char(& result, * c); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  | #pragma endregion String | ||||||
|  |  | ||||||
| 	// For-range support | #if GEN_COMPILER_CPP | ||||||
|  | struct String_POD { | ||||||
| 	char* begin() const |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char* end() const |  | ||||||
| 	{ |  | ||||||
| 		Header const& |  | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |  | ||||||
|  |  | ||||||
| 		return Data + header.Length; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator bool() |  | ||||||
| 	{ |  | ||||||
| 		return Data != nullptr; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator char* () |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator char const* () const |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator StrC() const |  | ||||||
| 	{ |  | ||||||
| 		return { length(), Data }; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Used with cached strings |  | ||||||
| 	// Essentially makes the string a string view. |  | ||||||
| 	String const& operator = ( String const& other ) const |  | ||||||
| 	{ |  | ||||||
| 		if ( this == & other ) |  | ||||||
| 			return *this; |  | ||||||
|  |  | ||||||
| 		String* |  | ||||||
| 		this_ = ccast(String*, this); |  | ||||||
| 		this_->Data = other.Data; |  | ||||||
|  |  | ||||||
| 		return *this; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char& operator [] ( ssize index ) |  | ||||||
| 	{ |  | ||||||
| 		return Data[ index ]; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char const& operator [] ( ssize index ) const |  | ||||||
| 	{ |  | ||||||
| 		return Data[ index ]; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char* Data; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct String_POD |  | ||||||
| { |  | ||||||
| 	char* Data; | 	char* Data; | ||||||
| }; | }; | ||||||
| static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Implements basic string interning. Data structure is based off the ZPL Hashtable. | forceinline | ||||||
| using StringTable = HashTable<String const>; | StrC strc_duplicate(StrC str, AllocatorInfo allocator) { | ||||||
|  | 	StrC result = string_to_strc( string_make_length(allocator, str.Ptr, str.Len)); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | StrC strc_visualize_whitespace(StrC str, AllocatorInfo allocator) | ||||||
|  | { | ||||||
|  | 	String result = string_make_reserve(allocator, str.Len * 2); // Assume worst case for space requirements. | ||||||
|  | 	for (char const* c = strc_begin(str); c != strc_end(str); c = strc_next(str, c))  | ||||||
|  | 	switch ( * c ) | ||||||
|  | 	{ | ||||||
|  | 		case ' ': | ||||||
|  | 			string_append_strc(& result, txt("·")); | ||||||
|  | 		break; | ||||||
|  | 		case '\t': | ||||||
|  | 			string_append_strc(& result, txt("→")); | ||||||
|  | 		break; | ||||||
|  | 		case '\n': | ||||||
|  | 			string_append_strc(& result, txt("↵")); | ||||||
|  | 		break; | ||||||
|  | 		case '\r': | ||||||
|  | 			string_append_strc(& result, txt("⏎")); | ||||||
|  | 		break; | ||||||
|  | 		case '\v': | ||||||
|  | 			string_append_strc(& result, txt("⇕")); | ||||||
|  | 		break; | ||||||
|  | 		case '\f': | ||||||
|  | 			string_append_strc(& result, txt("⌂")); | ||||||
|  | 		break; | ||||||
|  | 		default: | ||||||
|  | 			string_append_char(& result, * c); | ||||||
|  | 		break; | ||||||
|  | } | ||||||
|  | 	return string_to_strc(result); | ||||||
|  | } | ||||||
|  |  | ||||||
| // Represents strings cached with the string table. | // Represents strings cached with the string table. | ||||||
| // Should never be modified, if changed string is desired, cache_string( str ) another. | // Should never be modified, if changed string is desired, cache_string( str ) another. | ||||||
| using StringCached = String const; | typedef StrC StringCached; | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
|  | // Implements basic string interning. Data structure is based off the ZPL Hashtable. | ||||||
|  | typedef HashTable(StringCached) StringTable; | ||||||
| #pragma endregion Strings | #pragma endregion Strings | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Timing | #pragma region Timing | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| #ifdef GEN_BENCHMARK | #ifdef GEN_BENCHMARK | ||||||
| 	#if defined( GEN_COMPILER_MSVC ) && ! defined( __clang__ ) | 	#if defined( GEN_COMPILER_MSVC ) && ! defined( __clang__ ) | ||||||
| @@ -164,4 +165,5 @@ | |||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
| #pragma endregion Timing | #pragma endregion Timing | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
|  |  | ||||||
| #pragma region Timing | #pragma region Timing | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| #ifdef GEN_BENCHMARK | #ifdef GEN_BENCHMARK | ||||||
| //! Return CPU timestamp. | //! Return CPU timestamp. | ||||||
| u64 read_cpu_time_stamp_counter( void ); | u64 read_cpu_time_stamp_counter( void ); | ||||||
| @@ -16,4 +18,6 @@ f64 time_rel( void ); | |||||||
| u64 time_rel_ms( void ); | u64 time_rel_ms( void ); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Timing | #pragma endregion Timing | ||||||
|   | |||||||
| @@ -54,6 +54,7 @@ Template | |||||||
| Typedef | Typedef | ||||||
| Typename | Typename | ||||||
| Union | Union | ||||||
|  | Union_Fwd | ||||||
| Union_Body | Union_Body | ||||||
| Using | Using | ||||||
| Using_Namespace | Using_Namespace | ||||||
|   | |||||||
| 
 | 
| @@ -8,6 +8,13 @@ | |||||||
|  |  | ||||||
| #include "gen.hpp" | #include "gen.hpp" | ||||||
|  |  | ||||||
|  | // These are intended for use in the base library of gencpp and the C-variant of the library | ||||||
|  | // It provides a interoperability between the C++ and C interfacing for containers. (not letting these do any crazy substiution though) | ||||||
|  | // They are undefined in gen.hpp and gen.cpp at the end of the files. | ||||||
|  | // We cpp library expects the user to use the regular calls as they can resolve the type fine. | ||||||
|  |  | ||||||
|  | #include "helpers/push_container_defines.inline.hpp" | ||||||
|  |  | ||||||
| //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. | //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. | ||||||
| //! Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl | //! Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl | ||||||
| #ifndef GEN_ROLL_OWN_DEPENDENCIES | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
| @@ -32,4 +39,5 @@ GEN_NS_BEGIN | |||||||
|  |  | ||||||
| GEN_NS_END | GEN_NS_END | ||||||
|  |  | ||||||
|  | #include "helpers/pop_container_defines.inline.hpp" | ||||||
| #include "helpers/pop_ignores.inline.hpp" | #include "helpers/pop_ignores.inline.hpp" | ||||||
|   | |||||||
| @@ -11,6 +11,9 @@ | |||||||
| #include "helpers/push_ignores.inline.hpp" | #include "helpers/push_ignores.inline.hpp" | ||||||
| #include "components/header_start.hpp" | #include "components/header_start.hpp" | ||||||
|  |  | ||||||
|  | // Has container defines pushed | ||||||
|  | #include "gen.dep.hpp" | ||||||
|  |  | ||||||
| GEN_NS_BEGIN | GEN_NS_BEGIN | ||||||
|  |  | ||||||
| #include "components/types.hpp" | #include "components/types.hpp" | ||||||
| @@ -30,4 +33,5 @@ GEN_NS_BEGIN | |||||||
|  |  | ||||||
| GEN_NS_END | GEN_NS_END | ||||||
|  |  | ||||||
|  | #include "helpers/pop_container_defines.inline.hpp" | ||||||
| #include "helpers/pop_ignores.inline.hpp" | #include "helpers/pop_ignores.inline.hpp" | ||||||
|   | |||||||
| @@ -11,32 +11,35 @@ using namespace gen; | |||||||
| CodeBody gen_ecode( char const* path ) | CodeBody gen_ecode( char const* path ) | ||||||
| { | { | ||||||
| 	char  scratch_mem[kilobytes(1)]; | 	char  scratch_mem[kilobytes(1)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	file_read_contents( scratch, zero_terminate, path ); | 	file_read_contents( arena_allocator_info( & scratch), file_zero_terminate, path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_nodes; | 	CSV_Object csv_nodes; | ||||||
| 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | ||||||
|  |  | ||||||
| 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries   = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String enum_entries   = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	for ( ADT_Node node : enum_strs ) | 	for ( ADT_Node* node = array_begin(enum_strs); node != array_end(enum_strs); node = array_next(enum_strs, node) ) | ||||||
| 	{ | 	{ | ||||||
| 		char const* code = node.string; | 		char const* code = node->string; | ||||||
| 		enum_entries.append_fmt( "%s,\n", code ); |  | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); | 		string_append_fmt( & enum_entries, "CT_%s,\n", code ); | ||||||
|  | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", (StrC)enum_entries, "enum Type : u32 { <entries> NumTypes };")); | 	CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries),  | ||||||
|  | 		"enum CodeType_Def : u32 { <entries> CT_NumTypes };" | ||||||
|  | 	)); | ||||||
|  |  | ||||||
| #pragma push_macro("local_persist") | #pragma push_macro("local_persist") | ||||||
| #undef local_persist | #undef local_persist | ||||||
| 	CodeFn to_str = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | 	CodeFn to_str = parse_function( token_fmt( "entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( Type type ) | 		StrC to_str( CodeType type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			StrC lookup[] { | 			StrC lookup[] { | ||||||
| @@ -48,18 +51,19 @@ CodeBody gen_ecode( char const* path ) | |||||||
| 	))); | 	))); | ||||||
| #pragma pop_macro("local_persist") | #pragma pop_macro("local_persist") | ||||||
|  |  | ||||||
| 	CodeNS    nspace = def_namespace( name(ECode), def_namespace_body( args( enum_code, to_str ) ) ); | 	//CodeNS    nspace = def_namespace( name(ECode), def_namespace_body( args( enum_code, to_str ) ) ); | ||||||
| 	CodeUsing code_t = def_using( name(CodeT), def_type( name(ECode::Type) ) ); | 	//CodeUsing code_t = def_using( name(CodeT), def_type( name(ECode::Type) ) ); | ||||||
|  | 	CodeTypedef code_t = parse_typedef(code(typedef enum CodeType_Def CodeType; )); | ||||||
|  |  | ||||||
| 	return def_global_body( args( nspace, code_t, fmt_newline ) ); | 	return def_global_body( args( enum_code, code_t, to_str, fmt_newline ) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeBody gen_eoperator( char const* path ) | CodeBody gen_eoperator( char const* path ) | ||||||
| { | { | ||||||
| 	char scratch_mem[kilobytes(4)]; | 	char scratch_mem[kilobytes(4)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	file_read_contents( scratch, zero_terminate, path ); | 	file_read_contents( arena_allocator_info(& scratch), file_zero_terminate, path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_nodes; | 	CSV_Object csv_nodes; | ||||||
| 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | ||||||
| @@ -67,20 +71,20 @@ CodeBody gen_eoperator( char const* path ) | |||||||
| 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | ||||||
| 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries   = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String enum_entries   = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	for (usize idx = 0; idx < enum_strs.num(); idx++) | 	for (usize idx = 0; idx < array_num(enum_strs); idx++) | ||||||
| 	{ | 	{ | ||||||
| 		char const* enum_str     = enum_strs[idx].string; | 		char const* enum_str     = enum_strs[idx].string; | ||||||
| 		char const* entry_to_str = str_strs [idx].string; | 		char const* entry_to_str = str_strs [idx].string; | ||||||
|  |  | ||||||
| 		enum_entries.append_fmt( "%s,\n", enum_str ); | 		string_append_fmt( & enum_entries, "Op_%s,\n", enum_str ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum  enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( | 	CodeEnum  enum_code = parse_enum(token_fmt("entries", string_to_strc(enum_entries), stringize( | ||||||
| 		enum Type : u32 | 		enum Operator_Def : u32 | ||||||
| 		{ | 		{ | ||||||
| 			<entries> | 			<entries> | ||||||
| 			NumOps | 			NumOps | ||||||
| @@ -89,9 +93,9 @@ CodeBody gen_eoperator( char const* path ) | |||||||
|  |  | ||||||
| #pragma push_macro("local_persist") | #pragma push_macro("local_persist") | ||||||
| #undef local_persist | #undef local_persist | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( Type op ) | 		StrC to_str( Operator op ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			StrC lookup[] { | 			StrC lookup[] { | ||||||
| @@ -103,19 +107,19 @@ CodeBody gen_eoperator( char const* path ) | |||||||
| 	))); | 	))); | ||||||
| #pragma pop_macro("local_persist") | #pragma pop_macro("local_persist") | ||||||
|  |  | ||||||
| 	CodeNS nspace = def_namespace( name(EOperator), def_namespace_body( args( enum_code, to_str ) ) ); | 	//CodeNS nspace = def_namespace( name(EOperator), def_namespace_body( args( enum_code, to_str ) ) ); | ||||||
|  | 	//CodeUsing operator_t = def_using( name(OperatorT), def_type( name(EOperator::Type) ) ); | ||||||
|  | 	CodeTypedef operator_t = parse_typedef(code( typedef enum Operator_Def Operator; )); | ||||||
|  |  | ||||||
| 	CodeUsing operator_t = def_using( name(OperatorT), def_type( name(EOperator::Type) ) ); | 	return def_global_body( args( enum_code, operator_t, to_str, fmt_newline ) ); | ||||||
|  |  | ||||||
| 	return def_global_body( args( nspace, operator_t, fmt_newline ) ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeBody gen_especifier( char const* path ) | CodeBody gen_especifier( char const* path ) | ||||||
| { | { | ||||||
| 	char scratch_mem[kilobytes(4)]; | 	char scratch_mem[kilobytes(4)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	file_read_contents( scratch, zero_terminate, path ); | 	file_read_contents( arena_allocator_info(& scratch), file_zero_terminate, path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_nodes; | 	CSV_Object csv_nodes; | ||||||
| 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | ||||||
| @@ -123,31 +127,31 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | ||||||
| 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries   = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String enum_entries   = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	for (usize idx = 0; idx < enum_strs.num(); idx++) | 	for (usize idx = 0; idx < array_num(enum_strs); idx++) | ||||||
| 	{ | 	{ | ||||||
| 		char const* enum_str     = enum_strs[idx].string; | 		char const* enum_str     = enum_strs[idx].string; | ||||||
| 		char const* entry_to_str = str_strs [idx].string; | 		char const* entry_to_str = str_strs [idx].string; | ||||||
|  |  | ||||||
| 		enum_entries.append_fmt( "%s,\n", enum_str ); | 		string_append_fmt( & enum_entries, "Spec_%s,\n", enum_str ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum  enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( | 	CodeEnum  enum_code = parse_enum(token_fmt("entries", string_to_strc(enum_entries), stringize( | ||||||
| 		enum Type : u32 | 		enum Specifier_Def : u32 | ||||||
| 		{ | 		{ | ||||||
| 			<entries> | 			<entries> | ||||||
| 			NumSpecifiers | 			Spec_NumSpecifiers | ||||||
| 		}; | 		}; | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn is_trailing = parse_function(token_fmt("specifier", (StrC)to_str_entries, stringize( | 	CodeFn is_trailing = parse_function(token_fmt("specifier", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		bool is_trailing( Type specifier ) | 		bool is_trailing( Specifier specifier ) | ||||||
| 		{ | 		{ | ||||||
| 			return specifier > Virtual; | 			return specifier > Spec_Virtual; | ||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| @@ -161,9 +165,9 @@ CodeBody gen_especifier( char const* path ) | |||||||
| #undef do_once_end | #undef do_once_end | ||||||
| #undef forceinline | #undef forceinline | ||||||
| #undef neverinline | #undef neverinline | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( Type type ) | 		StrC to_str( Specifier type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			StrC lookup[] { | 			StrC lookup[] { | ||||||
| @@ -174,16 +178,16 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | 	CodeFn to_type = parse_function( token_fmt( "entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		Type to_type( StrC str ) | 		Specifier to_specifier( StrC str ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			u32 keymap[ NumSpecifiers ]; | 			u32 keymap[ Spec_NumSpecifiers ]; | ||||||
| 			do_once_start | 			do_once_start | ||||||
| 				for ( u32 index = 0; index < NumSpecifiers; index++ ) | 				for ( u32 index = 0; index < Spec_NumSpecifiers; index++ ) | ||||||
| 				{ | 				{ | ||||||
| 					StrC enum_str = to_str( (Type)index ); | 					StrC enum_str = to_str( (Specifier)index ); | ||||||
|  |  | ||||||
| 					// We subtract 1 to remove the null terminator | 					// We subtract 1 to remove the null terminator | ||||||
| 					// This is because the tokens lexed are not null terminated. | 					// This is because the tokens lexed are not null terminated. | ||||||
| @@ -193,13 +197,13 @@ CodeBody gen_especifier( char const* path ) | |||||||
|  |  | ||||||
| 			u32 hash = crc32( str.Ptr, str.Len ); | 			u32 hash = crc32( str.Ptr, str.Len ); | ||||||
|  |  | ||||||
| 			for ( u32 index = 0; index < NumSpecifiers; index++ ) | 			for ( u32 index = 0; index < Spec_NumSpecifiers; index++ ) | ||||||
| 			{ | 			{ | ||||||
| 				if ( keymap[index] == hash ) | 				if ( keymap[index] == hash ) | ||||||
| 					return (Type)index; | 					return (Specifier)index; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return Invalid; | 			return Spec_Invalid; | ||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
| #pragma pop_macro("local_persist") | #pragma pop_macro("local_persist") | ||||||
| @@ -208,24 +212,26 @@ CodeBody gen_especifier( char const* path ) | |||||||
| #pragma pop_macro("forceinline") | #pragma pop_macro("forceinline") | ||||||
| #pragma pop_macro("neverinline") | #pragma pop_macro("neverinline") | ||||||
|  |  | ||||||
| 	CodeNS nspace = def_namespace( name(ESpecifier), def_namespace_body( args( enum_code, is_trailing, to_str, to_type ) ) ); | 	//CodeNS nspace = def_namespace( name(ESpecifier), def_namespace_body( args( enum_code, is_trailing, to_str, to_type ) ) ); | ||||||
|  | 	//CodeUsing specifier_t = def_using( name(SpecifierT), def_type( name(ESpecifier::Type) ) ); | ||||||
|  | 	CodeTypedef specifier_t = parse_typedef( code(typedef enum Specifier_Def Specifier; )); | ||||||
|  |  | ||||||
| 	CodeUsing specifier_t = def_using( name(SpecifierT), def_type( name(ESpecifier::Type) ) ); | 	return def_global_body( args( enum_code, specifier_t, is_trailing, to_str, to_type, fmt_newline ) ); | ||||||
|  |  | ||||||
| 	return def_global_body( args( nspace, specifier_t, fmt_newline ) ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | ||||||
| { | { | ||||||
| 	char  scratch_mem[kilobytes(16)]; | 	char  scratch_mem[kilobytes(16)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	FileContents enum_content = file_read_contents( scratch, zero_terminate, etok_path ); | 	AllocatorInfo scratch_info = arena_allocator_info(& scratch); | ||||||
|  |  | ||||||
|  | 	FileContents enum_content = file_read_contents( scratch_info, file_zero_terminate, etok_path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_enum_nodes; | 	CSV_Object csv_enum_nodes; | ||||||
| 	csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false ); | 	csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false ); | ||||||
|  |  | ||||||
| 	FileContents attrib_content = file_read_contents( scratch, zero_terminate, attr_path ); | 	FileContents attrib_content = file_read_contents( scratch_info, file_zero_terminate, attr_path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_attr_nodes; | 	CSV_Object csv_attr_nodes; | ||||||
| 	csv_parse( &csv_attr_nodes, rcast(char*, attrib_content.data), GlobalAllocator, false ); | 	csv_parse( &csv_attr_nodes, rcast(char*, attrib_content.data), GlobalAllocator, false ); | ||||||
| @@ -235,48 +241,48 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| 	Array<ADT_Node> attribute_strs     = csv_attr_nodes.nodes[0].nodes; | 	Array<ADT_Node> attribute_strs     = csv_attr_nodes.nodes[0].nodes; | ||||||
| 	Array<ADT_Node> attribute_str_strs = csv_attr_nodes.nodes[1].nodes; | 	Array<ADT_Node> attribute_str_strs = csv_attr_nodes.nodes[1].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries             = String::make_reserve( GlobalAllocator, kilobytes(2) ); | 	String enum_entries             = string_make_reserve( GlobalAllocator, kilobytes(2) ); | ||||||
| 	String to_str_entries           = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 	String to_str_entries           = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
| 	String attribute_entries        = String::make_reserve( GlobalAllocator, kilobytes(2) ); | 	String attribute_entries        = string_make_reserve( GlobalAllocator, kilobytes(2) ); | ||||||
| 	String to_str_attributes        = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 	String to_str_attributes        = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
| 	String attribute_define_entries = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 	String attribute_define_entries = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
|  |  | ||||||
| 	for (usize idx = 0; idx < enum_strs.num(); idx++) | 	for (usize idx = 0; idx < array_num(enum_strs); idx++) | ||||||
| 	{ | 	{ | ||||||
| 		char const* enum_str     = enum_strs[idx].string; | 		char const* enum_str     = enum_strs[idx].string; | ||||||
| 		char const* entry_to_str = enum_str_strs [idx].string; | 		char const* entry_to_str = enum_str_strs [idx].string; | ||||||
|  |  | ||||||
| 		enum_entries.append_fmt( "%s,\n", enum_str ); | 		string_append_fmt( & enum_entries, "Tok_%s,\n", enum_str ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( usize idx = 0; idx < attribute_strs.num(); idx++ ) | 	for ( usize idx = 0; idx < array_num(attribute_strs); idx++ ) | ||||||
| 	{ | 	{ | ||||||
| 		char const* attribute_str = attribute_strs[idx].string; | 		char const* attribute_str = attribute_strs[idx].string; | ||||||
| 		char const* entry_to_str  = attribute_str_strs [idx].string; | 		char const* entry_to_str  = attribute_str_strs [idx].string; | ||||||
|  |  | ||||||
| 		attribute_entries.append_fmt( "Attribute_%s,\n", attribute_str ); | 		string_append_fmt( & attribute_entries, "Tok_Attribute_%s,\n", attribute_str ); | ||||||
| 		to_str_attributes.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_attributes, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 		attribute_define_entries.append_fmt( "Entry( Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); | 		string_append_fmt( & attribute_define_entries, "Entry( Tok_Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); | ||||||
|  |  | ||||||
| 		if ( idx < attribute_strs.num() - 1 ) | 		if ( idx < array_num(attribute_strs) - 1 ) | ||||||
| 			attribute_define_entries.append( " \\\n"); | 			string_append_strc( & attribute_define_entries, txt(" \\\n")); | ||||||
| 		else | 		else | ||||||
| 			attribute_define_entries.append( "\n"); | 			string_append_strc( & attribute_define_entries, txt("\n")); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | ||||||
| #undef GEN_DEFINE_ATTRIBUTE_TOKENS | #undef GEN_DEFINE_ATTRIBUTE_TOKENS | ||||||
| 	CodeDefine attribute_entires_def = def_define( name(GEN_DEFINE_ATTRIBUTE_TOKENS), attribute_define_entries  ); | 	CodeDefine attribute_entires_def = def_define( name(GEN_DEFINE_ATTRIBUTE_TOKENS), string_to_strc(attribute_define_entries)  ); | ||||||
| #pragma pop_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | #pragma pop_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | ||||||
|  |  | ||||||
| 	// We cannot parse this enum, it has Attribute names as enums | 	// We cannot parse this enum, it has Attribute names as enums | ||||||
| 	CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, "attribute_toks", (StrC)attribute_entries, stringize( | 	CodeEnum enum_code = parse_enum(token_fmt("entries", string_to_strc(enum_entries), "attribute_toks", string_to_strc(attribute_entries), stringize( | ||||||
| 		enum Type : u32 | 		enum TokType_Def : u32 | ||||||
| 		{ | 		{ | ||||||
| 			<entries> | 			<entries> | ||||||
| 			<attribute_toks> | 			<attribute_toks> | ||||||
| 			NumTokens | 			Tok_NumTokens | ||||||
| 		}; | 		}; | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| @@ -286,9 +292,9 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| #undef local_persist | #undef local_persist | ||||||
| #undef do_once_start | #undef do_once_start | ||||||
| #undef do_once_end | #undef do_once_end | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, "attribute_toks", (StrC)to_str_attributes, stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", string_to_strc(to_str_entries), "attribute_toks", string_to_strc(to_str_attributes), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( Type type ) | 		StrC to_str( TokType type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			StrC lookup[] { | 			StrC lookup[] { | ||||||
| @@ -300,16 +306,16 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | 	CodeFn to_type = parse_function( token_fmt( "entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		Type to_type( StrC str ) | 		TokType to_toktype( StrC str ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| 			u32 keymap[ NumTokens ]; | 			u32 keymap[ Tok_NumTokens ]; | ||||||
| 			do_once_start | 			do_once_start | ||||||
| 				for ( u32 index = 0; index < NumTokens; index++ ) | 				for ( u32 index = 0; index < Tok_NumTokens; index++ ) | ||||||
| 				{ | 				{ | ||||||
| 					StrC enum_str = to_str( (Type)index ); | 					StrC enum_str = to_str( (TokType)index ); | ||||||
|  |  | ||||||
| 					// We subtract 1 to remove the null terminator | 					// We subtract 1 to remove the null terminator | ||||||
| 					// This is because the tokens lexed are not null terminated. | 					// This is because the tokens lexed are not null terminated. | ||||||
| @@ -319,102 +325,56 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
|  |  | ||||||
| 			u32 hash = crc32( str.Ptr, str.Len ); | 			u32 hash = crc32( str.Ptr, str.Len ); | ||||||
|  |  | ||||||
| 			for ( u32 index = 0; index < NumTokens; index++ ) | 			for ( u32 index = 0; index < Tok_NumTokens; index++ ) | ||||||
| 			{ | 			{ | ||||||
| 				if ( keymap[index] == hash ) | 				if ( keymap[index] == hash ) | ||||||
| 					return (Type)index; | 					return (TokType)index; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return Invalid; | 			return Tok_Invalid; | ||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
| #pragma pop_macro("local_persist") | #pragma pop_macro("local_persist") | ||||||
| #pragma pop_macro("do_once_start") | #pragma pop_macro("do_once_start") | ||||||
| #pragma pop_macro("do_once_end") | #pragma pop_macro("do_once_end") | ||||||
|  |  | ||||||
| 	CodeNS    nspace     = def_namespace( name(ETokType), def_namespace_body( args( attribute_entires_def, enum_code, to_str, to_type ) ) ); | 	//CodeNS    nspace     = def_namespace( name(ETokType), def_namespace_body( args( attribute_entires_def, enum_code, to_str, to_type ) ) ); | ||||||
| 	CodeUsing td_toktype = def_using( name(TokType), def_type( name(ETokType::Type) ) ); | 	CodeTypedef td_toktype = parse_typedef( code( typedef enum TokType_Def TokType; )); | ||||||
|  |  | ||||||
| 	return def_global_body( args( nspace, td_toktype ) ); | 	return def_global_body( args( | ||||||
|  | 		attribute_entires_def, | ||||||
|  | 		enum_code, | ||||||
|  | 		td_toktype, | ||||||
|  | 		to_str, | ||||||
|  | 		to_type | ||||||
|  | 	)); | ||||||
| } | } | ||||||
|  |  | ||||||
| CodeBody gen_ast_inlines() | CodeBody gen_ast_inlines() | ||||||
| { | { | ||||||
|  | #pragma push_macro("GEN_NS") | ||||||
| #pragma push_macro("rcast") | #pragma push_macro("rcast") | ||||||
| #pragma push_macro("log_failure") | #pragma push_macro("log_failure") | ||||||
|  | #pragma push_macro("CodeInvalid") | ||||||
|  | #undef GEN_NS | ||||||
| #undef rcast | #undef rcast | ||||||
| #undef log_failure | #undef log_failure | ||||||
|  | #undef CodeInvalid | ||||||
| 	char const* code_impl_tmpl = stringize( | 	char const* code_impl_tmpl = stringize( | ||||||
| 		\n | 		\n | ||||||
| 		inline | 		inline | ||||||
| 		char const* <typename>::debug_str() |  | ||||||
| 		{ |  | ||||||
| 			if ( ast == nullptr ) |  | ||||||
| 				return "Code::debug_str: AST is null!"; |  | ||||||
|  |  | ||||||
| 			return rcast(AST*, ast)->debug_str(); |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		Code <typename>::duplicate() |  | ||||||
| 		{ |  | ||||||
| 			if ( ast == nullptr ) |  | ||||||
| 			{ |  | ||||||
| 				log_failure("Code::duplicate: Cannot duplicate code, AST is null!"); |  | ||||||
| 				return Code::Invalid; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			return { rcast(AST*, ast)->duplicate() }; |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		bool <typename>::is_equal( Code other ) |  | ||||||
| 		{ |  | ||||||
| 			if ( ast == nullptr || other.ast == nullptr ) |  | ||||||
| 			{ |  | ||||||
| 				// Just check if they're both null. |  | ||||||
| 				// log_failure( "Code::is_equal: Cannot compare code, AST is null!" ); |  | ||||||
| 				return ast == nullptr && other.ast == nullptr; |  | ||||||
| 			} |  | ||||||
| 			return rcast(AST*, ast)->is_equal( other.ast ); |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		bool <typename>::is_valid() |  | ||||||
| 		{ |  | ||||||
| 			return (AST*) ast != nullptr && rcast( AST*, ast)->Type != CodeT::Invalid; |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		void <typename>::set_global() |  | ||||||
| 		{ |  | ||||||
| 			if ( ast == nullptr ) |  | ||||||
| 			{ |  | ||||||
| 				log_failure("Code::set_global: Cannot set code as global, AST is null!"); |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			rcast(AST*, ast)->Parent = Code::Global.ast; |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		<typename>& <typename>::operator =( Code other ) | 		<typename>& <typename>::operator =( Code other ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( other.ast && other->Parent ) | 			if ( other.ast && other->Parent ) | ||||||
| 			{ | 			{ | ||||||
| 				ast = rcast( decltype(ast), other.ast->duplicate() ); | 				ast         = rcast( decltype(ast),  GEN_NS duplicate(other).ast); | ||||||
| 				rcast( AST*, ast)->Parent = nullptr; | 				ast->Parent = { nullptr }; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			ast = rcast( decltype( ast ), other.ast ); | 			ast = rcast( decltype( ast ), other.ast ); | ||||||
| 			return * this; | 			return * this; | ||||||
| 		} | 		} | ||||||
| 		inline | 		inline | ||||||
| 		bool <typename>::operator ==( Code other ) |  | ||||||
| 		{ |  | ||||||
| 			return (AST*) ast == other.ast; |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		bool <typename>::operator !=( Code other ) |  | ||||||
| 		{ |  | ||||||
| 			return (AST*) ast != other.ast; |  | ||||||
| 		} |  | ||||||
| 		inline |  | ||||||
| 		<typename>::operator bool() | 		<typename>::operator bool() | ||||||
| 		{ | 		{ | ||||||
| 			return ast != nullptr; | 			return ast != nullptr; | ||||||
| @@ -422,11 +382,6 @@ CodeBody gen_ast_inlines() | |||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	char const* codetype_impl_tmpl = stringize( | 	char const* codetype_impl_tmpl = stringize( | ||||||
| 		inline |  | ||||||
| 		AST* Code<typename>::raw() |  | ||||||
| 		{ |  | ||||||
| 			return rcast( AST*, ast ); |  | ||||||
| 		} |  | ||||||
| 		inline | 		inline | ||||||
| 		Code<typename>::operator Code() | 		Code<typename>::operator Code() | ||||||
| 		{ | 		{ | ||||||
| @@ -444,6 +399,8 @@ CodeBody gen_ast_inlines() | |||||||
| 		} | 		} | ||||||
| 		\n | 		\n | ||||||
| 	); | 	); | ||||||
|  | #pragma pop_macro("GEN_NS") | ||||||
|  | #pragma pop_macro("CodeInvalid") | ||||||
|  |  | ||||||
| 	CodeBody impl_code          = parse_global_body( token_fmt( "typename", StrC name(Code),               code_impl_tmpl )); | 	CodeBody impl_code          = parse_global_body( token_fmt( "typename", StrC name(Code),               code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_body     = parse_global_body( token_fmt( "typename", StrC name(CodeBody),           code_impl_tmpl )); | 	CodeBody impl_code_body     = parse_global_body( token_fmt( "typename", StrC name(CodeBody),           code_impl_tmpl )); | ||||||
| @@ -469,41 +426,37 @@ CodeBody gen_ast_inlines() | |||||||
| 	CodeBody impl_code_specs    = parse_global_body( token_fmt( "typename", StrC name(CodeSpecifiers),     code_impl_tmpl )); | 	CodeBody impl_code_specs    = parse_global_body( token_fmt( "typename", StrC name(CodeSpecifiers),     code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_struct   = parse_global_body( token_fmt( "typename", StrC name(CodeStruct),         code_impl_tmpl )); | 	CodeBody impl_code_struct   = parse_global_body( token_fmt( "typename", StrC name(CodeStruct),         code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_tmpl     = parse_global_body( token_fmt( "typename", StrC name(CodeTemplate),       code_impl_tmpl )); | 	CodeBody impl_code_tmpl     = parse_global_body( token_fmt( "typename", StrC name(CodeTemplate),       code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_type     = parse_global_body( token_fmt( "typename", StrC name(CodeType),           code_impl_tmpl )); | 	CodeBody impl_code_type     = parse_global_body( token_fmt( "typename", StrC name(CodeTypename),       code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_typedef  = parse_global_body( token_fmt( "typename", StrC name(CodeTypedef),        code_impl_tmpl )); | 	CodeBody impl_code_typedef  = parse_global_body( token_fmt( "typename", StrC name(CodeTypedef),        code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_union    = parse_global_body( token_fmt( "typename", StrC name(CodeUnion),          code_impl_tmpl )); | 	CodeBody impl_code_union    = parse_global_body( token_fmt( "typename", StrC name(CodeUnion),          code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_using    = parse_global_body( token_fmt( "typename", StrC name(CodeUsing),          code_impl_tmpl )); | 	CodeBody impl_code_using    = parse_global_body( token_fmt( "typename", StrC name(CodeUsing),          code_impl_tmpl )); | ||||||
| 	CodeBody impl_code_var      = parse_global_body( token_fmt( "typename", StrC name(CodeVar),            code_impl_tmpl )); | 	CodeBody impl_code_var      = parse_global_body( token_fmt( "typename", StrC name(CodeVar),            code_impl_tmpl )); | ||||||
|  |  | ||||||
| 	impl_code_attr.    append( parse_global_body( token_fmt( "typename", StrC name(Attributes),     codetype_impl_tmpl ))); | 	append(impl_code_attr,     parse_global_body( token_fmt( "typename", StrC name(Attributes),     codetype_impl_tmpl ))); | ||||||
| 	impl_code_cmt.     append( parse_global_body( token_fmt( "typename", StrC name(Comment),        codetype_impl_tmpl ))); | 	append(impl_code_cmt,      parse_global_body( token_fmt( "typename", StrC name(Comment),        codetype_impl_tmpl ))); | ||||||
| 	impl_code_constr.  append( parse_global_body( token_fmt( "typename", StrC name(Constructor),    codetype_impl_tmpl ))); | 	append(impl_code_constr,   parse_global_body( token_fmt( "typename", StrC name(Constructor),    codetype_impl_tmpl ))); | ||||||
| 	impl_code_define.  append( parse_global_body( token_fmt( "typename", StrC name(Define),         codetype_impl_tmpl ))); | 	append(impl_code_define,   parse_global_body( token_fmt( "typename", StrC name(Define),         codetype_impl_tmpl ))); | ||||||
| 	impl_code_destruct.append( parse_global_body( token_fmt( "typename", StrC name(Destructor),     codetype_impl_tmpl ))); | 	append(impl_code_destruct, parse_global_body( token_fmt( "typename", StrC name(Destructor),     codetype_impl_tmpl ))); | ||||||
| 	impl_code_enum.    append( parse_global_body( token_fmt( "typename", StrC name(Enum),           codetype_impl_tmpl ))); | 	append(impl_code_enum,     parse_global_body( token_fmt( "typename", StrC name(Enum),           codetype_impl_tmpl ))); | ||||||
| 	impl_code_exec.    append( parse_global_body( token_fmt( "typename", StrC name(Exec),           codetype_impl_tmpl ))); | 	append(impl_code_exec,     parse_global_body( token_fmt( "typename", StrC name(Exec),           codetype_impl_tmpl ))); | ||||||
| 	impl_code_extern.  append( parse_global_body( token_fmt( "typename", StrC name(Extern),         codetype_impl_tmpl ))); | 	append(impl_code_extern,   parse_global_body( token_fmt( "typename", StrC name(Extern),         codetype_impl_tmpl ))); | ||||||
| 	impl_code_include. append( parse_global_body( token_fmt( "typename", StrC name(Include),        codetype_impl_tmpl ))); | 	append(impl_code_include,  parse_global_body( token_fmt( "typename", StrC name(Include),        codetype_impl_tmpl ))); | ||||||
| 	impl_code_friend.  append( parse_global_body( token_fmt( "typename", StrC name(Friend),         codetype_impl_tmpl ))); | 	append(impl_code_friend,   parse_global_body( token_fmt( "typename", StrC name(Friend),         codetype_impl_tmpl ))); | ||||||
| 	impl_code_fn.      append( parse_global_body( token_fmt( "typename", StrC name(Fn),             codetype_impl_tmpl ))); | 	append(impl_code_fn,       parse_global_body( token_fmt( "typename", StrC name(Fn),             codetype_impl_tmpl ))); | ||||||
| 	impl_code_module.  append( parse_global_body( token_fmt( "typename", StrC name(Module),         codetype_impl_tmpl ))); | 	append(impl_code_module,   parse_global_body( token_fmt( "typename", StrC name(Module),         codetype_impl_tmpl ))); | ||||||
| 	impl_code_ns.      append( parse_global_body( token_fmt( "typename", StrC name(NS),             codetype_impl_tmpl ))); | 	append(impl_code_ns,       parse_global_body( token_fmt( "typename", StrC name(NS),             codetype_impl_tmpl ))); | ||||||
| 	impl_code_op.      append( parse_global_body( token_fmt( "typename", StrC name(Operator),       codetype_impl_tmpl ))); | 	append(impl_code_op,       parse_global_body( token_fmt( "typename", StrC name(Operator),       codetype_impl_tmpl ))); | ||||||
| 	impl_code_opcast.  append( parse_global_body( token_fmt( "typename", StrC name(OpCast),         codetype_impl_tmpl ))); | 	append(impl_code_opcast,   parse_global_body( token_fmt( "typename", StrC name(OpCast),         codetype_impl_tmpl ))); | ||||||
| 	impl_code_pragma . append( parse_global_body( token_fmt( "typename", StrC name(Pragma),         codetype_impl_tmpl ))); | 	append(impl_code_pragma,   parse_global_body( token_fmt( "typename", StrC name(Pragma),         codetype_impl_tmpl ))); | ||||||
| 	impl_code_precond. append( parse_global_body( token_fmt( "typename", StrC name(PreprocessCond), codetype_impl_tmpl ))); | 	append(impl_code_precond,  parse_global_body( token_fmt( "typename", StrC name(PreprocessCond), codetype_impl_tmpl ))); | ||||||
| 	impl_code_tmpl.    append( parse_global_body( token_fmt( "typename", StrC name(Template),       codetype_impl_tmpl ))); | 	append(impl_code_tmpl,     parse_global_body( token_fmt( "typename", StrC name(Template),       codetype_impl_tmpl ))); | ||||||
| 	impl_code_type.    append( parse_global_body( token_fmt( "typename", StrC name(Type),           codetype_impl_tmpl ))); | 	append(impl_code_type,     parse_global_body( token_fmt( "typename", StrC name(Typename),       codetype_impl_tmpl ))); | ||||||
| 	impl_code_typedef. append( parse_global_body( token_fmt( "typename", StrC name(Typedef),        codetype_impl_tmpl ))); | 	append(impl_code_typedef,  parse_global_body( token_fmt( "typename", StrC name(Typedef),        codetype_impl_tmpl ))); | ||||||
| 	impl_code_union.   append( parse_global_body( token_fmt( "typename", StrC name(Union),          codetype_impl_tmpl ))); | 	append(impl_code_union,    parse_global_body( token_fmt( "typename", StrC name(Union),          codetype_impl_tmpl ))); | ||||||
| 	impl_code_using.   append( parse_global_body( token_fmt( "typename", StrC name(Using),          codetype_impl_tmpl ))); | 	append(impl_code_using,    parse_global_body( token_fmt( "typename", StrC name(Using),          codetype_impl_tmpl ))); | ||||||
| 	impl_code_var.     append( parse_global_body( token_fmt( "typename", StrC name(Var),            codetype_impl_tmpl ))); | 	append(impl_code_var,      parse_global_body( token_fmt( "typename", StrC name(Var),            codetype_impl_tmpl ))); | ||||||
|  |  | ||||||
| 	char const* cast_tmpl = stringize( | 	char const* cast_tmpl = stringize( | ||||||
| 		inline	AST::operator Code<typename>() |  | ||||||
| 		{ |  | ||||||
| 			return { rcast( AST_<typename>*, this ) }; |  | ||||||
| 		} |  | ||||||
| 		inline Code::operator Code<typename>() const | 		inline Code::operator Code<typename>() const | ||||||
| 		{ | 		{ | ||||||
| 			return { (AST_<typename>*) ast }; | 			return { (AST_<typename>*) ast }; | ||||||
| @@ -533,7 +486,7 @@ CodeBody gen_ast_inlines() | |||||||
| 	CodeBody impl_cast_specs     = parse_global_body( token_fmt( "typename", StrC name(Specifiers),     cast_tmpl )); | 	CodeBody impl_cast_specs     = parse_global_body( token_fmt( "typename", StrC name(Specifiers),     cast_tmpl )); | ||||||
| 	CodeBody impl_cast_struct    = parse_global_body( token_fmt( "typename", StrC name(Struct),         cast_tmpl )); | 	CodeBody impl_cast_struct    = parse_global_body( token_fmt( "typename", StrC name(Struct),         cast_tmpl )); | ||||||
| 	CodeBody impl_cast_tmpl      = parse_global_body( token_fmt( "typename", StrC name(Template),       cast_tmpl )); | 	CodeBody impl_cast_tmpl      = parse_global_body( token_fmt( "typename", StrC name(Template),       cast_tmpl )); | ||||||
| 	CodeBody impl_cast_type      = parse_global_body( token_fmt( "typename", StrC name(Type),           cast_tmpl )); | 	CodeBody impl_cast_type      = parse_global_body( token_fmt( "typename", StrC name(Typename),       cast_tmpl )); | ||||||
| 	CodeBody impl_cast_typedef   = parse_global_body( token_fmt( "typename", StrC name(Typedef),        cast_tmpl )); | 	CodeBody impl_cast_typedef   = parse_global_body( token_fmt( "typename", StrC name(Typedef),        cast_tmpl )); | ||||||
| 	CodeBody impl_cast_union     = parse_global_body( token_fmt( "typename", StrC name(Union),          cast_tmpl )); | 	CodeBody impl_cast_union     = parse_global_body( token_fmt( "typename", StrC name(Union),          cast_tmpl )); | ||||||
| 	CodeBody impl_cast_using     = parse_global_body( token_fmt( "typename", StrC name(Using),          cast_tmpl )); | 	CodeBody impl_cast_using     = parse_global_body( token_fmt( "typename", StrC name(Using),          cast_tmpl )); | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								project/helpers/member_proc_support.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								project/helpers/member_proc_support.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "gen.hpp" | ||||||
|  |  | ||||||
|  | GEN_NS_BEGIN | ||||||
|  | #include "dependencies/parsing.hpp" | ||||||
|  | GEN_NS_END | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								project/helpers/pop_container_defines.inline.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								project/helpers/pop_container_defines.inline.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  |  | ||||||
|  | #undef array_init | ||||||
|  | #undef array_init_reserve | ||||||
|  | #undef array_append_array | ||||||
|  | #undef array_append | ||||||
|  | #undef array_append_items | ||||||
|  | #undef array_append_at | ||||||
|  | #undef array_append_items_at | ||||||
|  | #undef array_back | ||||||
|  | #undef array_clear | ||||||
|  | #undef array_fill | ||||||
|  | #undef array_free | ||||||
|  | #undef arary_grow | ||||||
|  | #undef array_num | ||||||
|  | #undef arary_pop | ||||||
|  | #undef arary_remove_at | ||||||
|  | #undef arary_reserve | ||||||
|  | #undef arary_resize | ||||||
|  | #undef arary_set_capacity | ||||||
|  | #undef arary_get_header | ||||||
|  |  | ||||||
|  | #undef hashtable_init | ||||||
|  | #undef hashtable_init_reserve | ||||||
|  | #undef hashtable_clear | ||||||
|  | #undef hashtable_destroy | ||||||
|  | #undef hashtable_get | ||||||
|  | #undef hashtable_grow | ||||||
|  | #undef hashtable_rehash | ||||||
|  | #undef hashtable_rehash_fast | ||||||
|  | #undef hashtable_remove | ||||||
|  | #undef hashtable_remove_entry | ||||||
|  | #undef hashtable_set | ||||||
|  | #undef hashtable_slot | ||||||
|  | #undef hashtable_map | ||||||
|  | #undef hashtable_map_mut | ||||||
|  |  | ||||||
|  | //#undef hashtable_add_entry | ||||||
|  | //#undef hashtable_find | ||||||
|  | //#undef hashtable_full | ||||||
							
								
								
									
										39
									
								
								project/helpers/push_container_defines.inline.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								project/helpers/push_container_defines.inline.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  |  | ||||||
|  | #define array_init(type, allocator)                        array_init           <type>                               (allocator ) | ||||||
|  | #define array_init_reserve(type, allocator, cap)           array_init_reserve   <type>                               (allocator, cap) | ||||||
|  | #define array_append_array(array, other)                   array_append_array   < get_array_underlying_type(array) > (& array, other ) | ||||||
|  | #define array_append(array, value)                         array_append         < get_array_underlying_type(array) > (& array, value ) | ||||||
|  | #define array_append_items(array, items, item_num)         array_append_items   < get_array_underlying_type(array) > (& array, items, item_num ) | ||||||
|  | #define array_append_at(array, item, idx )                 array_append_at      < get_array_underlying_type(array) > (& array, item, idx ) | ||||||
|  | #define array_append_at_items(array, items, item_num, idx) array_append_at_items< get_array_underlying_type(array) > (& items, item_num, idx ) | ||||||
|  | #define array_back(array)                                  array_back           < get_array_underlying_type(array) > (array ) | ||||||
|  | #define array_clear(array)                                 array_clear          < get_array_underlying_type(array) > (array ) | ||||||
|  | #define array_fill(array, begin, end, value)               array_fill           < get_array_underlying_type(array) > (array, begin, end, value ) | ||||||
|  | #define array_free(array)                                  array_free           < get_array_underlying_type(array) > (& array ) | ||||||
|  | #define arary_grow(array, min_capacity)                    arary_grow           < get_array_underlying_type(array) > (& array, min_capacity) | ||||||
|  | #define array_num(array)                                   array_num            < get_array_underlying_type(array) > (array ) | ||||||
|  | #define arary_pop(array)                                   arary_pop            < get_array_underlying_type(array) > (array ) | ||||||
|  | #define arary_remove_at(array, idx)                        arary_remove_at      < get_array_underlying_type(array) > (idx) | ||||||
|  | #define arary_reserve(array, new_capacity)                 arary_reserve        < get_array_underlying_type(array) > (& array, new_capacity ) | ||||||
|  | #define arary_resize(array, num)                           arary_resize         < get_array_underlying_type(array) > (& array, num) | ||||||
|  | #define arary_set_capacity(new_capacity)                   arary_set_capacity   < get_array_underlying_type(array) > (& array, new_capacity ) | ||||||
|  | #define arary_get_header(array)                            arary_get_header     < get_array_underlying_type(array) > (array ) | ||||||
|  |  | ||||||
|  | #define hashtable_init(type, allocator)              hashtable_init        <type              >(allocator) | ||||||
|  | #define hashtable_init_reserve(type, allocator, num) hashtable_init_reserve<type              >(allocator, num) | ||||||
|  | #define hashtable_clear(table)                       hashtable_clear       < get_hashtable_underlying_type(table) >(table) | ||||||
|  | #define hashtable_destroy(table)                     hashtable_destroy     < get_hashtable_underlying_type(table) >(& table) | ||||||
|  | #define hashtable_get(table, key)                    hashtable_get         < get_hashtable_underlying_type(table) >(table, key) | ||||||
|  | #define hashtable_grow(table)                        hashtable_grow        < get_hashtable_underlying_type(table) >(& table) | ||||||
|  | #define hashtable_rehash(table, new_num)             hashtable_rehash      < get_hashtable_underlying_type(table) >(& table, new_num) | ||||||
|  | #define hashtable_rehash_fast(table)                 hashtable_rehash_fast < get_hashtable_underlying_type(table) >(table) | ||||||
|  | #define hashtable_remove(table, key)                 hashtable_remove      < get_hashtable_underlying_type(table) >(table, key) | ||||||
|  | #define hashtable_remove_entry(table, idx)           hashtable_remove_entry< get_hashtable_underlying_type(table) >(table, idx) | ||||||
|  | #define hashtable_set(table, key, value)             hashtable_set         < get_hashtable_underlying_type(table) >(& table, key, value) | ||||||
|  | #define hashtable_slot(table, key)                   hashtable_slot        < get_hashtable_underlying_type(table) >(table, key) | ||||||
|  | #define hashtable_map(table, map_proc)               hashtable_map         < get_hashtable_underlying_type(table) >(table, map_proc) | ||||||
|  | #define hashtable_map_mut(table, map_proc)           hashtable_map_mut     < get_hashtable_underlying_type(table) >(table, map_proc) | ||||||
|  |  | ||||||
|  | //#define hashtable_add_entry(table, key)              hashtable_add_entry   < get_hashtable_underlying_type(table) >(& table, key) | ||||||
|  | //#define hashtable_find(table, key)                   hashtable_find        < get_hashtable_underlying_type(table) >(table, key) | ||||||
|  | //#define hashtable_full(table)                        hashtable_full        < get_hashtable_underlying_type(table) >(table) | ||||||
| @@ -7,6 +7,8 @@ | |||||||
| #   pragma clang diagnostic ignored "-Wunknown-pragmas" | #   pragma clang diagnostic ignored "-Wunknown-pragmas" | ||||||
| #	pragma clang diagnostic ignored "-Wvarargs" | #	pragma clang diagnostic ignored "-Wvarargs" | ||||||
| #	pragma clang diagnostic ignored "-Wunused-function" | #	pragma clang diagnostic ignored "-Wunused-function" | ||||||
|  | #	pragma clang diagnostic ignored "-Wbraced-scalar-init" | ||||||
|  | #   pragma clang diagnostic ignored "-W#pragma-messages" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef __GNUC__ | #ifdef __GNUC__ | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ Push-Location $path_root | |||||||
| 	   $verbose      = $false | 	   $verbose      = $false | ||||||
| [bool] $bootstrap    = $false | [bool] $bootstrap    = $false | ||||||
| [bool] $singleheader = $false | [bool] $singleheader = $false | ||||||
|  | [bool] $c_library    = $false | ||||||
| [bool] $unreal       = $false | [bool] $unreal       = $false | ||||||
| [bool] $test         = $false | [bool] $test         = $false | ||||||
|  |  | ||||||
| @@ -59,6 +60,7 @@ if ( $args ) { $args | ForEach-Object { | |||||||
| 		"debug"               { $release      = $false } | 		"debug"               { $release      = $false } | ||||||
| 		"bootstrap"           { $bootstrap    = $true } | 		"bootstrap"           { $bootstrap    = $true } | ||||||
| 		"singleheader"        { $singleheader = $true } | 		"singleheader"        { $singleheader = $true } | ||||||
|  | 		"c_library"           { $c_library    = $true } | ||||||
| 		"unreal"              { $unreal       = $true } | 		"unreal"              { $unreal       = $true } | ||||||
| 		"test"                { $test         = $true } | 		"test"                { $test         = $true } | ||||||
| 	} | 	} | ||||||
| @@ -88,7 +90,7 @@ else { | |||||||
| 	$optimize = $true | 	$optimize = $true | ||||||
| } | } | ||||||
|  |  | ||||||
| if ( $bootstrap -eq $false -and $singleheader -eq $false -and $unreal -eq $false -and $test -eq $false ) { | if ( $bootstrap -eq $false -and $singleheader -eq $false -and $c_library -eq $false -and $unreal -eq $false -and $test -eq $false ) { | ||||||
| 	throw "No build target specified. One must be specified, this script will not assume one" | 	throw "No build target specified. One must be specified, this script will not assume one" | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -103,8 +105,9 @@ write-host "Build Type: $(if ($release) {"Release"} else {"Debug"} )" | |||||||
| $path_build        = Join-Path $path_root build | $path_build        = Join-Path $path_root build | ||||||
| $path_project      = Join-Path $path_root project | $path_project      = Join-Path $path_root project | ||||||
| $path_scripts      = Join-Path $path_root scripts | $path_scripts      = Join-Path $path_root scripts | ||||||
| $path_singleheader = Join-Path $path_root singleheader | $path_c_library    = join-Path $path_root gen_c_library | ||||||
| $path_unreal       = Join-Path $path_root unreal_engine | $path_singleheader = Join-Path $path_root gen_singleheader | ||||||
|  | $path_unreal       = Join-Path $path_root gen_unreal_engine | ||||||
| $path_test         = Join-Path $path_root test | $path_test         = Join-Path $path_root test | ||||||
|  |  | ||||||
| if ( $bootstrap ) | if ( $bootstrap ) | ||||||
| @@ -134,7 +137,7 @@ if ( $bootstrap ) | |||||||
| 	$unit       = join-path $path_project "bootstrap.cpp" | 	$unit       = join-path $path_project "bootstrap.cpp" | ||||||
| 	$executable = join-path $path_build   "bootstrap.exe" | 	$executable = join-path $path_build   "bootstrap.exe" | ||||||
|  |  | ||||||
| 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | 	$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
| 	Push-Location $path_project | 	Push-Location $path_project | ||||||
| 		if ( Test-Path( $executable ) ) { | 		if ( Test-Path( $executable ) ) { | ||||||
| @@ -172,7 +175,7 @@ if ( $singleheader ) | |||||||
| 		$flag_link_win_subsystem_console | 		$flag_link_win_subsystem_console | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | 	$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
| 	Push-Location $path_singleheader | 	Push-Location $path_singleheader | ||||||
| 		if ( Test-Path( $executable ) ) { | 		if ( Test-Path( $executable ) ) { | ||||||
| @@ -187,6 +190,71 @@ if ( $singleheader ) | |||||||
| 	Pop-Location | 	Pop-Location | ||||||
| } | } | ||||||
|  |  | ||||||
|  | if ( $c_library ) | ||||||
|  | { | ||||||
|  | 	$path_build = join-path $path_c_library build | ||||||
|  | 	$path_gen   = join-path $path_c_library gen | ||||||
|  |  | ||||||
|  | 	if ( -not(Test-Path($path_build) )) { | ||||||
|  | 		New-Item -ItemType Directory -Path $path_build | ||||||
|  | 	} | ||||||
|  | 	if ( -not(Test-Path($path_gen) )) { | ||||||
|  | 		New-Item -ItemType Directory -Path $path_gen | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$includes    = @( $path_project ) | ||||||
|  | 	$unit       = join-path $path_c_library "c_library.cpp" | ||||||
|  | 	$executable = join-path $path_build     "c_library.exe" | ||||||
|  |  | ||||||
|  | 	$compiler_args = @() | ||||||
|  | 	$compiler_args += ( $flag_define + 'GEN_TIME' ) | ||||||
|  |  | ||||||
|  | 	$linker_args   = @( | ||||||
|  | 		$flag_link_win_subsystem_console | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
|  | 	Push-Location $path_c_library | ||||||
|  | 		if ( Test-Path( $executable ) ) { | ||||||
|  | 			write-host "`nRunning c_library generator" | ||||||
|  | 			$time_taken = Measure-Command { & $executable | ||||||
|  | 					| ForEach-Object { | ||||||
|  | 						write-host `t $_ -ForegroundColor Green | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms" | ||||||
|  | 		} | ||||||
|  | 	Pop-Location | ||||||
|  |  | ||||||
|  | 	$unit       = join-path $path_c_library "gen.c" | ||||||
|  | 	$executable = join-path $path_build     "gen_c_library_test.exe" | ||||||
|  |  | ||||||
|  | 	if ($vendor -eq "clang") { | ||||||
|  | 		$compiler_args += '-x' | ||||||
|  | 		$compiler_args += 'c' | ||||||
|  | 		$compiler_args += '-std=c11' | ||||||
|  | 	} elseif ($vendor -eq "msvc") { | ||||||
|  | 		$compiler_args += "/TC"       # Compile as C | ||||||
|  | 		$compiler_args += "/Zc:__cplusplus" # Fix __cplusplus macro | ||||||
|  | 		$compiler_args += "/std:c11" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
|  | 	Push-Location $path_c_library | ||||||
|  | 		if ( Test-Path( $executable ) ) { | ||||||
|  | 			write-host "`nRunning c_library test" | ||||||
|  | 			$time_taken = Measure-Command { & $executable | ||||||
|  | 					| ForEach-Object { | ||||||
|  | 						write-host `t $_ -ForegroundColor Green | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms" | ||||||
|  | 		} | ||||||
|  | 	Pop-Location | ||||||
|  | } | ||||||
|  |  | ||||||
| if ( $unreal ) | if ( $unreal ) | ||||||
| { | { | ||||||
| 	$path_build = join-path $path_unreal build | 	$path_build = join-path $path_unreal build | ||||||
| @@ -210,7 +278,7 @@ if ( $unreal ) | |||||||
| 		$flag_link_win_subsystem_console | 		$flag_link_win_subsystem_console | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | 	$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
| 	Push-Location $path_unreal | 	Push-Location $path_unreal | ||||||
| 		if ( Test-Path( $executable ) ) { | 		if ( Test-Path( $executable ) ) { | ||||||
| @@ -272,7 +340,7 @@ if ( $test ) | |||||||
| 		$flag_link_win_subsystem_console | 		$flag_link_win_subsystem_console | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | 	$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
| 	Push-Location $path_test | 	Push-Location $path_test | ||||||
| 		Write-Host $path_test | 		Write-Host $path_test | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								scripts/c_library.refactor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								scripts/c_library.refactor
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  |  __VERSION 1 | ||||||
|  |  | ||||||
|  | // This is a example template to be used with the refactor program | ||||||
|  | // Use it to refactor the naming convention of this library to your own. | ||||||
|  | // Can be used as an aid to help use use your project's implementation if it fullfills the dependencies of this project. | ||||||
|  | // Example: Most likely have a memory and string library already, just rename the functions and make sure the args are the same. | ||||||
|  | // Program: https://github.com/Ed94/refactor | ||||||
|  |  | ||||||
|  | // NOTE: Due to the current limitations of the program, not every symbol in the library can be renamed. | ||||||
|  | // This is due to the program not actually parsing C/C++. | ||||||
|  |  | ||||||
|  | // not       : Ignore | ||||||
|  | // include   : #includes | ||||||
|  | // word      : Alphanumeric or underscore | ||||||
|  | // namespace : Prefix search and replace (c-namspaces). | ||||||
|  | // regex     : Unavailable in __VERSION 1. | ||||||
|  |  | ||||||
|  | // Precedence (highest to lowest): | ||||||
|  | // word, namespace, regex | ||||||
|  |  | ||||||
|  | // Gen Macro namespace | ||||||
|  | // namespace GEN_, new_namespace_ | ||||||
|  |  | ||||||
|  | // TODO(Ed): This will be large as nearly all symbols will need to optionally support getting prefixed with gen_ or something else the user wants. | ||||||
| @@ -253,7 +253,7 @@ | |||||||
|  |  | ||||||
| // word log_failure, new_name | // word log_failure, new_name | ||||||
|  |  | ||||||
| // word NoCode,      new_name | // word NullCode,      new_name | ||||||
| // word CodeInvalid, new_name | // word CodeInvalid, new_name | ||||||
|  |  | ||||||
| // ------------ gencpp common | // ------------ gencpp common | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								scripts/refactor_c_library.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								scripts/refactor_c_library.ps1
									
									
									
									
									
										Normal file
									
								
							| @@ -1,23 +0,0 @@ | |||||||
| /* |  | ||||||
| 	gencpp: An attempt at "simple" staged metaprogramming for c/c++. |  | ||||||
|  |  | ||||||
| 	See Readme.md for more information from the project repository. |  | ||||||
|  |  | ||||||
| 	Public Address: |  | ||||||
| 	https://github.com/Ed94/gencpp |  | ||||||
|  |  | ||||||
| 	This is a single header variant of the library. |  | ||||||
| 	Define GEN_IMPLEMENTATION before including this file in a single compilation unit. |  | ||||||
| */ |  | ||||||
| #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) |  | ||||||
| #	error Gen.hpp : GEN_TIME not defined |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef GEN_DONT_USE_NAMESPACE |  | ||||||
| #	define GEN_NS_BEGIN |  | ||||||
| #	define GEN_NS_END |  | ||||||
| #else |  | ||||||
| #	define GEN_NS_BEGIN namespace gen { |  | ||||||
| #	define GEN_NS_END   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| @@ -50,7 +50,7 @@ u32 gen_sanity_upfront() | |||||||
|  |  | ||||||
| 	// Enum | 	// Enum | ||||||
| 	{ | 	{ | ||||||
| 		CodeEnum fwd = def_enum( name(ETestEnum), NoCode, t_u8 ); | 		CodeEnum fwd = def_enum( name(ETestEnum), NullCode, t_u8 ); | ||||||
| 		CodeEnum def; | 		CodeEnum def; | ||||||
| 		{ | 		{ | ||||||
| 			Code body = untyped_str( code( | 			Code body = untyped_str( code( | ||||||
| @@ -62,7 +62,7 @@ u32 gen_sanity_upfront() | |||||||
| 			def = def_enum( name(ETestEnum), body, t_u8 ); | 			def = def_enum( name(ETestEnum), body, t_u8 ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		CodeEnum fwd_enum_class = def_enum( name(ETestEnumClass), NoCode, t_u8, EnumClass ); | 		CodeEnum fwd_enum_class = def_enum( name(ETestEnumClass), NullCode, t_u8, EnumClass ); | ||||||
|  |  | ||||||
| 		gen_sanity_file.print(fwd); | 		gen_sanity_file.print(fwd); | ||||||
| 		gen_sanity_file.print(def); | 		gen_sanity_file.print(def); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user