mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	WIP: more progress on new macro handling
This commit is contained in:
		| @@ -36,7 +36,6 @@ Str code_debug_str(Code self) | ||||
| 		case CT_Execution: | ||||
| 		case CT_Comment: | ||||
| 		case CT_PlatformAttributes: | ||||
| 		case CT_Preprocess_Define: | ||||
| 		case CT_Preprocess_Include: | ||||
| 		case CT_Preprocess_Pragma: | ||||
| 		case CT_Preprocess_If: | ||||
| @@ -52,6 +51,11 @@ Str code_debug_str(Code self) | ||||
| 			strbuilder_append_fmt( result, "\n\tContent: %S", self->Content ); | ||||
| 		break; | ||||
|  | ||||
| 		case CT_Preprocess_Define: | ||||
| 			// TODO(ED): Needs implementaton | ||||
| 			log_failure("code_debug_str: NOT IMPLEMENTED for CT_Preprocess_Define"); | ||||
| 		break; | ||||
|  | ||||
| 		case CT_Class: | ||||
| 		case CT_Struct: | ||||
| 			if ( self->Prev ) | ||||
| @@ -259,6 +263,11 @@ Str code_debug_str(Code self) | ||||
| 			strbuilder_append_fmt( result, "\n\tValue     : %S", self->Value     ? strbuilder_to_str( code_to_strbuilder(self->Value))     : txt("Null") ); | ||||
| 		break; | ||||
|  | ||||
| 		case CT_Parameters_Define: | ||||
| 			// TODO(ED): Needs implementaton | ||||
| 			log_failure("code_debug_str: NOT IMPLEMENTED for CT_Parameters_Define"); | ||||
| 		break; | ||||
|  | ||||
| 		case CT_Specifiers: | ||||
| 		{ | ||||
| 			strbuilder_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); | ||||
| @@ -497,6 +506,10 @@ void code_to_strbuilder_ptr( Code self, StrBuilder* result ) | ||||
| 			params_to_strbuilder_ref(cast(CodeParams, self), result ); | ||||
| 		break; | ||||
|  | ||||
| 		case CT_Parameters_Define: | ||||
| 			define_params_to_strbuilder_ref(cast(CodeDefineParams, self), result); | ||||
| 		break; | ||||
|  | ||||
| 		case CT_Preprocess_Define: | ||||
| 			define_to_strbuilder_ref(cast(CodeDefine, self), result ); | ||||
| 		break; | ||||
| @@ -987,11 +1000,17 @@ bool code_is_equal( Code self, Code other ) | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		case CT_Parameters_Define: | ||||
| 		{ | ||||
| 			// TODO(ED): Needs implementaton | ||||
| 			log_failure("code_is_equal: NOT IMPLEMENTED for CT_Parameters_Define"); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		case CT_Preprocess_Define: | ||||
| 		{ | ||||
| 			check_member_str( Name ); | ||||
| 			check_member_content( Content ); | ||||
|  | ||||
| 			check_member_content( Body->Content ); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -176,7 +176,7 @@ void class_to_strbuilder_def( CodeClass self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
|  | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_str( result, txt("class ") ); | ||||
| @@ -221,7 +221,7 @@ void class_to_strbuilder_fwd( CodeClass self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
|  | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -241,12 +241,48 @@ void class_to_strbuilder_fwd( CodeClass self, StrBuilder* result ) | ||||
|  | ||||
| StrBuilder define_to_strbuilder(CodeDefine define) | ||||
| { | ||||
| 	return strbuilder_fmt_buf( _ctx->Allocator_Temp, "#define %S %S", define->Name, define->Content ); | ||||
| 	StrBuilder result = strbuilder_make_reserve( _ctx->Allocator_Temp, 512 ); | ||||
| 	define_to_strbuilder_ref(define, & result); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| void define_to_strbuilder_ref(CodeDefine define, StrBuilder* result ) | ||||
| { | ||||
| 	strbuilder_append_fmt( result, "#define %S %S", define->Name, define->Content ); | ||||
| 	GEN_ASSERT(define); | ||||
| 	GEN_ASSERT(define->Body); | ||||
| 	GEN_ASSERT(define->Body->Content); | ||||
| 	if (define->Params) { | ||||
| 		StrBuilder params_builder = define_params_to_strbuilder(define->Params) | ||||
| 		strbuilder_append_fmt( result, "#define %S(%S) %S", define->Name, strbuilder_to_str(params_builder), define->Body->Content ); | ||||
| 	} | ||||
| 	else { | ||||
| 		strbuilder_append_fmt( result, "#define %S %S", define->Name, define->Body->Content ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| StrBuilder define_params_to_strbuilder(CodeDefineParams params) | ||||
| { | ||||
| 	GEN_ASSERT(params); | ||||
| 	StrBuilder result = strbuilder_make_reserve( _ctx->Allocator_Temp, 128 ); | ||||
| 	define_params_to_strbuilder_ref( params, & result ); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| void define_params_to_strbuilder_ref(CodeDefineParams params, StrBuilder* result) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(result); | ||||
| 	if ( self->Name.Ptr && self->Name.Len ) | ||||
| 	{ | ||||
| 		strbuilder_append_fmt( result, " %S", self->Name ); | ||||
| 	} | ||||
| 	if ( self->NumEntries - 1 > 0 ) | ||||
| 	{ | ||||
| 		for ( CodeParams param = begin_CodeDefineParams(self->Next); param != end_CodeDefineParams(self->Next); param = next_CodeDefineParams(self->Next, param) ) | ||||
| 		{ | ||||
| 			strbuilder_append_fmt( result, ", %SB", params_to_strbuilder(param) ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| StrBuilder destructor_to_strbuilder(CodeDestructor self) | ||||
| @@ -329,7 +365,7 @@ StrBuilder enum_to_strbuilder(CodeEnum self) | ||||
|  | ||||
| void enum_to_strbuilder_def(CodeEnum self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes || self->UnderlyingType || self->UnderlyingTypeMacro ) | ||||
| @@ -362,7 +398,7 @@ void enum_to_strbuilder_def(CodeEnum self, StrBuilder* result ) | ||||
|  | ||||
| void enum_to_strbuilder_fwd(CodeEnum self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -389,7 +425,7 @@ void enum_to_strbuilder_fwd(CodeEnum self, StrBuilder* result ) | ||||
|  | ||||
| void enum_to_strbuilder_class_def(CodeEnum self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes || self->UnderlyingType ) | ||||
| @@ -421,7 +457,7 @@ void enum_to_strbuilder_class_def(CodeEnum self, StrBuilder* result ) | ||||
|  | ||||
| void enum_to_strbuilder_class_fwd(CodeEnum self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_str( result, txt("enum class ") ); | ||||
| @@ -505,7 +541,7 @@ StrBuilder fn_to_strbuilder(CodeFn self) | ||||
|  | ||||
| void fn_to_strbuilder_def(CodeFn self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -558,7 +594,7 @@ void fn_to_strbuilder_def(CodeFn self, StrBuilder* result ) | ||||
|  | ||||
| void fn_to_strbuilder_fwd(CodeFn self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -646,7 +682,7 @@ StrBuilder namespace_to_strbuilder(CodeNS self) | ||||
|  | ||||
| void namespace_to_strbuilder_ref(CodeNS self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_fmt( result, "namespace %S\n{\n%SB\n}\n", self->Name, body_to_strbuilder(self->Body) ); | ||||
| @@ -671,7 +707,7 @@ StrBuilder code_op_to_strbuilder(CodeOperator self) | ||||
|  | ||||
| void code_op_to_strbuilder_def(CodeOperator self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -725,7 +761,7 @@ void code_op_to_strbuilder_def(CodeOperator self, StrBuilder* result ) | ||||
|  | ||||
| void code_op_to_strbuilder_fwd(CodeOperator self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -865,7 +901,6 @@ void opcast_to_strbuilder_fwd(CodeOpCast self, StrBuilder* result ) | ||||
|  | ||||
| StrBuilder params_to_strbuilder(CodeParams self) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(self); | ||||
| 	StrBuilder result = strbuilder_make_reserve( _ctx->Allocator_Temp, 128 ); | ||||
| 	params_to_strbuilder_ref( self, & result ); | ||||
| @@ -1030,7 +1065,7 @@ void struct_to_strbuilder_def( CodeStruct self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(result); | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_str( result, txt("struct ") ); | ||||
| @@ -1076,7 +1111,7 @@ void struct_to_strbuilder_fwd( CodeStruct self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(result); | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -1105,7 +1140,7 @@ void template_to_strbuilder_ref(CodeTemplate self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(result); | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Params ) | ||||
| @@ -1123,7 +1158,7 @@ StrBuilder typedef_to_strbuilder(CodeTypedef self) | ||||
|  | ||||
| void typedef_to_strbuilder_ref(CodeTypedef self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_str( result, txt("typedef ")); | ||||
| @@ -1236,7 +1271,7 @@ StrBuilder union_to_strbuilder(CodeUnion self) | ||||
|  | ||||
| void union_to_strbuilder_def(CodeUnion self, StrBuilder* result ) | ||||
| { | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_str( result, txt("union ") ); | ||||
| @@ -1267,7 +1302,7 @@ void union_to_strbuilder_fwd(CodeUnion self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(result); | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	strbuilder_append_str( result, txt("union ") ); | ||||
| @@ -1304,7 +1339,7 @@ void using_to_strbuilder_ref(CodeUsing self, StrBuilder* result ) | ||||
| { | ||||
| 	GEN_ASSERT(self); | ||||
| 	GEN_ASSERT(result); | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes ) | ||||
| @@ -1401,7 +1436,7 @@ void var_to_strbuilder_ref(CodeVar self, StrBuilder* result ) | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 	if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export )) | ||||
| 		strbuilder_append_str( result, txt("export ") ); | ||||
|  | ||||
| 	if ( self->Attributes || self->Specs ) | ||||
|   | ||||
| @@ -46,6 +46,7 @@ enum CodeType : u32 | ||||
| 	CT_Operator_Cast, | ||||
| 	CT_Operator_Cast_Fwd, | ||||
| 	CT_Parameters, | ||||
| 	CT_Parameters_Define, | ||||
| 	CT_Preprocess_Define, | ||||
| 	CT_Preprocess_Include, | ||||
| 	CT_Preprocess_If, | ||||
| @@ -114,6 +115,7 @@ inline Str codetype_to_str( CodeType type ) | ||||
| 		{ "Operator_Cast",       sizeof( "Operator_Cast" ) - 1       }, | ||||
| 		{ "Operator_Cast_Fwd",   sizeof( "Operator_Cast_Fwd" ) - 1   }, | ||||
| 		{ "Parameters",          sizeof( "Parameters" ) - 1          }, | ||||
| 		{ "Parameters_Define",   sizeof( "Parameters_Define" ) - 1   }, | ||||
| 		{ "Preprocess_Define",   sizeof( "Preprocess_Define" ) - 1   }, | ||||
| 		{ "Preprocess_Include",  sizeof( "Preprocess_Include" ) - 1  }, | ||||
| 		{ "Preprocess_If",       sizeof( "Preprocess_If" ) - 1       }, | ||||
| @@ -182,6 +184,7 @@ inline Str codetype_to_keyword_str( CodeType type ) | ||||
| 		{ "operator",        sizeof( "operator" ) - 1        }, | ||||
| 		{ "operator",        sizeof( "operator" ) - 1        }, | ||||
| 		{ "__NA__",          sizeof( "__NA__" ) - 1          }, | ||||
| 		{ "__NA__",          sizeof( "__NA__" ) - 1          }, | ||||
| 		{ "define",          sizeof( "define" ) - 1          }, | ||||
| 		{ "include",         sizeof( "include" ) - 1         }, | ||||
| 		{ "if",              sizeof( "if" ) - 1              }, | ||||
|   | ||||
| @@ -53,6 +53,7 @@ enum TokType : u32 | ||||
| 	Tok_Operator, | ||||
| 	Tok_Preprocess_Hash, | ||||
| 	Tok_Preprocess_Define, | ||||
| 	Tok_Preprocess_Define_Param, | ||||
| 	Tok_Preprocess_If, | ||||
| 	Tok_Preprocess_IfDef, | ||||
| 	Tok_Preprocess_IfNotDef, | ||||
| @@ -62,7 +63,9 @@ enum TokType : u32 | ||||
| 	Tok_Preprocess_Include, | ||||
| 	Tok_Preprocess_Pragma, | ||||
| 	Tok_Preprocess_Content, | ||||
| 	Tok_Preprocess_Macro, | ||||
| 	Tok_Preprocess_Macro_Expr, | ||||
| 	Tok_Preprocess_Macro_Stmt, | ||||
| 	Tok_Preprocess_Macro_Typename, | ||||
| 	Tok_Preprocess_Unsupported, | ||||
| 	Tok_Spec_Alignas, | ||||
| 	Tok_Spec_Const, | ||||
| @@ -155,6 +158,7 @@ inline Str toktype_to_str( TokType type ) | ||||
| 		{ "__operator__",      sizeof( "__operator__" ) - 1      }, | ||||
| 		{ "#",		         sizeof( "#" ) - 1                 }, | ||||
| 		{ "define",            sizeof( "define" ) - 1            }, | ||||
| 		{ "__define_param__",  sizeof( "__define__param__" ) - 1  }, | ||||
| 		{ "if",		        sizeof( "if" ) - 1                }, | ||||
| 		{ "ifdef",             sizeof( "ifdef" ) - 1             }, | ||||
| 		{ "ifndef",            sizeof( "ifndef" ) - 1            }, | ||||
| @@ -164,7 +168,9 @@ inline Str toktype_to_str( TokType type ) | ||||
| 		{ "include",           sizeof( "include" ) - 1           }, | ||||
| 		{ "pragma",            sizeof( "pragma" ) - 1            }, | ||||
| 		{ "__macro_content__", sizeof( "__macro_content__" ) - 1 }, | ||||
| 		{ "__macro__",         sizeof( "__macro__" ) - 1         }, | ||||
| 		{ "__macro_expression__", sizeof( "__macro_expression__" ) - 1         }, | ||||
| 		{ "__macro_statment__",   sizeof( "__macro_statment__" ) - 1         }, | ||||
| 		{ "__macro_typename__",   sizeof( "__macro_typename__" ) - 1         }, | ||||
| 		{ "__unsupported__",   sizeof( "__unsupported__" ) - 1   }, | ||||
| 		{ "alignas",           sizeof( "alignas" ) - 1           }, | ||||
| 		{ "const",             sizeof( "const" ) - 1             }, | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|  | ||||
| #pragma region Constants | ||||
|  | ||||
| extern Str enum_underlying_sig; | ||||
| extern PreprocessorMacro enum_underlying_macro; | ||||
|  | ||||
| extern Code access_public; | ||||
| extern Code access_protected; | ||||
|   | ||||
| @@ -206,10 +206,12 @@ void define_constants() | ||||
| 	spec_local_persist = def_specifiers( 1, Spec_Local_Persist ); | ||||
| 	code_set_global(cast(Code, spec_local_persist)); | ||||
|  | ||||
| 	if (enum_underlying_sig.Len == 0) { | ||||
| 		enum_underlying_sig = txt("enum_underlying("); | ||||
| 	if (enum_underlying_macro.Name.Len == 0) { | ||||
| 		enum_underlying_macro.Name  = txt("enum_underlying("); | ||||
| 		enum_underlying_macro.Type  = MT_Expression; | ||||
| 		enum_underlying_macro.Flags = MF_Functional; | ||||
| 	} | ||||
| 	array_append( _ctx->PreprocessorDefines, enum_underlying_sig); | ||||
| 	register_preprocess_macro(enum_underlying_macro); | ||||
| } | ||||
|  | ||||
| void init(Context* ctx) | ||||
| @@ -301,9 +303,6 @@ void init(Context* ctx) | ||||
| 			GEN_FATAL( "gen::init: Failed to initialize the code pool" ); | ||||
| 		array_append( ctx->CodePools, code_pool ); | ||||
|  | ||||
| 		// TODO(Ed): This is going to be phased out most likely. | ||||
| 		ctx->LexArena = arena_init_from_allocator( ctx->Allocator_DyanmicContainers, ctx->InitSize_LexArena ); | ||||
|  | ||||
| 		// TODO(Ed): Eventually the string arenas needs to be phased out for a dedicated string slab allocator | ||||
| 		Arena strbuilder_arena = arena_init_from_allocator( ctx->Allocator_StrCache, ctx->SizePer_StringArena ); | ||||
| 		if ( strbuilder_arena.PhysicalStart == nullptr ) | ||||
| @@ -315,9 +314,12 @@ void init(Context* ctx) | ||||
| 		ctx->StrCache = hashtable_init(StrCached, ctx->Allocator_DyanmicContainers); | ||||
| 		if ( ctx->StrCache.Entries == nullptr ) | ||||
| 			GEN_FATAL( "gen::init: Failed to initialize the StringCache"); | ||||
|  | ||||
| 		ctx->PreprocessorMacros = hashtable_init(PreprocessorMacros, ctx->Allocator_DyanmicContainers); | ||||
| 		if (ctx->PreprocessorMacros.Hashes == nullptr || ctx->PreprocessorMacros.Entries == nullptr) { | ||||
| 			GEN_FATAL( "gen::init: Failed to initialize the PreprocessMacros table" ); | ||||
| 		} | ||||
| 	} | ||||
| 	// Preprocessor Defines | ||||
| 	ctx->PreprocessorDefines = array_init_reserve(StrCached, ctx->Allocator_DyanmicContainers, kilobytes(1) ); | ||||
|  | ||||
| 	define_constants(); | ||||
| 	parser_init(); | ||||
| @@ -354,9 +356,7 @@ void deinit(Context* ctx) | ||||
| 	array_free( ctx->CodePools); | ||||
| 	array_free( ctx->StringArenas); | ||||
|  | ||||
| 	// arena_free(& ctx->LexArena); | ||||
|  | ||||
| 	array_free(ctx->PreprocessorDefines); | ||||
| 	hashtable_destroy(ctx->PreprocessorMacros); | ||||
|  | ||||
| 	left  = array_num( ctx->Fallback_AllocatorBuckets); | ||||
| 	if (left) | ||||
| @@ -401,6 +401,7 @@ void reset(Context* ctx) | ||||
| 	while ( left--, left ); | ||||
|  | ||||
| 	hashtable_clear(ctx->StrCache); | ||||
| 	hashtable_clear(ctx->PreprocessorMacros); | ||||
| 	define_constants(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -156,6 +156,7 @@ GEN_API CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEF | ||||
| struct Opts_def_define { | ||||
| 	MacroFlags       flags; | ||||
| 	CodeDefineParams params; | ||||
| 	Str              content; | ||||
| 	b32              dont_register_to_preprocess_macros; | ||||
| }; | ||||
| GEN_API CodeDefine def_define( Str name, MacroType type, Opts_def_define opts GEN_PARAM_DEFAULT ); | ||||
| @@ -269,28 +270,30 @@ GEN_API CodeBody def_body( CodeType type ); | ||||
| // There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num, | ||||
| /// or provide as an array of Code objects. | ||||
|  | ||||
| GEN_API CodeBody       def_class_body      ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_class_body      ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody       def_enum_body       ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_enum_body       ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody       def_export_body     ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_export_body     ( s32 num, Code* codes); | ||||
| GEN_API CodeBody       def_extern_link_body( s32 num, ... ); | ||||
| GEN_API CodeBody       def_extern_link_body( s32 num, Code* codes ); | ||||
| GEN_API CodeBody       def_function_body   ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_function_body   ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody       def_global_body     ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_global_body     ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody       def_namespace_body  ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_namespace_body  ( s32 num, Code* codes ); | ||||
| GEN_API CodeParams     def_params          ( s32 num, ... ); | ||||
| GEN_API CodeParams     def_params          ( s32 num, CodeParams* params ); | ||||
| GEN_API CodeSpecifiers def_specifiers      ( s32 num, ... ); | ||||
| GEN_API CodeSpecifiers def_specifiers      ( s32 num, Specifier* specs ); | ||||
| GEN_API CodeBody       def_struct_body     ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_struct_body     ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody       def_union_body      ( s32 num, ... ); | ||||
| GEN_API CodeBody       def_union_body      ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody         def_class_body      ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_class_body      ( s32 num, Code* codes ); | ||||
| GEN_API CodeDefineParams def_define_params   ( s32 num, ... ); | ||||
| GEN_API CodeDefineParams def_define_params   ( s32 num, CodeDefineParams* codes ) | ||||
| GEN_API CodeBody         def_enum_body       ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_enum_body       ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody         def_export_body     ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_export_body     ( s32 num, Code* codes); | ||||
| GEN_API CodeBody         def_extern_link_body( s32 num, ... ); | ||||
| GEN_API CodeBody         def_extern_link_body( s32 num, Code* codes ); | ||||
| GEN_API CodeBody         def_function_body   ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_function_body   ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody         def_global_body     ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_global_body     ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody         def_namespace_body  ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_namespace_body  ( s32 num, Code* codes ); | ||||
| GEN_API CodeParams       def_params          ( s32 num, ... ); | ||||
| GEN_API CodeParams       def_params          ( s32 num, CodeParams* params ); | ||||
| GEN_API CodeSpecifiers   def_specifiers      ( s32 num, ... ); | ||||
| GEN_API CodeSpecifiers   def_specifiers      ( s32 num, Specifier* specs ); | ||||
| GEN_API CodeBody         def_struct_body     ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_struct_body     ( s32 num, Code* codes ); | ||||
| GEN_API CodeBody         def_union_body      ( s32 num, ... ); | ||||
| GEN_API CodeBody         def_union_body      ( s32 num, Code* codes ); | ||||
|  | ||||
| #pragma endregion Upfront | ||||
|  | ||||
|   | ||||
| @@ -516,7 +516,6 @@ CodeClass def_class( Str name, Opts_def_struct p ) | ||||
| 		GEN_DEBUG_TRAP(); | ||||
| 		return InvalidCode; | ||||
| 	} | ||||
|  | ||||
| 	if ( p.attributes && p.attributes->Type != CT_PlatformAttributes ) { | ||||
| 		log_failure( "gen::def_class: attributes was not a 'PlatformAttributes' type: %s", code_debug_str(p.attributes) ); | ||||
| 		GEN_DEBUG_TRAP(); | ||||
| @@ -529,9 +528,12 @@ CodeClass def_class( Str name, Opts_def_struct p ) | ||||
| 	} | ||||
|  | ||||
| 	CodeClass | ||||
| 	result              = (CodeClass) make_code(); | ||||
| 	result->Name        = cache_str( name ); | ||||
| 	result->ModuleFlags = p.mflags; | ||||
| 	result               = (CodeClass) make_code(); | ||||
| 	result->Name         = cache_str( name ); | ||||
| 	result->ModuleFlags  = p.mflags; | ||||
| 	result->Attributes   = p.attributes; | ||||
| 	result->ParentAccess = p.parent_access; | ||||
| 	result->ParentType   = p.parent; | ||||
| 	if ( p.body ) | ||||
| 	{ | ||||
| 		switch ( p.body->Type ) | ||||
| @@ -552,44 +554,32 @@ CodeClass def_class( Str name, Opts_def_struct p ) | ||||
| 	else { | ||||
| 		result->Type = CT_Class_Fwd; | ||||
| 	} | ||||
|  | ||||
| 	result->Attributes   = p.attributes; | ||||
| 	result->ParentAccess = p.parent_access; | ||||
| 	result->ParentType   = p.parent; | ||||
|  | ||||
| 	for (s32 idx = 0; idx < p.num_interfaces; idx++ ) { | ||||
| 		class_add_interface(result, p.interfaces[idx] ); | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| CodeDefine def_define( Str name, Str content, Opts_def_define p ) | ||||
| CodeDefine def_define( Str name, MacroType type, Opts_def_define p ) | ||||
| { | ||||
| 	if ( ! name_check( def_define, name ) ) { | ||||
| 		GEN_DEBUG_TRAP(); | ||||
| 		return InvalidCode; | ||||
| 	} | ||||
|  | ||||
| 	CodeDefine | ||||
| 	result          = (CodeDefine) make_code(); | ||||
| 	result->Type    = CT_Preprocess_Define; | ||||
| 	result->Name    = cache_str( name ); | ||||
|  | ||||
| 	if ( content.Len <= 0 || content.Ptr == nullptr ) | ||||
| 		result->Content = cache_str( txt("") ); | ||||
| 	result->Params  = p.params; | ||||
| 	if ( p.content.Len <= 0 || p.content.Ptr == nullptr ) | ||||
| 		result->Content = cache_str( txt("\n") ); | ||||
| 	else | ||||
| 		result->Content = cache_str( strbuilder_to_str(strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S\n", content)) ); | ||||
|  | ||||
| 	b32  append_preprocess_defines = ! p.dont_append_preprocess_defines; | ||||
| 	if ( append_preprocess_defines ) { | ||||
| 		// Add the define to PreprocessorDefines for usage in parsing | ||||
| 		s32 lex_id_len = 0; | ||||
| 		for (; lex_id_len < result->Name.Len; ++ lex_id_len ) { | ||||
| 			if ( result->Name.Ptr[lex_id_len] == '(' ) | ||||
| 				break; | ||||
| 		} | ||||
| 		Str lex_id = { result->Name.Ptr,  lex_id_len }; | ||||
| 		array_append(_ctx->PreprocessorDefines, cache_str(lex_id) ); | ||||
| 	b32  register_define = ! p.dont_register_to_preprocess_macros; | ||||
| 	if ( register_define ) { | ||||
| 		macro_entry = { result->Name, type, p.flags }; | ||||
| 		register_preprocess_macro(macro_entry); | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
| @@ -1410,6 +1400,67 @@ CodeBody def_class_body( s32 num, Code* codes ) | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| CodeDefineParams def_define_params( s32 num, ... ) | ||||
| { | ||||
| 	def_body_start( def_define_params ); | ||||
|  | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
|  | ||||
| 	Code_POD         pod   = va_arg(va, Code_POD); | ||||
| 	CodeDefineParams param = pcast( CodeDefineParams, pod ); | ||||
|  | ||||
| 	null_check( def_define_params, param ); | ||||
| 	if ( param->Type != CT_Parameters_Define ) { | ||||
| 		log_failure( "gen::def_define_params: param %d is not a parameter for a preprocessor define", num - num + 1 ); | ||||
| 		return InvalidCode; | ||||
| 	} | ||||
|  | ||||
| 	CodeDefineParams result = (CodeDefineParams) code_duplicate(param); | ||||
| 	while ( -- num ) | ||||
| 	{ | ||||
| 		pod   = va_arg(va, Code_POD); | ||||
| 		param = pcast( CodeDefineParams, pod ); | ||||
| 		if ( param->Type != CT_Parameters_Define ) { | ||||
| 			log_failure( "gen::def_define_params: param %d is not a parameter for a preprocessor define", num - num + 1 ); | ||||
| 			return InvalidCode; | ||||
| 		} | ||||
| 		define_params_append(result, param ); | ||||
| 	} | ||||
| 	va_end(va); | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| CodeDefineParams def_define_params( s32 num, CodeDefineParams* codes ) | ||||
| { | ||||
| 	def_body_code_array_start( def_define_params ); | ||||
|  | ||||
| #	define check_current(current)                                                                                                                 \ | ||||
| 	if ( current == nullptr ) {                                                                                                                   \ | ||||
| 		log_failure("gen::def_define_params: Provide a null code in codes array");                                                                \ | ||||
| 		return InvalidCode;                                                                                                                       \ | ||||
| 	}                                                                                                                                             \ | ||||
| 	if (current->Type != CT_Parameters_Define ) {                                                                                                 \ | ||||
| 		log_failure("gen::def_define_params: Code in coes array is not of paramter for preprocessor define type - %s", code_debug_str(current) ); \ | ||||
| 		return InvalidCode;                                                                                                                       \ | ||||
| 	} | ||||
| 	CodeDefineParams current = (CodeDefineParams)code_duplicate(* codes); | ||||
| 	check_current(current); | ||||
|  | ||||
| 	CodeDefineParams | ||||
| 	result            = (CodeDefineParams) make_code(); | ||||
| 	result->Name      = current->Name; | ||||
| 	result->Type      = current->Type; | ||||
| 	while( codes++, current = * codes, num--, num > 0 ) { | ||||
| 		check_current(current); | ||||
| 		define_params_append(result, current ); | ||||
| 	} | ||||
| #	undef check_current | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| CodeBody def_enum_body( s32 num, ... ) | ||||
| { | ||||
| 	def_body_start( def_enum_body ); | ||||
|   | ||||
| @@ -112,6 +112,102 @@ void lexer_end_line( LexContext* ctx ) | ||||
| } | ||||
| #define end_line() lexer_end_line(ctx) | ||||
|  | ||||
| // TODO(Ed): We need to to attempt to recover from a lex failure? | ||||
| s32 lex_preprocessor_define( LexContext* ctx ) | ||||
| { | ||||
| 	Token name = { { ctx->scanner, 1 }, Tok_Identifier, ctx->line, ctx->column, TF_Preprocess }; | ||||
| 	move_forward(); | ||||
|  | ||||
| 	PreprocessorMacro  macro            = { name.Text, MT_Statement, 0 }; | ||||
| 	PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text); | ||||
| 	if ( registered_macro == nullptr ) { | ||||
| 		log_fmt("Warning: %S is was not registered before the lexer processed its #define directive, it will be registered as a statement macro" | ||||
| 			, name.Text  | ||||
| 		); | ||||
| 	} | ||||
| 	while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) { | ||||
| 		move_forward(); | ||||
| 		name.Text.Len++; | ||||
| 	} | ||||
| 	array_append( _ctx->Lexer_Tokens, name ); | ||||
|  | ||||
| 	if ( ctx->left && (* ctx->scanner) == '(' ) | ||||
| 	{ | ||||
| 		if (registered_macro && ! macro_is_functional(* registered_macro)) { | ||||
| 			log_fmt("Warning: %S registered macro is not flagged as functional yet the definition detects opening parenthesis '(' for arguments" | ||||
| 				, name.Text | ||||
| 			); | ||||
| 		} | ||||
| 		else { | ||||
| 			macro.Flags |= MF_Functional; | ||||
| 		} | ||||
|  | ||||
| 		Token opening_paren = { { ctx->scanner, 1 }, Tok_Capture_Start, ctx->line, ctx->column, TF_Preprocess }; | ||||
| 		array_append( _ctx->Lexer_Tokens, opening_paren ); | ||||
| 		move_forward(); | ||||
|  | ||||
| 		// We need to tokenize the define's arguments now: | ||||
| 		while( ctx->left && * ctx->scanner != ')') | ||||
| 		{ | ||||
| 			skip_whitespace(); | ||||
| 			if ( char_is_alpha( (* ctx->scanner) ) || (* ctx->scanner) == '_' ) | ||||
| 			{ | ||||
| 				Token parameter = { { ctx->scanner, 1 }, Tok_Preprocess_Define_Param, ctx->line, ctx->column, TF_Preprocess }; | ||||
| 				move_forward(); | ||||
|  | ||||
| 				while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) | ||||
| 				{ | ||||
| 					move_forward(); | ||||
| 					parameter.Text.Len++; | ||||
| 				} | ||||
| 				array_append(_ctx->Lexer_Tokens, parameter); | ||||
| 				skip_whitespace(); | ||||
| 			} | ||||
| 			else { | ||||
| 				log_failure("lex_preprocessor_define(%d, %d): Expected a '_' or alpha character for a parameter name for %S\n" | ||||
| 					, ctx->line | ||||
| 					, ctx->column | ||||
| 					, name.Text | ||||
| 				); | ||||
| 				return Lex_ReturnNull; | ||||
| 			} | ||||
| 			// There should be a comma | ||||
| 			if ( * ctx->scanner != ',' ) { | ||||
| 				log_failure("lex_preprocessor_define(%d, %d): Expected a comma after parameter %S for %S\n" | ||||
| 					, ctx->line | ||||
| 					, ctx->column | ||||
| 					, parameter.Text | ||||
| 					, name.Text | ||||
| 				); | ||||
| 				return Lex_ReturnNull; | ||||
| 			} | ||||
| 			Token comma = { { ctx->scanner, 1 }, Tok_Comma, ctx->line, ctx->column, TF_Preprocess }; | ||||
| 			array_append(_ctx->Lexer_Tokens, comma); | ||||
| 			move_forward(); | ||||
| 		} | ||||
| 		 | ||||
| 		if ( * ctx->scanner != ')' ) { | ||||
| 			log_failure("lex_preprocessor_define(%d, %d): Expected a ')' after last_parameter %S for %S (ran out of characters...)\n" | ||||
| 				, ctx->line | ||||
| 				, ctx->column | ||||
| 				, parameter.Text | ||||
| 				, name.Text | ||||
| 			); | ||||
| 			return Lex_ReturnNull; | ||||
| 		} | ||||
| 		Token closing_paren = { { ctx->scanner, 1 }, Tok_Capture_End, ctx->line, ctx->column, TF_Preprocess }; | ||||
| 		array_append(_ctx->Lexer_Tokens, closing_paren); | ||||
| 		move_forward(); | ||||
| 	} | ||||
| 	if ( registered_macro == nullptr ) { | ||||
| 		register_preprocess_macro(macro); | ||||
| 	} | ||||
|  | ||||
| 	// Define's content handled by lex_preprocessor_directive (the original caller of this) | ||||
| 	return Lex_Continue; | ||||
| } | ||||
|  | ||||
| // TODO(Ed): We need to to attempt to recover from a lex failure? | ||||
| forceinline | ||||
| s32 lex_preprocessor_directive( LexContext* ctx ) | ||||
| { | ||||
| @@ -215,31 +311,9 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | ||||
|  | ||||
| 	if ( ctx->token.Type == Tok_Preprocess_Define ) | ||||
| 	{ | ||||
| 		Token name = { { ctx->scanner, 0 }, Tok_Identifier, ctx->line, ctx->column, TF_Preprocess }; | ||||
|  | ||||
| 		name.Text.Ptr = ctx->scanner; | ||||
| 		name.Text.Len = 1; | ||||
| 		move_forward(); | ||||
|  | ||||
| 		PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text); | ||||
| 		 | ||||
|  | ||||
| 		while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) | ||||
| 		{ | ||||
| 			move_forward(); | ||||
| 			name.Text.Len++; | ||||
| 		} | ||||
|  | ||||
| 		if ( ctx->left && (* ctx->scanner) == '(' ) | ||||
| 		{ | ||||
| 			move_forward(); | ||||
| 			name.Text.Len++; | ||||
| 		} | ||||
|  | ||||
| 		array_append( _ctx->Lexer_Tokens, name ); | ||||
|  | ||||
| 		u64 key = crc32( name.Text.Ptr, name.Text.Len ); | ||||
| 		hashtable_set(ctx->defines, key, tok_to_str(name) ); | ||||
| 		u32 result = lex_preprocessor_define(ctx); // handles: #define <name>( <params> ) - define's content handled later on within this scope. | ||||
| 		if (result != Lex_Continue) | ||||
| 			return Lex_ReturnNull; | ||||
| 	} | ||||
|  | ||||
| 	Token preprocess_content = { { ctx->scanner, 0 }, Tok_Preprocess_Content, ctx->line, ctx->column, TF_Preprocess }; | ||||
| @@ -289,7 +363,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | ||||
| 	s32 within_string = false; | ||||
| 	s32 within_char   = false; | ||||
|  | ||||
| 	// SkipWhitespace(); | ||||
| 	// Consume preprocess content | ||||
| 	while ( ctx->left ) | ||||
| 	{ | ||||
| 		if ( (* ctx->scanner) == '"' && ! within_char ) | ||||
| @@ -325,6 +399,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | ||||
| 					, (* ctx->scanner), ctx->line, ctx->column | ||||
| 					, directive_str, preprocess_content.Line, preprocess_content.Column | ||||
| 					, content_str ); | ||||
| 				return Lex_ReturnNull; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| @@ -404,14 +479,15 @@ void lex_found_token( LexContext* ctx ) | ||||
| 	} | ||||
|  | ||||
| 	u64 key = 0; | ||||
| 	if ( (* ctx->scanner) == '(') | ||||
| 		key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len + 1 ); | ||||
| 	else | ||||
| 		key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len ); | ||||
| 	// if ( (* ctx->scanner) == '(') | ||||
| 	// 	key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len + 1 ); | ||||
| 	// else | ||||
| 	key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len ); | ||||
|  | ||||
| 	Str* define = hashtable_get(ctx->defines, key ); | ||||
| 	Str* define = hashtable_get(_ctx->PreprocessMacros, key ); | ||||
| 	if ( define ) | ||||
| 	{ | ||||
| 		// TODO(Ed): Needs updating (Macros) | ||||
| 		ctx->token.Type = Tok_Preprocess_Macro; | ||||
|  | ||||
| 		// Want to ignore any arguments the define may have as they can be execution expressions. | ||||
| @@ -456,6 +532,7 @@ void lex_found_token( LexContext* ctx ) | ||||
| 	array_append( _ctx->Lexer_Tokens, ctx->token ); | ||||
| } | ||||
|  | ||||
| // TODO(Ed): We need to to attempt to recover from a lex failure? | ||||
| neverinline | ||||
| // TokArray lex( Array<Token> tokens, Str content ) | ||||
| TokArray lex( Str content ) | ||||
| @@ -480,27 +557,10 @@ TokArray lex( Str content ) | ||||
| 		return null_array; | ||||
| 	} | ||||
|  | ||||
| 	// TODO(ED): Remove this when preprocess defines has been converted | ||||
| 	// for ( StrCached* entry = array_begin(_ctx->PreprocessorDefines); entry != array_end(_ctx->PreprocessorDefines); entry = array_next(_ctx->PreprocessorDefines, entry)) | ||||
| 	// { | ||||
| 	// 	s32         length  = 0; | ||||
| 	// 	char const* entry_scanner = (*entry).Ptr; | ||||
| 	// 	while ( entry->Len > length && (char_is_alphanumeric( *entry_scanner ) || *entry_scanner == '_') ) | ||||
| 	// 	{ | ||||
| 	// 		entry_scanner++; | ||||
| 	// 		length ++; | ||||
| 	// 	} | ||||
| 	// 	if ( entry_scanner[0] == '(' ) | ||||
| 	// 	{ | ||||
| 	// 		length++; | ||||
| 	// 	} | ||||
|  | ||||
| 	// 	u64 key = crc32( entry->Ptr, length ); | ||||
| 	// 	hashtable_set(c.defines, key, * entry ); | ||||
| 	// } | ||||
|  | ||||
| 	array_clear(_ctx->Lexer_Tokens); | ||||
|  | ||||
| 	b32 preprocess_args = true; | ||||
|  | ||||
| 	while (c.left ) | ||||
| 	{ | ||||
| 		#if 0 | ||||
| @@ -1182,6 +1242,7 @@ TokArray lex( Str content ) | ||||
| 		{ | ||||
| 			lex_found_token( ctx ); | ||||
| 			TokType last_type = array_back(_ctx->Lexer_Tokens)->Type; | ||||
| 			// TODO(Ed): Change this to just detect if its a MACRO THAT SHOULD ACCEPT NEWLINES | ||||
| 			if ( last_type == Tok_Preprocess_Macro ) | ||||
| 			{ | ||||
| 				Token thanks_c = { { c.scanner, 0 }, Tok_Invalid, c.line, c.column, TF_Null }; | ||||
| @@ -1217,6 +1278,7 @@ TokArray lex( Str content ) | ||||
| 	TokArray result = { _ctx->Lexer_Tokens, 0 }; | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| #undef move_forward | ||||
| #undef skip_whitespace | ||||
| #undef end_line | ||||
|   | ||||
| @@ -825,22 +825,21 @@ CodeBody parse_class_struct_body( TokType which, Token name ) | ||||
|  | ||||
| 		switch ( currtok_noskip.Type ) | ||||
| 		{ | ||||
| 			case Tok_Statement_End: | ||||
| 			{ | ||||
| 			case Tok_Statement_End: { | ||||
| 				// TODO(Ed): Convert this to a general warning procedure | ||||
| 				log_fmt("Dangling end statement found %SB\n", tok_to_strbuilder(currtok_noskip)); | ||||
| 				eat( Tok_Statement_End ); | ||||
| 				continue; | ||||
| 			} | ||||
| 			case Tok_NewLine: | ||||
| 			case Tok_NewLine: { | ||||
| 				member = fmt_newline; | ||||
| 				eat( Tok_NewLine ); | ||||
| 			break; | ||||
|  | ||||
| 			case Tok_Comment: | ||||
| 				break; | ||||
| 			} | ||||
| 			case Tok_Comment: { | ||||
| 				member = cast(Code, parse_comment()); | ||||
| 			break; | ||||
|  | ||||
| 				break; | ||||
| 			} | ||||
| 			case Tok_Access_Public: | ||||
| 				member = access_public; | ||||
| 				eat( Tok_Access_Public ); | ||||
| @@ -1727,8 +1726,8 @@ CodeBody parse_global_nspace( CodeType which ) | ||||
| 				// <Macro> | ||||
| 				macro_found = true; | ||||
| 				goto Preprocess_Macro_Bare_In_Body; | ||||
| 				// TODO(Ed): MACRO UPDATE | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			case Tok_Preprocess_Pragma: { | ||||
| 				member = cast(Code, parse_pragma()); | ||||
| @@ -2727,7 +2726,7 @@ CodeParams parse_params( bool use_template_capture ) | ||||
| 		// In template captures you can have a typename have direct assignment without a name | ||||
| 		// typename = typename ... | ||||
| 		// Which would result in a static value type from a struct expansion (traditionally) | ||||
| 		if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) | ||||
| 		if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_set( u32, currtok.Flags, TF_Assign ) ) | ||||
| 		{ | ||||
| 			eat( Tok_Operator ); | ||||
| 			// ( <Macro> <ValueType> <Name> = | ||||
| @@ -2839,7 +2838,7 @@ CodeParams parse_params( bool use_template_capture ) | ||||
| 			// In template captures you can have a typename have direct assignment without a name | ||||
| 			// typename = typename ... | ||||
| 			// Which would result in a static value type from a struct expansion (traditionally) | ||||
| 			if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) | ||||
| 			if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_set( u32, currtok.Flags, TF_Assign ) ) | ||||
| 			{ | ||||
| 				eat( Tok_Operator ); | ||||
| 				// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = | ||||
| @@ -3166,7 +3165,7 @@ CodeVar parse_variable_after_name( | ||||
|  | ||||
| 	b32 using_constructor_initializer = false; | ||||
|  | ||||
| 	if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) | ||||
| 	if ( bitfield_is_set( u32, currtok.Flags, TF_Assign ) ) | ||||
| 	{ | ||||
| 		// <Attributes> <Specifiers> <ValueType> <Name> = <Expression> | ||||
| 		expr = parse_assignment_expression(); | ||||
| @@ -4645,6 +4644,7 @@ else if ( currtok.Type == Tok_DeclType ) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// TODO(Ed): This needs updating | ||||
| 	else if ( currtok.Type == Tok_Preprocess_Macro ) { | ||||
| 		// Typename is a macro | ||||
| 		name = currtok; | ||||
| @@ -4988,6 +4988,7 @@ CodeTypedef parser_parse_typedef() | ||||
|  | ||||
| 	const bool from_typedef = true; | ||||
|  | ||||
| 	// TODO(Ed): UPDATE MACRO USAGE HERE | ||||
| #if GEN_PARSER_DISABLE_MACRO_TYPEDEF | ||||
| 	if ( false ) | ||||
| #else | ||||
| @@ -5365,7 +5366,7 @@ CodeUsing parser_parse_using() | ||||
|  | ||||
| 	if ( ! is_namespace ) | ||||
| 	{ | ||||
| 		if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) | ||||
| 		if ( bitfield_is_set( u32, currtok.Flags, TF_Assign ) ) | ||||
| 		{ | ||||
| 			attributes = parse_attributes(); | ||||
| 			// <ModuleFlags> using <Name> <Attributes> | ||||
|   | ||||
| @@ -6,34 +6,6 @@ | ||||
| #include "gen/especifier.hpp" | ||||
| #endif | ||||
|  | ||||
| enum MacroTypes : u16 | ||||
| { | ||||
| 	MT_Block_Start,    // Not Supported yet | ||||
| 	MT_Block_End,      // Not Supported yet | ||||
| 	MT_Case_Statement, // Not Supported yet | ||||
| 	MT_Expression, | ||||
| 	MT_Statement, | ||||
| 	MT_Typename, | ||||
|  | ||||
| 	MF_UnderlyingType = GEN_U16_Max, | ||||
| }; | ||||
|  | ||||
| enum MacroFlags : u16 | ||||
| { | ||||
| 	MF_Functional     = bit(0), // Macro has parameters (args expected to be passed) | ||||
| 	MF_Expects_Body   = bit(1), // Expects to assign a braced scope to its body. | ||||
|  | ||||
| 	MF_Null           = 0, | ||||
| 	MF_UnderlyingType = GEN_U16_Max, | ||||
| }; | ||||
|  | ||||
| struct PreprocessorMacro | ||||
| { | ||||
| 	StrCached  Name; | ||||
| 	MacroTypes Type; | ||||
| 	MacroFlags Flags; | ||||
| }; | ||||
|  | ||||
| enum TokFlags : u32 | ||||
| { | ||||
| 	TF_Operator		         = bit(0), | ||||
| @@ -82,42 +54,42 @@ bool tok_is_valid( Token tok ) { | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_access_operator(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_AccessOperator ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_AccessOperator ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_access_specifier(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_AccessSpecifier ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_AccessSpecifier ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_attribute(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_Attribute ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_Attribute ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_operator(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_Operator ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_Operator ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_preprocessor(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_Preprocess ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_Preprocess ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_preprocess_cond(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_Preprocess_Cond ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_Preprocess_Cond ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_specifier(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_Specifier ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_Specifier ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| bool tok_is_end_definition(Token tok) { | ||||
| 	return bitfield_is_equal( u32, tok.Flags, TF_EndDefinition ); | ||||
| 	return bitfield_is_set( u32, tok.Flags, TF_EndDefinition ); | ||||
| } | ||||
|  | ||||
| StrBuilder tok_to_strbuilder(Token tok); | ||||
| @@ -153,3 +125,60 @@ struct ParseContext | ||||
| 	TokArray   Tokens; | ||||
| 	StackNode* Scope; | ||||
| }; | ||||
|  | ||||
| enum MacroType : u16 | ||||
| { | ||||
| 	MT_Statement,      // A macro is assumed to be a statement if not resolved. | ||||
| 	MT_Expression, | ||||
| 	MT_Typename, | ||||
| 	MT_Block_Start,    // Not Supported yet | ||||
| 	MT_Block_End,      // Not Supported yet | ||||
| 	MT_Case_Statement, // Not Supported yet | ||||
|  | ||||
| 	MF_UnderlyingType = GEN_U16_Max, | ||||
| }; | ||||
|  | ||||
| Str macro_type_to_str( MacroType type ) | ||||
| { | ||||
| 	local_persist | ||||
| 	Str lookup[ (u32)Num_ModuleFlags ] = { | ||||
| 		{ "Statement",      sizeof("Statement")      - 1 }, | ||||
| 		{ "Expression",     sizeof("Expression")     - 1 }, | ||||
| 		{ "Typename",       sizeof("Typename")       - 1 }, | ||||
| 		{ "Block_Start",    sizeof("Block_Start")    - 1 }, | ||||
| 		{ "Block_End",      sizeof("Block_End")      - 1 }, | ||||
| 		{ "Case_Statement", sizeof("Case_Statement") - 1 }, | ||||
| 	}; | ||||
| 	local_persist | ||||
| 	Str invalid_flag = { "Invalid", sizeof("Invalid") }; | ||||
| 	if ( flag > ModuleFlag_Import ) | ||||
| 		return invalid_flag; | ||||
|  | ||||
| 	return lookup[ (u32)flag ]; | ||||
| } | ||||
|  | ||||
| enum MacroFlags : u16 | ||||
| { | ||||
| 	MF_Functional     = bit(0), // Macro has parameters (args expected to be passed) | ||||
| 	MF_Expects_Body   = bit(1), // Expects to assign a braced scope to its body. | ||||
|  | ||||
| 	MF_Null           = 0, | ||||
| 	MF_UnderlyingType = GEN_U16_Max, | ||||
| }; | ||||
|  | ||||
| struct PreprocessorMacro | ||||
| { | ||||
| 	StrCached  Name; | ||||
| 	MacroType  Type; | ||||
| 	MacroFlags Flags; | ||||
| }; | ||||
|  | ||||
| forceinine | ||||
| b32 macro_is_functional( PreprocessorMacro macro ) { | ||||
| 	return bitfield_is_set( macro->Flags, MF_Functional ); | ||||
| } | ||||
|  | ||||
| forceinline | ||||
| b32 macro_expects_body( PreprocessorMacro macro ) { | ||||
| 	return bitfield_is_set( macro->Flags, MF_Expects_Body ); | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ global Context* _ctx; | ||||
| #pragma region Constants | ||||
| global u32 context_counter; | ||||
|  | ||||
| global Str enum_underlying_sig; | ||||
| global PreprocessorMacro enum_underlying_macro; | ||||
|  | ||||
| global Code Code_Global; | ||||
| global Code Code_Invalid; | ||||
|   | ||||
| @@ -34,8 +34,8 @@ | ||||
| #endif | ||||
|  | ||||
| #ifndef bit | ||||
| #define bit( Value )                             ( 1 << Value ) | ||||
| #define bitfield_is_equal( Type, Field, Mask ) ( (scast(Type, Mask) & scast(Type, Field)) == scast(Type, Mask) ) | ||||
| #define bit( Value )                         ( 1 << Value ) | ||||
| #define bitfield_is_set( Type, Field, Mask ) ( (scast(Type, Mask) & scast(Type, Field)) == scast(Type, Mask) ) | ||||
| #endif | ||||
|  | ||||
| // Mainly intended for forcing the base library to utilize only C-valid constructs or type coercion | ||||
|   | ||||
| @@ -42,6 +42,7 @@ Number,                     "__number__" | ||||
| Operator,                   "__operator__" | ||||
| Preprocess_Hash,            "#" | ||||
| Preprocess_Define,          "define" | ||||
| Preprocess_Define_Param,    "__define_param__" | ||||
| Preprocess_If,              "if" | ||||
| Preprocess_IfDef,           "ifdef" | ||||
| Preprocess_IfNotDef,        "ifndef" | ||||
|   | ||||
| 
 | 
| @@ -41,7 +41,7 @@ | ||||
| #undef local_persist | ||||
|  | ||||
| #undef bit | ||||
| #undef bitfield_is_equal | ||||
| #undef bitfield_is_set | ||||
|  | ||||
| #undef cast | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ word global,                       gen_global | ||||
| word internal,                     gen_internal | ||||
| word local_persist,                gen_local_persist | ||||
| word bit,                          gen_bit | ||||
| word bitfield_is_equal,            gen_bitfield_is_equal | ||||
| word bitfield_is_set,            gen_bitfield_is_set | ||||
| word cast,                         gen_cast | ||||
| word ccast,                        gen_ccast | ||||
| word pcast,                        gen_pcast | ||||
|   | ||||
		Reference in New Issue
	
	Block a user