mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 22:40:54 -07:00 
			
		
		
		
	WIP: Still reworking based on design changes.
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| #define BLOAT_IMPL | ||||
| #include "Bloat.hpp" | ||||
|  | ||||
|  | ||||
| namespace Global | ||||
| { | ||||
| 	bool ShouldShowDebug = false; | ||||
| @@ -40,131 +41,88 @@ namespace Memory | ||||
| } | ||||
|  | ||||
|  | ||||
| bool opts_custom_add(opts* options, opts_entry *t, char* b) | ||||
| struct TokEntry | ||||
| { | ||||
| 	if (t->type != ZPL_OPTS_STRING) | ||||
| 	{ | ||||
| 		return false;    | ||||
| 	} | ||||
| 	char const* Str; | ||||
| 	s32         Length; | ||||
| }; | ||||
|  | ||||
| 	t->text = string_append_length(t->text, " ", 1); | ||||
| 	t->text = string_appendc( t->text, b ); | ||||
| ZPL_TABLE( static, TokMap, tokmap_, TokEntry ) | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| b32 opts_custom_compile(opts *options, int argc, char **argv)  | ||||
| sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_list va ) | ||||
| { | ||||
| 	b32 had_errors = false; | ||||
| 	char const* buf_begin = buf; | ||||
| 	sw          remaining = buf_size; | ||||
|  | ||||
| 	for (int i = 1; i < argc; ++i)  | ||||
| 	TokMap tok_map; | ||||
| 	{ | ||||
| 		char* arg = argv[i]; | ||||
| 	 | ||||
| 		if (*arg)  | ||||
| 		tokmap_init( & tok_map, g_allocator ); | ||||
|  | ||||
| 		s32 left = num_tokens; | ||||
|  | ||||
| 		while ( left-- ) | ||||
| 		{ | ||||
| 			arg = (char*)str_trim(arg, false); | ||||
| 			char const* token = va_arg( va, char const* ); | ||||
| 			char const* value = va_arg( va, char const* ); | ||||
|  | ||||
| 			if (*arg == '-')  | ||||
| 			{ | ||||
| 				opts_entry* entry = 0; | ||||
| 				b32 checkln = false; | ||||
| 				if ( *(arg + 1) == '-')  | ||||
| 				{ | ||||
| 					checkln = true; | ||||
| 					++arg; | ||||
| 				} | ||||
| 			TokEntry entry  | ||||
| 			{  | ||||
| 				value, | ||||
| 				zpl_strnlen(value, 128)  | ||||
| 			}; | ||||
|  | ||||
| 				char *b = arg + 1, *e = b; | ||||
| 			u32 key = crc32( token, zpl_strnlen(token, 32) ); | ||||
|  | ||||
| 				while (char_is_alphanumeric(*e) || *e == '-' || *e == '_') { | ||||
| 					++e; | ||||
| 				} | ||||
|  | ||||
| 				entry = zpl__opts_find(options, b, (e - b), checkln); | ||||
|  | ||||
| 				if (entry)  | ||||
| 				{ | ||||
| 					char *ob = b; | ||||
| 					b = e; | ||||
|  | ||||
| 					/**/  | ||||
| 					if (*e == '=')  | ||||
| 					{ | ||||
| 						if (entry->type == ZPL_OPTS_FLAG)  | ||||
| 						{ | ||||
| 							*e = '\0'; | ||||
| 							zpl__opts_push_error(options, ob, ZPL_OPTS_ERR_EXTRA_VALUE); | ||||
| 							had_errors = true; | ||||
|  | ||||
| 							continue; | ||||
| 						} | ||||
|  | ||||
| 						b = e = e + 1; | ||||
| 					}  | ||||
| 					else if (*e == '\0')  | ||||
| 					{ | ||||
| 						char *sp = argv[i+1]; | ||||
|  | ||||
| 						if (sp && *sp != '-' && (array_count(options->positioned) < 1  || entry->type != ZPL_OPTS_FLAG))  | ||||
| 						{ | ||||
| 							if (entry->type == ZPL_OPTS_FLAG)  | ||||
| 							{ | ||||
| 								zpl__opts_push_error(options, b, ZPL_OPTS_ERR_EXTRA_VALUE); | ||||
| 								had_errors = true; | ||||
|  | ||||
| 								continue; | ||||
| 							} | ||||
|  | ||||
| 							arg = sp; | ||||
| 							b = e = sp; | ||||
| 							++i; | ||||
| 						}  | ||||
| 						else  | ||||
| 						{ | ||||
| 							if (entry->type != ZPL_OPTS_FLAG)  | ||||
| 							{ | ||||
| 								zpl__opts_push_error(options, ob, ZPL_OPTS_ERR_MISSING_VALUE); | ||||
| 								had_errors = true; | ||||
| 								continue; | ||||
| 							} | ||||
|  | ||||
| 							entry->met = true; | ||||
|  | ||||
| 							continue; | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					e = (char *)str_control_skip(e, '\0'); | ||||
| 					zpl__opts_set_value(options, entry, b); | ||||
|  | ||||
| 					if ( (i + 1) < argc ) | ||||
| 					{ | ||||
| 						for ( b = argv[i + 1]; i < argc && b[0] != '-'; i++, b = argv[i + 1] ) | ||||
| 						{ | ||||
| 							opts_custom_add(options, entry, b ); | ||||
| 						} | ||||
| 					} | ||||
| 				}  | ||||
| 				else  | ||||
| 				{ | ||||
| 					zpl__opts_push_error(options, b, ZPL_OPTS_ERR_OPTION); | ||||
| 					had_errors = true; | ||||
| 				} | ||||
| 			}  | ||||
| 			else if (array_count(options->positioned))  | ||||
| 			{ | ||||
| 				opts_entry *l = array_back(options->positioned); | ||||
| 				array_pop(options->positioned); | ||||
| 				zpl__opts_set_value(options, l, arg); | ||||
| 			}  | ||||
| 			else  | ||||
| 			{ | ||||
| 				zpl__opts_push_error(options, arg, ZPL_OPTS_ERR_VALUE); | ||||
| 				had_errors = true; | ||||
| 			} | ||||
| 			tokmap_set( & tok_map, key, entry ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return !had_errors; | ||||
| 	sw   result  = 0; | ||||
| 	char current = *fmt; | ||||
|  | ||||
| 	while ( current ) | ||||
| 	{ | ||||
| 		sw len = 0; | ||||
|  | ||||
| 		while ( current && current != '{' && remaining )  | ||||
| 		{ | ||||
| 			*buf = *fmt; | ||||
| 			buf++; | ||||
| 			fmt++; | ||||
|  | ||||
| 			current = *fmt; | ||||
| 		} | ||||
|  | ||||
| 		if ( current == '{' ) | ||||
| 		{ | ||||
| 			char const* scanner = fmt; | ||||
|  | ||||
| 			s32 tok_len = 0; | ||||
|  | ||||
| 			while ( *scanner != '}' ) | ||||
| 			{ | ||||
| 				tok_len++; | ||||
| 				scanner++; | ||||
| 			} | ||||
|  | ||||
| 			char const* token = fmt; | ||||
|  | ||||
| 			s32      key   = crc32( token, tok_len ); | ||||
| 			TokEntry value = * tokmap_get( & tok_map, key ); | ||||
| 			s32      left  = value.Length; | ||||
|  | ||||
| 			while ( left-- ) | ||||
| 			{ | ||||
| 				*buf = *value.Str; | ||||
| 				buf++; | ||||
| 				value.Str++; | ||||
| 			} | ||||
|  | ||||
| 			scanner++; | ||||
| 			fmt     = scanner;				 | ||||
| 			current = *fmt; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|   | ||||
| @@ -1,35 +1,15 @@ | ||||
| /* | ||||
| 	BLOAT. | ||||
|  | ||||
| 	This contians all definitions not directly related to the project. | ||||
| */ | ||||
|  | ||||
| #pragma once	 | ||||
|  | ||||
| #if defined(__GNUC__) || defined(__clang__) || 1 | ||||
|   // Supports 0-10 arguments | ||||
|   #define VA_NARGS_IMPL( _0,                          \ | ||||
| 	 _1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10, \ | ||||
| 	_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ | ||||
| 	_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ | ||||
| 	  N, ...) N  | ||||
|   // ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang) | ||||
|   #define VA_NARGS(...) VA_NARGS_IMPL(_, ## __VA_ARGS__, \ | ||||
|   	30, 29, 28, 27, 26, 25, 24, 23, 22, 21,              \ | ||||
| 	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,              \ | ||||
| 	10, 9, 8, 7, 6, 5, 4, 3, 2, 1,                       \ | ||||
| 	0)     | ||||
| 	                 | ||||
| #else | ||||
|   // Supports 1-10 arguments | ||||
|   #define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N | ||||
|   #define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) | ||||
| #endif | ||||
|  | ||||
| #define VA_NARGS2(...) ((int)(sizeof((int[]){ __VA_ARGS__ })/sizeof(int))) | ||||
|  | ||||
| #ifdef BLOAT_IMPL | ||||
| #	define ZPL_IMPLEMENTATION | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #pragma region 									ZPL INCLUDE | ||||
| #if __clang__ | ||||
| #	pragma clang diagnostic push  | ||||
| @@ -44,15 +24,15 @@ | ||||
| #		define ZPL_MODULE_CORE | ||||
| #		define ZPL_MODULE_TIMER | ||||
| #		define ZPL_MODULE_HASHING | ||||
| // #	define ZPL_MODULE_REGEX | ||||
| // #	define ZPL_MODULE_EVENT | ||||
| // #	define ZPL_MODULE_DLL | ||||
| #		define ZPL_MODULE_OPTS | ||||
| // #	define ZPL_MODULE_PROCESS | ||||
| // #	define ZPL_MODULE_MAT | ||||
| // #	define ZPL_MODULE_THREADING | ||||
| // #	define ZPL_MODULE_JOBS | ||||
| // #	define ZPL_MODULE_PARSER | ||||
| // #		define ZPL_MODULE_REGEX | ||||
| // #		define ZPL_MODULE_EVENT | ||||
| // #		define ZPL_MODULE_DLL | ||||
| // #		define ZPL_MODULE_OPTS | ||||
| // #		define ZPL_MODULE_PROCESS | ||||
| // #		define ZPL_MODULE_MAT | ||||
| // #		define ZPL_MODULE_THREADING | ||||
| // #		define ZPL_MODULE_JOBS | ||||
| // #		define ZPL_MODULE_PARSER | ||||
| #include "zpl.h" | ||||
|  | ||||
| #if __clang__ | ||||
| @@ -61,7 +41,6 @@ | ||||
| #pragma endregion 								ZPL INCLUDE | ||||
|  | ||||
|  | ||||
|  | ||||
| #if __clang__ | ||||
| #	pragma clang diagnostic ignored "-Wunused-const-variable" | ||||
| #	pragma clang diagnostic ignored "-Wswitch" | ||||
| @@ -70,16 +49,41 @@ | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #if defined(__GNUC__) || defined(__clang__) || 1 | ||||
|   // Supports 0-10 arguments | ||||
|   #define VA_NARGS_IMPL( _0,                          \ | ||||
| 	 _1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10, \ | ||||
| 	_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ | ||||
| 	_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ | ||||
| 	_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ | ||||
| 	_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ | ||||
| 	  N, ...) N  | ||||
|   // ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang) | ||||
|   #define VA_NARGS(...) VA_NARGS_IMPL(_, ## __VA_ARGS__, \ | ||||
|   	50, 49, 48, 47, 46, 45, 44, 43, 42, 41,              \ | ||||
|   	40, 39, 38, 37, 36, 35, 34, 33, 32, 31,              \ | ||||
|   	30, 29, 28, 27, 26, 25, 24, 23, 22, 21,              \ | ||||
| 	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,              \ | ||||
| 	10, 9, 8, 7, 6, 5, 4, 3, 2, 1,                       \ | ||||
| 	0)     | ||||
| #else | ||||
|   // Supports 1-10 arguments | ||||
|   #define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N | ||||
|   #define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) | ||||
| #endif | ||||
|  | ||||
| #define bit( Value_ )                      ( 1 << Value_ ) | ||||
| #define bitfield_is_equal( Field_, Mask_ ) ( ( Mask_ & Field_ ) == Mask_ ) | ||||
| #define ct                                 constexpr | ||||
| #define forceinline                        ZPL_ALWAYS_INLINE | ||||
| #define print_nl( _)                       zpl_printf("\n") | ||||
| #define ccast( Type_, Value_ )             * const_cast< Type_* >( & Value_ ) | ||||
| #define scast( Type_, Value_ )			   static_cast< Type_ >( Value_ ) | ||||
| #define rcast( Type_, Value_ )			   reinterpret_cast< Type_ >( Value_ ) | ||||
| #define pcast( Type_, Value_ )             ( * (Type_*)( & Value_ ) ) | ||||
| #define txt( Value_ )                      ZPL_STRINGIFY_EX( Value_ ) | ||||
| #define txt_impl( Value_ )                 #Value_ | ||||
| #define txt( Value_ )                      txt_impl( Value_ ) | ||||
| #define txt_with_length( Value_ )		   txt_impl( Value_ ), sizeof( txt_impl( Value_) ) | ||||
|  | ||||
| #define do_once()      \ | ||||
| do                     \ | ||||
| @@ -90,7 +94,7 @@ do                     \ | ||||
| 		return;        \ | ||||
| 	Done = true;       \ | ||||
| }                      \ | ||||
| while(0)               \ | ||||
| while(0) | ||||
|  | ||||
| #define do_once_start  \ | ||||
| do                     \ | ||||
| @@ -105,14 +109,8 @@ do                     \ | ||||
| }                      \ | ||||
| while(0); | ||||
|  | ||||
|  | ||||
| using Line       = char*; | ||||
| using Array_Line = array( Line ); | ||||
|  | ||||
|  | ||||
| ct char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED"; | ||||
|  | ||||
|  | ||||
| namespace Global | ||||
| { | ||||
| 	extern bool ShouldShowDebug; | ||||
| @@ -124,6 +122,8 @@ namespace Memory | ||||
|  | ||||
| 	extern arena Global_Arena; | ||||
| 	// #define g_allocator arena_allocator( & Memory::Global_Arena) | ||||
|  | ||||
| 	// Heap allocator is being used for now to isolate errors from being memory related (tech debt till ready to address) | ||||
| 	#define g_allocator heap() | ||||
|  | ||||
| 	void setup(); | ||||
| @@ -131,9 +131,19 @@ namespace Memory | ||||
| 	void cleanup(); | ||||
| } | ||||
|  | ||||
| // Had to be made to support multiple sub-arguments per "opt" argument. | ||||
| b32 opts_custom_compile(opts *options, int argc, char **argv); | ||||
| inline | ||||
| char const* token_fmt( char const* fmt, sw num_tokens, ... ) | ||||
| { | ||||
| 	local_persist thread_local  | ||||
| 	char buf[ZPL_PRINTF_MAXLEN] = { 0 }; | ||||
|  | ||||
| 	va_list va; | ||||
| 	va_start(va, fmt); | ||||
| 	token_fmt_va(buf, ZPL_PRINTF_MAXLEN, fmt, num_tokens, va); | ||||
| 	va_end(va); | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
|  | ||||
| inline | ||||
| sw log_fmt(char const *fmt, ...)  | ||||
| @@ -152,7 +162,7 @@ sw log_fmt(char const *fmt, ...) | ||||
| } | ||||
|  | ||||
| inline | ||||
| void fatal(char const *fmt, ...)  | ||||
| sw fatal(char const *fmt, ...)  | ||||
| { | ||||
| 	local_persist thread_local  | ||||
| 	char buf[ZPL_PRINTF_MAXLEN] = { 0 }; | ||||
| @@ -165,11 +175,13 @@ void fatal(char const *fmt, ...) | ||||
| 	va_end(va); | ||||
|  | ||||
| 	assert_crash(buf); | ||||
| 	return -1; | ||||
| #else | ||||
| 	va_start(va, fmt); | ||||
| 	zpl_printf_err_va( fmt, va); | ||||
| 	va_end(va); | ||||
|  | ||||
| 	zpl_exit(1); | ||||
| 	return -1; | ||||
| #endif | ||||
| } | ||||
|   | ||||
							
								
								
									
										18
									
								
								project/Bloat.undef.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								project/Bloat.undef.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* | ||||
| 	Remvoe any macro definitions related to the Bloat header. | ||||
| */ | ||||
|  | ||||
| #undef bit | ||||
| #undef bitfield_is_equal | ||||
| #undef ct | ||||
| #undef forceinline | ||||
| #undef print_nl | ||||
| #undef scast | ||||
| #undef rcast | ||||
| #undef pcast | ||||
| #undef txt | ||||
|  | ||||
| #undef do_once | ||||
| #undef do_once_start | ||||
| #undef do_once_end | ||||
|  | ||||
							
								
								
									
										730
									
								
								project/gen.cpp
									
									
									
									
									
								
							
							
						
						
									
										730
									
								
								project/gen.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										628
									
								
								project/gen.hpp
									
									
									
									
									
								
							
							
						
						
									
										628
									
								
								project/gen.hpp
									
									
									
									
									
								
							| @@ -1,105 +1,163 @@ | ||||
| /* | ||||
| 	gencpp: A simple staged metaprogramming library for C++. | ||||
|  | ||||
| 	This library is intended for small-to midsize projects that want rapid complation times  | ||||
| 	for fast debugging. | ||||
| 	 | ||||
| 	This library is intended for small-to midsize projects. | ||||
|  | ||||
| 	AST type checking supports only a small subset of c++.  | ||||
| 	See the 'ECode' namespace and 'gen API' region to see what is supported. | ||||
|  | ||||
| 	There is no support for accessability fields in structs. | ||||
| 	WHAT IS NOT PROVIDED: | ||||
| 	* Macro or template generation      : This library is to avoid those, adding support for them  | ||||
| 											adds unnecessary complexity. | ||||
| 											If you desire define them outside the gen_time scopes.  | ||||
| 											 | ||||
| 	* Modern c++ (STL library) features :  | ||||
| 	* Expression validation             : Execution expressions are defined using the untyped string API. | ||||
| 										: There is no parse API for validating expression (possibly will add in the future) | ||||
|  | ||||
| 	* Complete file parser DSL          : This isn't like the unreal header tool.  | ||||
| 											Code injection to file or based off a file contents is not supported by the api. | ||||
| 											However nothing is stopping you using the library for that purpose. | ||||
| 												 | ||||
|  | ||||
| 	There are four different of construction of Code ast's the library provides: | ||||
| 	* Upfront construction | ||||
| 	* Incremental construction | ||||
| 	* Parse construction | ||||
| 	* Untyped | ||||
|  | ||||
| 	Upfront Construction: | ||||
| 	All component ASTs must be previously constructed, and provided on creation of the code AST. | ||||
| 	The construction will fail and return InvalidCode otherwise. | ||||
|  | ||||
| 	API: | ||||
| 	* def_forward_decl | ||||
| 	* def_class           | ||||
| 	* def_global_body | ||||
| 	* def_proc | ||||
| 	* def_proc_body | ||||
| 	* def_namespace | ||||
| 	* def_namespace_body | ||||
| 	* def_param | ||||
| 	* def_params | ||||
| 	* def_operator | ||||
| 	* def_specifier | ||||
| 	* def_specifiers | ||||
| 	* def_struct | ||||
| 	* def_struct_body | ||||
| 	* def_variable | ||||
| 	* def_type | ||||
| 	* def_using | ||||
| 	* def_using_namespace | ||||
|  | ||||
| 	Incremental construction: | ||||
| 	A Code ast is provided but only completed upfront if all components are provided. | ||||
| 	Components are then added using the AST API for adding ASTs:  | ||||
| 		* code.add( AST* )         // Adds AST with validation. | ||||
| 		* code.add_entry( AST* )   // Adds AST entry without validation. | ||||
| 		* code.add_content( AST* ) // Adds AST string content without validation. | ||||
|  | ||||
| 	API: | ||||
| 	* make_forward_decl | ||||
| 	* make_class | ||||
| 	* make_global_body | ||||
| 	* make_proc | ||||
| 	* make_namespace | ||||
| 	* make_params | ||||
| 	* make_operator | ||||
| 	* make_specifiers | ||||
| 	* make_struct | ||||
| 	* make_variable | ||||
| 	* make_type | ||||
| 	* make_using | ||||
| 	* make_using_namespace | ||||
|  | ||||
| 	Parse construction: | ||||
| 	A string provided to the API is parsed for the intended language construct. | ||||
|  | ||||
| 	API: | ||||
| 	* parse_forward_decl | ||||
| 	* parse_class | ||||
| 	* parse_glboal_body | ||||
| 	* parse_proc | ||||
| 	* parse_namespace | ||||
| 	* parse_params | ||||
| 	* parse_operator | ||||
| 	* parse_specifiers | ||||
| 	* parse_struct | ||||
| 	* parse_variable | ||||
| 	* parse_type | ||||
| 	* parse_using | ||||
| 	* parse_using | ||||
|  | ||||
| 	The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. | ||||
| 	This includes the assignmetn of variables; due to the library not yet supporting c/c++ expression parsing. | ||||
|  | ||||
| 	Untyped constructions: | ||||
| 	Code ASTs are constructed using unvalidated strings. | ||||
| 	 | ||||
| 	API: | ||||
| 	* untyped_str | ||||
| 	* untyped_fmt | ||||
| 	* untyped_token_fmt | ||||
|  | ||||
| 	During serialization any untyped Code AST is has its string value directly injected inline of  | ||||
| 	whatever context the content existed as an entry within. | ||||
| 	Even though thse are not validated from somewhat correct c/c++ syntax or components, it doesn't mean that | ||||
| 	Untyped code can be added as any component of a Code AST: | ||||
| 		* Untyped code cannot have children, thus there cannot be recursive injection this way. | ||||
| 		* Untyped code can only be a child of a parent of body AST, or for values of an assignment. | ||||
| 	These restrictions help prevent abuse of untyped code to some extent. | ||||
| */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Bloat.hpp" | ||||
|  | ||||
| // Defined by default. | ||||
|  | ||||
| #define GEN_ENABLE_READONLY_AST | ||||
| // #define GEN_DEFINE_DSL | ||||
|  | ||||
| // Temporarily here for debugging purposes. | ||||
| #define gen_time | ||||
| #define GEN_ENFORCE_READONLY_AST | ||||
| // #define GEN_DEFINE_DSL | ||||
| #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||
| // #define GEN_BAN_CPP_TEMPLATES | ||||
| // #define GEN_USE_FATAL | ||||
|  | ||||
| #ifdef gen_time | ||||
| namespace gen | ||||
| { | ||||
| 	#if 0 | ||||
| 	ct sw ColumnLimit = 256; | ||||
| 	ct sw MaxLines    = kilobytes(256); | ||||
| 	using LogFailType = sw(*)(char const*, ...); | ||||
|  | ||||
| 	using LineStr = char[ColumnLimit]; | ||||
| 	#endif | ||||
| #ifdef GEN_BAN_CPP_TEMPLATES | ||||
| 	#define template static_assert("Templates are banned within gen_time scope blocks") | ||||
| #endif | ||||
|  | ||||
| 	// Specifier Type | ||||
| 	enum Specifier : u8 | ||||
| 	{ | ||||
| 		Alignas,            // alignas(#) | ||||
| 		Constexpr,          // constexpr | ||||
| 		Inline,             // inline | ||||
| #ifdef GEN_USE_FATAL | ||||
| 	ct LogFailType log_failure = fatal; | ||||
| #else | ||||
| 	ct LogFailType log_failure = log_fmt; | ||||
| #endif | ||||
|  | ||||
| 		C_Linkage,          // extern "C" | ||||
| 		API_Import,         // Vendor specific way dynamic import symbol | ||||
| 		API_Export,         // Vendor specific way to dynamic export | ||||
| 		External_Linkage,   // extern | ||||
| 		Internal_Linkage,   // static (within unit file) | ||||
| 		Static_Member,      // static (within sturct/class) | ||||
| 		Local_Persist,      // static (within function) | ||||
| 		Thread_Local,       // thread_local | ||||
|  | ||||
| 		Num_Specifiers | ||||
| 	}; | ||||
|  | ||||
| 	// Specifier to string | ||||
| 	inline | ||||
| 	char const* specifier_str( Specifier specifier ) | ||||
| 	{ | ||||
| 		static  | ||||
| 		char const* lookup[ Num_Specifiers ] = { | ||||
| 			"alignas", | ||||
| 			"constexpr", | ||||
| 			"inline", | ||||
|  | ||||
| 			"extern \"C\"", | ||||
| 		#if defined(ZPL_SYSTEM_WINDOWS) | ||||
| 			"__declspec(dllexport)", | ||||
| 			"__declspec(dllimport)", | ||||
| 		#elif defined(ZPL_SYSTEM_MACOS) | ||||
| 			"__attribute__ ((visibility ("default")))", | ||||
| 			"__attribute__ ((visibility ("default")))", | ||||
| 		#endif | ||||
| 			"extern", | ||||
| 			"static", | ||||
| 			"static", | ||||
| 			"static", | ||||
| 			"thread_local" | ||||
| 		}; | ||||
|  | ||||
| 		return lookup[ specifier ]; | ||||
| 	} | ||||
|  | ||||
| 	// Code Type | ||||
| 	namespace ECode | ||||
| 	{ | ||||
| 		enum Type : u8 | ||||
| 		{ | ||||
| 			Invalid, | ||||
|  | ||||
| 			Untyped, // User provided raw string. | ||||
|  | ||||
| 			Decl_Function,  // Forward a function | ||||
| 			Decl_Type,      // Forward a type. | ||||
| 			Invalid,        // Used only with improperly created Code nodes | ||||
| 			Untyped,        // User provided raw string | ||||
| 			Decl_Function,  // <specifier> <type> <name> ( <params> ) | ||||
| 			Decl_Type,      // <type> <name>; | ||||
| 			Function,       // <type> <name>( <parameters> ) | ||||
| 			Function_Body,  // { <body> } | ||||
| 			Namespace, | ||||
| 			Namespace_Body,  | ||||
| 			Parameters,  // Used with functions. | ||||
| 			Specifiers, | ||||
| 			Struct,      | ||||
| 			Struct_Body, | ||||
| 			Variable, | ||||
| 			Typedef, | ||||
| 			Typename, | ||||
| 			Using, | ||||
| 			Namespace,      // Define a namespace | ||||
| 			Namespace_Body, // { <body> }  | ||||
| 			Parameters,     // <type> <param> ... | ||||
| 			Specifiers,     // Used with functions, structs, variables | ||||
| 			Struct,         // struct <specifier> <name> <parent> | ||||
| 			Struct_Body,    // {<body> } | ||||
| 			Variable,       // <type> <name> | ||||
| 			Typedef,        // typedef <type> <alias> | ||||
| 			Typename,       // Typename, used with other types | ||||
| 			Using,          // using <name> = <type> | ||||
| 			Unit,           // Represents a file. | ||||
|  | ||||
| 			Num_Types | ||||
| 		}; | ||||
| @@ -110,11 +168,9 @@ namespace gen | ||||
| 			static  | ||||
| 			char const* lookup[Num_Types] = { | ||||
| 				"Invalid", | ||||
|  | ||||
| 				"Untyped", | ||||
| 				 | ||||
| 				"Decl_Function", | ||||
| 				"Decl_type", | ||||
| 				"Decl_Type", | ||||
| 				"Function", | ||||
| 				"Function_Body", | ||||
| 				"Namespace", | ||||
| @@ -126,7 +182,8 @@ namespace gen | ||||
| 				"Variable", | ||||
| 				"Typedef", | ||||
| 				"Typename", | ||||
| 				"using" | ||||
| 				"Using", | ||||
| 				"Unit", | ||||
| 			}; | ||||
|  | ||||
| 			return lookup[ type ]; | ||||
| @@ -134,6 +191,116 @@ namespace gen | ||||
| 	} | ||||
| 	using CodeT = ECode::Type; | ||||
|  | ||||
| 	namespace EOperator | ||||
| 	{ | ||||
| 		enum Type : u8 | ||||
| 		{ | ||||
| 			Add, | ||||
| 			Subtract, | ||||
| 			Multiply, | ||||
| 			Divide, | ||||
| 			Modulo, | ||||
|  | ||||
| 			Num_Ops | ||||
| 		}; | ||||
|  | ||||
| 		inline  | ||||
| 		char const* str( Type op ) | ||||
| 		{ | ||||
| 			static  | ||||
| 			char const* lookup[ Num_Ops ] = { | ||||
| 				"+", | ||||
| 				"-", | ||||
| 				"*", | ||||
| 				"/", | ||||
| 			}; | ||||
|  | ||||
| 			return lookup[ op ]; | ||||
| 		} | ||||
| 	} | ||||
| 	using OperatorT = EOperator::Type; | ||||
|  | ||||
| 	namespace ESpecifier | ||||
| 	{ | ||||
| 		enum Type : u8 | ||||
| 		{ | ||||
| 			Attribute,          // [ <attributes ] | ||||
| 			Alignas,            // alignas(#) | ||||
| 			Constexpr,          // constexpr | ||||
| 			Const,              // const | ||||
| 			Inline,             // inline | ||||
| 			RValue,             //  | ||||
|  | ||||
| 			C_Linkage,          // extern "C" | ||||
| 			API_Import,         // Vendor specific way dynamic import symbol | ||||
| 			API_Export,         // Vendor specific way to dynamic export | ||||
| 			External_Linkage,   // extern | ||||
| 			Internal_Linkage,   // static (within unit file) | ||||
| 			Static_Member,      // static (within sturct/class) | ||||
| 			Local_Persist,      // static (within function) | ||||
| 			Thread_Local,       // thread_local | ||||
|  | ||||
| 			Num_Specifiers, | ||||
| 			Invalid | ||||
| 		}; | ||||
|  | ||||
| 		// Specifier to string | ||||
| 		inline | ||||
| 		char const* to_str( Type specifier ) | ||||
| 		{ | ||||
| 			static  | ||||
| 			char const* lookup[ Num_Specifiers ] = { | ||||
| 				"alignas", | ||||
| 				"constexpr", | ||||
| 				"const", | ||||
| 				"inline", | ||||
|  | ||||
| 				"extern \"C\"", | ||||
|  | ||||
| 			#if defined(ZPL_SYSTEM_WINDOWS) && 0// API_Import and API_Export strings | ||||
| 				"__declspec(dllexport)", | ||||
| 				"__declspec(dllimport)", | ||||
| 			#elif defined(ZPL_SYSTEM_MACOS) || 1 | ||||
| 				"__attribute__ ((visibility (\"default\")))", | ||||
| 				"__attribute__ ((visibility (\"default\")))", | ||||
| 			#endif | ||||
|  | ||||
| 				"extern", | ||||
| 				"static", | ||||
| 				"static", | ||||
| 				"static", | ||||
| 				"thread_local" | ||||
| 			}; | ||||
|  | ||||
| 			return lookup[ specifier ]; | ||||
| 		} | ||||
| 		 | ||||
| 		Type to_type( char const* str, s32 length ) | ||||
| 		{ | ||||
| 			static  | ||||
| 			u32 keymap[ Num_Specifiers ]; | ||||
| 			do_once_start | ||||
| 				for ( u32 index = 0; index < Num_Specifiers; index++ ) | ||||
| 				{ | ||||
| 					char const* enum_str = to_str( (Type)index ); | ||||
|  | ||||
| 					keymap[index] = crc32( enum_str, strnlen(enum_str, 42) ); | ||||
| 				} | ||||
| 			do_once_end | ||||
|  | ||||
| 			u32 hash = crc32(str, length ); | ||||
|  | ||||
| 			for ( u32 index = 0; index < Num_Specifiers; index++ ) | ||||
| 			{ | ||||
| 				if ( keymap[index] == hash ) | ||||
| 					return (Type)index; | ||||
| 			} | ||||
|  | ||||
| 			return Invalid; | ||||
| 		} | ||||
| 	} | ||||
| 	using SpecifierT = ESpecifier::Type; | ||||
|  | ||||
| 	// TODO: If perf needs it, convert layout an SOA format. | ||||
| 	/*  | ||||
| 		Simple AST POD with functionality to seralize into C++ syntax. | ||||
| @@ -154,38 +321,40 @@ namespace gen | ||||
| 		} | ||||
|  | ||||
| 		forceinline | ||||
| 		bool has_entries() | ||||
| 		bool has_entries() const | ||||
| 		{ | ||||
| 			static bool lookup[ ECode::Num_Types] = { | ||||
| 				false, // Invalid | ||||
| 				false, // Unused | ||||
| 				false, // Untyped | ||||
| 				true,  // Decl_Type | ||||
| 				true,  // Decl_Function | ||||
| 				true,  // Parameter | ||||
| 				true,  // Struct | ||||
| 				true,  // Decl_Type | ||||
| 				true,  // Function | ||||
| 				false, // Specifier | ||||
| 				true,  // Parameters | ||||
| 				false, // Specifies | ||||
| 				true,  // Struct | ||||
| 				true,  // Struct_Body | ||||
| 				true,  // Variable | ||||
| 				true,  // Typedef | ||||
| 				true,  // Typename | ||||
| 				true,  // Using | ||||
| 			}; | ||||
|  | ||||
| 			return lookup[Type]; | ||||
| 		} | ||||
|  | ||||
| 		forceinline | ||||
| 		bool is_invalid() | ||||
| 		bool is_invalid() const | ||||
| 		{ | ||||
| 			return Type != ECode::Invalid; | ||||
| 		} | ||||
|  | ||||
| 		forceinline | ||||
| 		char const* type_str() | ||||
| 		char const* type_str() const | ||||
| 		{ | ||||
| 			return ECode::str( Type ); | ||||
| 		} | ||||
|  | ||||
| 		string to_string(); | ||||
| 		string to_string() const; | ||||
|  | ||||
| 	#pragma endregion Member API | ||||
|  | ||||
| @@ -215,7 +384,7 @@ namespace gen | ||||
| 	/* | ||||
| 		AST* typedef as to not constantly have to add the '*' as this is written often.. | ||||
|  | ||||
| 		If GEN_ENABLE_READONLY_AST is defined, readonly assertions will be done on any member dreference,  | ||||
| 		If GEN_ENFORCE_READONLY_AST is defined, readonly assertions will be done on any member dreference,  | ||||
| 		and the 'gen API' related functions. will set their created ASTs to readonly before returning. | ||||
|  | ||||
| 		Casting to AST* will bypass. | ||||
| @@ -224,13 +393,32 @@ namespace gen | ||||
| 	{ | ||||
| 		AST* ast; | ||||
|  | ||||
| 		forceinline | ||||
| 		operator bool() | ||||
| 		Code body() | ||||
| 		{ | ||||
| 			return ast->is_invalid(); | ||||
| 			if ( ast->Type == ECode::Invalid ) | ||||
| 				fatal("Code::body: Type is invalid, cannot get"); | ||||
|  | ||||
| 			if ( ast->Entries == nullptr || array_count(ast->Entries) == 0 ) | ||||
| 				fatal("Code::body: Entries of ast not properly setup."); | ||||
|  | ||||
| 			return pcast( Code, ast->Entries[0]); | ||||
| 		} | ||||
|  | ||||
| 		bool operator ==( Code other ) | ||||
| 		forceinline | ||||
| 		void lock() | ||||
| 		{ | ||||
| 		#ifdef GEN_ENFORCE_READONLY_AST | ||||
| 			ast->Readonly = true; | ||||
| 		#endif | ||||
| 		} | ||||
|  | ||||
| 		forceinline | ||||
| 		operator bool() const | ||||
| 		{ | ||||
| 			return ast && ast->is_invalid(); | ||||
| 		} | ||||
|  | ||||
| 		bool operator ==( Code other ) const | ||||
| 		{ | ||||
| 			return ast == other.ast; | ||||
| 		} | ||||
| @@ -247,28 +435,27 @@ namespace gen | ||||
| 			return *this; | ||||
| 		} | ||||
|  | ||||
| 	#ifdef GEN_ENABLE_READONLY_AST | ||||
| 		forceinline | ||||
| 		AST* operator ->()  | ||||
| 		{ | ||||
| 		#ifdef GEN_ENFORCE_READONLY_AST  | ||||
| 			if ( ast == nullptr ) | ||||
| 				fatal("Attempt to dereference a nullptr!"); | ||||
|  | ||||
| 			if ( ast->Readonly ) | ||||
| 				fatal("Attempted to access a member from a readonly ast!");			 | ||||
| 		#endif | ||||
|  | ||||
| 			return ast; | ||||
| 		} | ||||
|  | ||||
| 		Code& operator *() = delete; | ||||
| 	#endif | ||||
| 	}; | ||||
| 	static_assert( sizeof(Code) == sizeof(AST*), "ERROR: Code is not POD" ); | ||||
|  | ||||
| 	// Used when the its desired when omission is allowed in a definition. | ||||
| 	ct Code UnusedCode = { nullptr }; | ||||
|  | ||||
| 	// Used internally for the most part to identify invaidly generated code. | ||||
| 	ct CodePOD InvalidCode = { ECode::Invalid, false, nullptr, nullptr, nullptr, { nullptr } }; | ||||
| 	extern const Code InvalidCode; | ||||
|  | ||||
| 	/* | ||||
| 		Type registy: Used to store Typename ASTs. Types are registered by their string literal value. | ||||
| @@ -277,7 +464,7 @@ namespace gen | ||||
| 		Strings made with the Typename ASTs are stored in thier own arena allocator. | ||||
| 		TODO: Implement and replace usage of def_type. | ||||
| 	*/ | ||||
| 	// ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeRegistry, type_reg_, Code ); | ||||
| 	ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeRegistry, type_reg_, Code ); | ||||
|  | ||||
| #pragma region gen API | ||||
| 	/* | ||||
| @@ -286,17 +473,18 @@ namespace gen | ||||
| 	*/	 | ||||
| 	void init(); | ||||
|  | ||||
| 	#pragma region Upfront | ||||
| 	/* | ||||
| 		Foward Declare a type: | ||||
| 		<specifiers> <type> <name>; | ||||
| 	*/ | ||||
| 	Code decl_type( char const* name, Code type, Code specifiers = UnusedCode ); | ||||
| 	Code def_fwd_type( Code type, char const* name, Code specifiers = UnusedCode ); | ||||
|  | ||||
| 	/* | ||||
| 		Foward Declare a function: | ||||
| 		<specifiers> <name> ( <params> ); | ||||
| 	*/ | ||||
| 	Code decl_fn( char const* name | ||||
| 	Code def_fwd_proc( char const* name | ||||
| 		, Code specifiers | ||||
| 		, Code params | ||||
| 		, Code ret_type | ||||
| @@ -305,8 +493,10 @@ namespace gen | ||||
| 	/* | ||||
| 		Define an expression: | ||||
| 		< c/c++ expression > | ||||
|  | ||||
| 		TODO: Evalute if you want to validiate at the execution layer during gen_time (dosen't seem necessary) | ||||
| 	*/ | ||||
| 	Code def_expression( Code value ); | ||||
| 	// Code def_expression( Code value ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a function: | ||||
| @@ -315,7 +505,7 @@ namespace gen | ||||
| 			<body> | ||||
| 		} | ||||
| 	*/ | ||||
| 	Code def_function( char const* name | ||||
| 	Code def_proc( char const* name | ||||
| 		, Code specifiers | ||||
| 		, Code params | ||||
| 		, Code ret_type | ||||
| @@ -330,9 +520,10 @@ namespace gen | ||||
| 			... | ||||
| 		} | ||||
|  | ||||
| 		Each entry is provided an empty line separation. | ||||
| 		There will be an empty line separation between entires | ||||
| 	*/ | ||||
| 	Code def_function_body( s32 num, ... ); | ||||
| 	Code def_proc_body( s32 num, ... ); | ||||
| 	Code def_proc_body( s32 num, Code* codes ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a namespace; | ||||
| @@ -351,7 +542,7 @@ namespace gen | ||||
| 			... | ||||
| 		} | ||||
|  | ||||
| 		Each entry is provided an empty line separation. | ||||
| 		There will be an empty line separation between entires | ||||
| 	*/ | ||||
| 	Code def_namespace_body( s32 num, ... ); | ||||
|  | ||||
| @@ -359,12 +550,23 @@ namespace gen | ||||
| 		Define a set of parameters for a function: | ||||
| 		<name> <type>, ... | ||||
| 	*/ | ||||
| 	Code def_parameters( s32 num, ... ); | ||||
| 	Code def_params( s32 num, ... ); | ||||
| 	Code def_params( s32 num, char const** params ); | ||||
|  | ||||
| 	/* | ||||
| 		Define an operator definition. | ||||
| 	*/ | ||||
| 	Code def_operator( OperatorT op, Code specifiers, Code params, Code ret_type, Code body ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a set of specifiers for a function, struct, type, or varaible | ||||
|  | ||||
| 		Note: 		 | ||||
| 		If alignas is specified the procedure expects the next argument to be the alignment value. | ||||
| 		If attribute is specified the procedure expects the next argument to be its content as a string. | ||||
| 	*/ | ||||
| 	Code def_specifiers( s32 num , ... ); | ||||
| 	Code def_specifiers( s32 num, SpecifierT* specs ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a struct: | ||||
| @@ -383,19 +585,26 @@ namespace gen | ||||
| 			... | ||||
| 		} | ||||
|  | ||||
| 		Each entry is provided an empty line separation. | ||||
| 		There will be an empty line separation between entires | ||||
| 	*/ | ||||
| 	Code def_struct_body( s32 num, ... ); | ||||
| 	Code def_struct_body( s32 num, Code* codes ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a variable: | ||||
| 		<specifiers> <type> <name> = <value>; | ||||
| 	*/ | ||||
| 	Code def_variable( char const* name, Code type, Code value = UnusedCode, Code specifiers = UnusedCode ); | ||||
| 	Code def_variable( Code type, char const* name, Code value = UnusedCode, Code specifiers = UnusedCode ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a type AST value. | ||||
| 		Useless by itself, its intended to be used in conjunction with  | ||||
| 		Define a typename AST value. | ||||
| 		Useless by itself, its intended to be used in conjunction with other Code. | ||||
|  | ||||
| 	Planned - Not yet Implemented: | ||||
| 		Typename Codes are not held in the CodePool, instead they are stored in a  | ||||
| 		type registry (hastable where the key is a crc hash of the name string). | ||||
|  | ||||
| 		If a key exists the existing code value will be provided. | ||||
| 	*/ | ||||
| 	Code def_type( char const* name ); | ||||
|  | ||||
| @@ -412,7 +621,88 @@ namespace gen | ||||
| 		Can only be used in either a  | ||||
| 	*/ | ||||
| 	Code def_using_namespace( char const* name ); | ||||
| 	#pragma endregion Upfront | ||||
|  | ||||
| 	#pragma region Incremental | ||||
| 	/* | ||||
| 		Provides an incomplete procedure AST but sets the intended type. | ||||
| 		Any adds will be type checked. | ||||
|  | ||||
| 		Body is automatically made. Use body() to retrieve. | ||||
| 	*/ | ||||
| 	Code make_proc( char const* name | ||||
| 		, Code specifiers = UnusedCode | ||||
| 		, Code params = UnusedCode | ||||
| 		, Code ret_type = UnusedCode | ||||
| 	); | ||||
| 	 | ||||
| 	/* | ||||
| 		Provides an incomplete struct AST but sets the intended type. | ||||
| 		Any adds will be type checked. | ||||
|  | ||||
| 		Body is automatically made. Use body() to retrieve. | ||||
| 	*/ | ||||
| 	Code make_struct( char const* name, Code parent = UnusedCode, Code specifiers = UnusedCode ); | ||||
|  | ||||
| /* | ||||
| 	Creates a unit file. | ||||
|  | ||||
| 	These represent an encapsulation of a generated file | ||||
| 	Used this if you need to pass around a group of Code entires at file scope level. | ||||
|  | ||||
| 	The name provided is the name of the file. | ||||
| */ | ||||
| Code make_file_body( char const* name ); | ||||
| 	#pragma endregion Incremental | ||||
|  | ||||
| 	/* | ||||
| 	*/ | ||||
| 	Code parse_variable( char const* var_def, s32 length ); | ||||
|  | ||||
| 	/* | ||||
| 	*/ | ||||
| 	Code parse_using( char const* using_def, s32 length ); | ||||
|  | ||||
| 	/* | ||||
|  | ||||
| 	*/ | ||||
| 	Code parse_operator( char const* operator_def, s32 length ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a procedure by parsing a string. | ||||
|  | ||||
| 		Note: This parser only supports the language features the library supports | ||||
| 		Any other features used and the lex or parse operation will fail. | ||||
|  | ||||
| 		This is not a full-on c/c++ parser, it literally only grabs  | ||||
| 		what it needs to reconstruct the Code AST for seralization in the  | ||||
| 		builder, nothing else. | ||||
| 	*/ | ||||
| 	Code parse_proc( char const* proc_def, s32 length ); | ||||
|  | ||||
| 	/* | ||||
| 		Define a struct by parsing a string. | ||||
|  | ||||
| 		Note: This parser only supports the language features the library supports | ||||
| 		Any other features used and the lex or parse operation will fail. | ||||
|  | ||||
| 		This is not a full-on c/c++ parser, it literally only grabs  | ||||
| 		what it needs to reconstruct the Code AST for seralization in the  | ||||
| 		builder, nothing else. | ||||
| 	*/ | ||||
| 	Code parse_struct( char const* struct_def, s32 length ); | ||||
|  | ||||
| 	/* | ||||
| 	 | ||||
| 	*/ | ||||
| 	s32 parse_vars( char const* vars_def, s32 length, Code* out_vars_codes ); | ||||
|  | ||||
| 	/* | ||||
|  | ||||
| 	*/ | ||||
| 	s32 parse_usings( char const* usings_def, s32 length, Code* out_usings_codes ); | ||||
|  | ||||
| 	#pragma region Untyped text | ||||
| 	/* | ||||
| 		Define an untyped code string. | ||||
|  | ||||
| @@ -423,6 +713,7 @@ namespace gen | ||||
| 		Consider this an a preprocessor define. | ||||
| 	*/ | ||||
| 	Code untyped_str( char const* str ); | ||||
| 	Code untyped_str( char const* str, s32 length); | ||||
|  | ||||
| 	/* | ||||
| 		Define an untyped code string using traditional 'printf'. | ||||
| @@ -449,18 +740,8 @@ namespace gen | ||||
| 		Because the code within it is untyped, errors will naturally not be provided. | ||||
| 		Consider this an a preprocessor define. | ||||
| 	*/ | ||||
| 	Code token_fmt( char const* fmt, s32 num_tokens, ... ); | ||||
|  | ||||
|  | ||||
| 	/* | ||||
| 		Creates a unit file. | ||||
|  | ||||
| 		These represent an encapsulation of a generated file | ||||
| 		Used this if you need to pass around a group of Code entires at file scope level. | ||||
|  | ||||
| 		The name provided is the name of the file. | ||||
| 	*/ | ||||
| 	Code create_Unit( char const* name ); | ||||
| 	Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... ); | ||||
| 	#pragma endregion Untyped text | ||||
|  | ||||
| 	/*  | ||||
| 		Used to generate the files. | ||||
| @@ -492,62 +773,93 @@ namespace gen | ||||
|  | ||||
| #pragma region MACROS | ||||
| #	define gen_main main | ||||
|  | ||||
| #	define __ UnusedCode | ||||
| #	define __       UnusedCode | ||||
|  | ||||
| /* | ||||
| 	gen's Domain Specific Langauge. | ||||
|  | ||||
| 	Completely optional, makes the code gen syntax less verbose.. | ||||
| 	Completely optional, makes the code gen syntax less verbose and cumbersome... | ||||
| 	Since its C macros ends up looking like a lisp dialect... | ||||
|  | ||||
| 	Longforms auto-define the variable. | ||||
| 	Shorthands are just the function call. | ||||
|  | ||||
| 	Anything below the make() macro is intended to be syntacticall used int he follwing format: | ||||
| 	make( <type>, <name> ) | ||||
| 	{ | ||||
| 		... | ||||
| 	} | ||||
|  | ||||
| 	Where ... are whatever is deemed necessary to produce the definition for the def( <name> ). | ||||
|  | ||||
| 	The code macros are used to embed c/c++ to insert into the desired lcoation. | ||||
| */ | ||||
| #ifdef GEN_DEFINE_DSL | ||||
| #	define type( Name_, Value_ )        Code Name_ = gen::def_type( txt(Value_) ) | ||||
| #	define type_fmt( Name_, Fmt_, ... ) Code Name_ = gen::def_type( bprintf( Fmt_, __VA_ARGS__ ) ) | ||||
| #   define value( Name_, Value_ )       Code Name_ = gen::untyped_str( Value_ ) | ||||
| #	define specifiers( Name_, ... )     Code Name_ = gen::def_specifiers( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define using( Name_, Type_ )		Code Name_ = gen::def_using( #Name_, Type_ ) | ||||
| #   define untyped_code( Name_, Value_ )     Code Name_     = gen::untyped_str( txt(Value_) ) | ||||
| #	define typename( Name_, Value_ )         Code t_##Name_ = gen::def_type( txt(Value_) ) | ||||
| #	define typename_fmt( Name_, Fmt_, ... )  Code t_##Name_ = gen::def_type( bprintf( Fmt_, __VA_ARGS__ ) ) | ||||
| #	define using_type( Name_, Type_ )		 Code Name_     = gen::def_using( #Name_, t_##Type_ ) | ||||
| #	define variable( Type_, Name_, ... )     Code Name_     = gen::def_variable( t_##Type_, #Name_, __VA_ARGS__ ) | ||||
|  | ||||
| #	define var( Name_, Type_, Value_, Specifiers_ ) \ | ||||
| 		Code Name_ = gen::def_variable( #Name_, Type_, untyped_str( #Value_ ), Specifiers_ ) | ||||
| #   define untyped( Value_ )                      gen::untyped_str( txt(Value_) ) | ||||
| #	define code_token( Fmt_, ... )                gen::untyped_token_fmt( Fmt_, VA_NARGS( __VA_ARGS__), __VA_ARGS__ ) | ||||
| #	define code_fmt( Fmt_, ... )                  gen::untyped_fmt( Fmt_, __VA_ARGS__ ) | ||||
| #	define specifiers( ... )                      gen::def_specifiers( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define type( Value_ )                         gen::def_type( txt(Value_) ) | ||||
| #	define type_fmt( Fmt_, ... )                  gen::def_type( bprintf( Fmt_, __VA_ARGS__ ) ) | ||||
| #	define using( Name_, Type_ )		          gen::def_using( #Name_, Type_ ) | ||||
| #	define var( Type_, Name_, ... )               gen::def_variable( Type_, #Name_, __VA_ARGS__ ) | ||||
|  | ||||
| // #   define def ( Name _ ) Code Name_; | ||||
| #   define make( Type_, Name_, ... )                                Code Name_ = make_##Type_( #Name_, __VA_ARGS__ ); | ||||
| #	define proc( Name_, Specifiers_, RetType_, Parameters_, Body_ ) Name_ = gen::def_proc( #Name_, Specifiers_, Parameters_, RetType_, Body_ ) | ||||
| #	define proc_body( ... )                                                 gen::def_proc_body( VA_NARGS( __VA_ARS__ ), __VA_ARGS__ ) | ||||
| #	define params( ... )                                                    gen::def_params( VA_NARGS( __VA_ARGS__ ) / 2, __VA_ARGS__ ) | ||||
| #	define struct( Name_, Parent_, Specifiers_, Body_ )             Name_ = gen::def_struct( #Name_, Body_, Parent_, Specifiers_ ) | ||||
| #	define struct_body( ... )                                               gen::def_struct_body( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
|  | ||||
| #	define params( ... ) gen::def_parameters( VA_NARGS( __VA_ARGS__ ) / 2, __VA_ARGS__ ) | ||||
| #	define add_var( Type_, Name_, ... ) add( gen::def_variable( t_##Type_, #Name_, __VA_ARGS__ ) ) | ||||
| #	define add_untyped( Value_ )        add( gen::untyped_str( txt( Value ) ) ) | ||||
| #	define add_ret_type( ... ) | ||||
| #	define add_params( ... ) | ||||
|  | ||||
| /* | ||||
| 	Defines scoped symbol. | ||||
|  | ||||
| 	Used with: | ||||
| 	- function | ||||
| 	- namespace | ||||
| 	- struct | ||||
| */ | ||||
| #	define def( Name_ ) Code Name_; | ||||
|  | ||||
| #	define function( Name_, Specifiers_, ReturnType_, Parameters_, Body_ ) \ | ||||
| 		Name_ = gen::def_function( #Name_, Specifiers_, Parameters_, ReturnType_, Body_ ) | ||||
|  | ||||
| #	define function_body( ... ) \ | ||||
| 		gen::def_function_body( VA_NARGS( __VA_ARS__ ), __VA_ARGS__ ) | ||||
| 	 | ||||
| #	define struct( Name_, Parent_, Specifiers_, Body_ ) \ | ||||
| 		Name_ = gen::def_struct( #Name_, Body_, Parent_, Specifiers_ ) | ||||
|  | ||||
| #	define struct_body( ... ) \ | ||||
| 		gen::def_struct_body( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ ) | ||||
| #	define proc_code( Def_ )   gen::parse_proc( txt( Def_ ), sizeof( txt( Def_ )) ) | ||||
| #	define struct_code( Def_ ) gen::parse_struct( txt( Def_ ), sizeof( txt( Def_ )) ) | ||||
| #endif | ||||
| #pragma endregion MACROS | ||||
|  | ||||
| #pragma region CONSTANTS | ||||
| #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS  | ||||
| namespace gen | ||||
| { | ||||
| 	// Predefined typename codes. | ||||
| 	// These are not set until gen::init is called. | ||||
| 	// This just preloads a bunch of Code types into the code pool. | ||||
|  | ||||
| 	extern const Code t_void; | ||||
|  | ||||
| 	extern const Code t_bool; | ||||
| 	extern const Code t_char; | ||||
| 	extern const Code t_wchar_t; | ||||
|  | ||||
| 	extern const Code t_s8; | ||||
| 	extern const Code t_s16; | ||||
| 	extern const Code t_s32; | ||||
| 	extern const Code t_s64; | ||||
|  | ||||
| 	extern const Code t_u8; | ||||
| 	extern const Code t_u16; | ||||
| 	extern const Code t_u32; | ||||
| 	extern const Code t_u64; | ||||
|  | ||||
| 	extern const Code t_sw; | ||||
| 	extern const Code t_uw; | ||||
|  | ||||
| 	extern const Code t_f32; | ||||
| 	extern const Code t_f64; | ||||
|  | ||||
| 	extern const Code spec_constexpr; | ||||
| 	extern const Code spec_inline; | ||||
| } | ||||
| #endif | ||||
| #pragma endregion CONSTANTS | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user