diff --git a/Project/Source/GasaGen/gen.cpp b/Project/Source/GasaGen/gen.cpp index f00a0e4..505c889 100644 --- a/Project/Source/GasaGen/gen.cpp +++ b/Project/Source/GasaGen/gen.cpp @@ -36,7 +36,7 @@ global Context* _ctx; #pragma region Constants global u32 context_counter; -global Str enum_underlying_sig; +global Macro enum_underlying_macro; global Code Code_Global; global Code Code_Invalid; @@ -121,9 +121,9 @@ global CodeTypename t_f64; #pragma region AST -// These macros are used in the swtich cases are used within ast.cpp, inteface.upfront.cpp, parser.cpp +// These macros are used in the swtich cases within ast.cpp, inteface.upfront.cpp, parser.cpp -# define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \ +# define GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES \ case CT_PlatformAttributes: \ case CT_Class_Body: \ case CT_Enum_Body: \ @@ -139,9 +139,9 @@ global CodeTypename t_f64; case CT_Specifiers: \ case CT_Struct_Body: \ case CT_Typename -# define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES +# define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES -# define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \ +# define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES \ case CT_Access_Public: \ case CT_Access_Protected: \ case CT_Access_Private: \ @@ -164,7 +164,7 @@ global CodeTypename t_f64; case CT_Struct_Body: \ case CT_Typename -# define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES \ +# define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES \ case CT_Access_Public: \ case CT_Access_Protected: \ case CT_Access_Private: \ @@ -181,10 +181,10 @@ global CodeTypename t_f64; case CT_Specifiers: \ case CT_Struct_Body: \ case CT_Typename -# define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES -# define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES +# define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES +# define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES -# define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \ +# define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES \ case CT_Access_Public: \ case CT_Access_Protected: \ case CT_Access_Private: \ @@ -235,7 +235,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: @@ -251,6 +250,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 ) @@ -458,6 +462,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 ); @@ -696,6 +705,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; @@ -1186,11 +1199,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; } @@ -1364,7 +1383,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type) { - GEN_AST_BODY_CLASS_UNALLOWED_TYPES: + GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry)); return false; @@ -1391,7 +1410,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type) { - GEN_AST_BODY_EXPORT_UNALLOWED_TYPES: + GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry)); return false; @@ -1405,7 +1424,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type) { - GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES: + GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry)); return false; @@ -1419,7 +1438,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type) { - GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES: + GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry)); return false; @@ -1433,7 +1452,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) )switch (entry->Type) { - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES: + GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(entry)); return false; } @@ -1444,7 +1463,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) ) switch (entry->Type) { - GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES: + GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(entry)); return false; } @@ -1455,7 +1474,7 @@ bool code_validate_body(Code self) CodeBody body = cast(CodeBody, self); for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) ) switch (entry->Type) { - GEN_AST_BODY_STRUCT_UNALLOWED_TYPES: + GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES: log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(entry)); return false; } @@ -1655,7 +1674,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 ") ); @@ -1700,7 +1719,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 ) @@ -1720,12 +1739,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.Ptr && define->Body->Content.Len > 0); + 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 self, 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 ( CodeDefineParams param = begin_CodeDefineParams(self->Next); param != end_CodeDefineParams(self->Next); param = next_CodeDefineParams(self->Next, param) ) + { + strbuilder_append_fmt( result, ", %SB", define_params_to_strbuilder(param) ); + } + } } StrBuilder destructor_to_strbuilder(CodeDestructor self) @@ -1808,7 +1863,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 ) @@ -1841,7 +1896,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 ) @@ -1868,7 +1923,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 ) @@ -1900,7 +1955,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 ") ); @@ -1984,7 +2039,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 ) @@ -2037,7 +2092,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 ) @@ -2125,7 +2180,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) ); @@ -2150,7 +2205,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 ) @@ -2204,7 +2259,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 ) @@ -2344,7 +2399,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 ); @@ -2509,7 +2563,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 ") ); @@ -2555,7 +2609,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 ) @@ -2584,7 +2638,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 ) @@ -2602,7 +2656,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 ")); @@ -2715,7 +2769,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 ") ); @@ -2746,7 +2800,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 ") ); @@ -2783,7 +2837,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 ) @@ -2880,7 +2934,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 ) @@ -3150,37 +3204,39 @@ void define_constants() #endif spec_const = def_specifier( Spec_Const); code_set_global( cast(Code, spec_const )); - spec_consteval = def_specifier( Spec_Consteval); code_set_global( cast(Code, spec_consteval ));; - spec_constexpr = def_specifier( Spec_Constexpr); code_set_global( cast(Code, spec_constexpr ));; - spec_constinit = def_specifier( Spec_Constinit); code_set_global( cast(Code, spec_constinit ));; - spec_extern_linkage = def_specifier( Spec_External_Linkage); code_set_global( cast(Code, spec_extern_linkage ));; - spec_final = def_specifier( Spec_Final); code_set_global( cast(Code, spec_final ));; - spec_FORCEINLINE = def_specifier( Spec_ForceInline); code_set_global( cast(Code, spec_FORCEINLINE ));; - spec_global = def_specifier( Spec_Global); code_set_global( cast(Code, spec_global ));; - spec_inline = def_specifier( Spec_Inline); code_set_global( cast(Code, spec_inline ));; - spec_internal_linkage = def_specifier( Spec_Internal_Linkage); code_set_global( cast(Code, spec_internal_linkage ));; - spec_local_persist = def_specifier( Spec_Local_Persist); code_set_global( cast(Code, spec_local_persist ));; - spec_mutable = def_specifier( Spec_Mutable); code_set_global( cast(Code, spec_mutable ));; - spec_neverinline = def_specifier( Spec_NeverInline); code_set_global( cast(Code, spec_neverinline ));; - spec_noexcept = def_specifier( Spec_NoExceptions); code_set_global( cast(Code, spec_noexcept ));; - spec_override = def_specifier( Spec_Override); code_set_global( cast(Code, spec_override ));; - spec_ptr = def_specifier( Spec_Ptr); code_set_global( cast(Code, spec_ptr ));; + spec_consteval = def_specifier( Spec_Consteval); code_set_global( cast(Code, spec_consteval )); + spec_constexpr = def_specifier( Spec_Constexpr); code_set_global( cast(Code, spec_constexpr )); + spec_constinit = def_specifier( Spec_Constinit); code_set_global( cast(Code, spec_constinit )); + spec_extern_linkage = def_specifier( Spec_External_Linkage); code_set_global( cast(Code, spec_extern_linkage )); + spec_final = def_specifier( Spec_Final); code_set_global( cast(Code, spec_final )); + spec_FORCEINLINE = def_specifier( Spec_ForceInline); code_set_global( cast(Code, spec_FORCEINLINE )); + spec_global = def_specifier( Spec_Global); code_set_global( cast(Code, spec_global )); + spec_inline = def_specifier( Spec_Inline); code_set_global( cast(Code, spec_inline )); + spec_internal_linkage = def_specifier( Spec_Internal_Linkage); code_set_global( cast(Code, spec_internal_linkage )); + spec_local_persist = def_specifier( Spec_Local_Persist); code_set_global( cast(Code, spec_local_persist )); + spec_mutable = def_specifier( Spec_Mutable); code_set_global( cast(Code, spec_mutable )); + spec_neverinline = def_specifier( Spec_NeverInline); code_set_global( cast(Code, spec_neverinline )); + spec_noexcept = def_specifier( Spec_NoExceptions); code_set_global( cast(Code, spec_noexcept )); + spec_override = def_specifier( Spec_Override); code_set_global( cast(Code, spec_override )); + spec_ptr = def_specifier( Spec_Ptr); code_set_global( cast(Code, spec_ptr )); spec_pure = def_specifier( Spec_Pure); code_set_global( cast(Code, spec_pure )); - spec_ref = def_specifier( Spec_Ref); code_set_global( cast(Code, spec_ref ));; - spec_register = def_specifier( Spec_Register); code_set_global( cast(Code, spec_register ));; - spec_rvalue = def_specifier( Spec_RValue); code_set_global( cast(Code, spec_rvalue ));; - spec_static_member = def_specifier( Spec_Static); code_set_global( cast(Code, spec_static_member ));; - spec_thread_local = def_specifier( Spec_Thread_Local); code_set_global( cast(Code, spec_thread_local ));; - spec_virtual = def_specifier( Spec_Virtual); code_set_global( cast(Code, spec_virtual ));; + spec_ref = def_specifier( Spec_Ref); code_set_global( cast(Code, spec_ref )); + spec_register = def_specifier( Spec_Register); code_set_global( cast(Code, spec_register )); + spec_rvalue = def_specifier( Spec_RValue); code_set_global( cast(Code, spec_rvalue )); + spec_static_member = def_specifier( Spec_Static); code_set_global( cast(Code, spec_static_member )); + spec_thread_local = def_specifier( Spec_Thread_Local); code_set_global( cast(Code, spec_thread_local )); + spec_virtual = def_specifier( Spec_Virtual); code_set_global( cast(Code, spec_virtual )); spec_volatile = def_specifier( Spec_Volatile); code_set_global( cast(Code, spec_volatile )); 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_macro(enum_underlying_macro); } void init(Context* ctx) @@ -3241,8 +3297,8 @@ void init(Context* ctx) ctx->CodePool_NumBlocks = kilobytes(16); } - if (ctx->InitSize_LexArena == 0 ) { - ctx->InitSize_LexArena = megabytes(4); + if (ctx->InitSize_LexerTokens == 0 ) { + ctx->InitSize_LexerTokens = kilobytes(64); } if (ctx->SizePer_StringArena == 0) { ctx->SizePer_StringArena = megabytes(1); @@ -3272,9 +3328,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 ) @@ -3286,9 +3339,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->Macros = hashtable_init(Macro, ctx->Allocator_DyanmicContainers); + if (ctx->Macros.Hashes == nullptr || ctx->Macros.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(); @@ -3325,9 +3381,7 @@ void deinit(Context* ctx) array_free( ctx->CodePools); array_free( ctx->StringArenas); - arena_free(& ctx->LexArena); - - array_free(ctx->PreprocessorDefines); + hashtable_destroy(ctx->Macros); left = array_num( ctx->Fallback_AllocatorBuckets); if (left) @@ -3372,6 +3426,7 @@ void reset(Context* ctx) while ( left--, left ); hashtable_clear(ctx->StrCache); + hashtable_clear(ctx->Macros); define_constants(); } @@ -3434,12 +3489,50 @@ Code make_code() return result; } -void set_preprocess_define( Str id, b32 is_functional ) { - StrBuilder builder = strbuilder_make_str( _ctx->Allocator_Temp, id ); - if (is_functional) { - strbuilder_append_char( & builder, '(' ); +Macro* lookup_macro( Str name ) { + u32 key = crc32( name.Ptr, name.Len ); + return hashtable_get( _ctx->Macros, key ); +} + +void register_macro( Macro macro ) { + GEN_ASSERT_NOT_NULL(macro.Name.Ptr); + GEN_ASSERT(macro.Name.Len > 0); + u32 key = crc32( macro.Name.Ptr, macro.Name.Len ); + hashtable_set( _ctx->Macros, key, macro ); +} + +void register_macros( s32 num, ... ) +{ + GEN_ASSERT(num > 0); + va_list va; + va_start(va, num); + do + { + Macro macro = va_arg(va, Macro); + GEN_ASSERT_NOT_NULL(macro.Name.Ptr); + GEN_ASSERT(macro.Name.Len > 0); + + u32 key = crc32( macro.Name.Ptr, macro.Name.Len ); + hashtable_set( _ctx->Macros, key, macro ); } - array_append( _ctx->PreprocessorDefines, cache_str( strbuilder_to_str(builder)) ); + while (num--, num > 0); + va_end(va); +} + +void register_macros( s32 num, Macro* macros ) +{ + GEN_ASSERT(num > 0); + do + { + Macro macro = * macros; + GEN_ASSERT_NOT_NULL(macro.Name.Ptr); + GEN_ASSERT(macro.Name.Len > 0); + + u32 key = crc32( macro.Name.Ptr, macro.Name.Len ); + hashtable_set( _ctx->Macros, key, macro ); + ++ macros; + } + while (num--, num > 0); } #pragma region Upfront @@ -3955,7 +4048,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(); @@ -3968,9 +4060,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 ) @@ -3991,44 +4086,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->Body = untyped_str( txt("\n") ); else - result->Content = cache_str( strbuilder_to_str(strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S\n", content)) ); + result->Body = untyped_str( strbuilder_to_str(strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S\n", p.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 macro_entry = { result->Name, type, p.flags }; + register_macro(macro_entry); } return result; } @@ -4803,7 +4886,7 @@ CodeBody def_class_body( s32 num, ... ) } switch (entry->Type) { - GEN_AST_BODY_CLASS_UNALLOWED_TYPES: + GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_class_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -4835,7 +4918,7 @@ CodeBody def_class_body( s32 num, Code* codes ) } switch (entry->Type) { - GEN_AST_BODY_CLASS_UNALLOWED_TYPES: + GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_class_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -4849,6 +4932,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 ); @@ -4925,7 +5069,7 @@ CodeBody def_export_body( s32 num, ... ) } switch (entry->Type) { - GEN_AST_BODY_EXPORT_UNALLOWED_TYPES: + GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_export_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -4957,7 +5101,7 @@ CodeBody def_export_body( s32 num, Code* codes ) } switch (entry->Type) { - GEN_AST_BODY_EXPORT_UNALLOWED_TYPES: + GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_export_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -4991,7 +5135,7 @@ CodeBody def_extern_link_body( s32 num, ... ) } switch (entry->Type) { - GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES: + GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_extern_linkage_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5024,7 +5168,7 @@ CodeBody def_extern_link_body( s32 num, Code* codes ) } switch (entry->Type) { - GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES: + GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_extern_linkage_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5058,7 +5202,7 @@ CodeBody def_function_body( s32 num, ... ) } switch (entry->Type) { - GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES: + GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES: log_failure("gen::" stringize(def_function_body) ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5090,7 +5234,7 @@ CodeBody def_function_body( s32 num, Code* codes ) } switch (entry->Type) { - GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES: + GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_function_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5129,7 +5273,7 @@ CodeBody def_global_body( s32 num, ... ) body_append_body( result, cast(CodeBody, entry) ); continue; - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES: + GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_global_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5165,7 +5309,7 @@ CodeBody def_global_body( s32 num, Code* codes ) body_append_body(result, cast(CodeBody, entry) ); continue; - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES: + GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_global_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5200,7 +5344,7 @@ CodeBody def_namespace_body( s32 num, ... ) } switch (entry->Type) { - GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES: + GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_namespace_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5232,7 +5376,7 @@ CodeBody def_namespace_body( s32 num, Code* codes ) } switch (entry->Type) { - GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES: + GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_namespace_body" ": Entry type is not allowed: %s", code_debug_str(entry) ); return InvalidCode; @@ -5377,7 +5521,7 @@ CodeBody def_struct_body( s32 num, ... ) } switch (entry->Type) { - GEN_AST_BODY_STRUCT_UNALLOWED_TYPES: + GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_struct_body" ": Entry type is not allowed: %s", code_debug_str(entry)); return InvalidCode; @@ -5409,7 +5553,7 @@ CodeBody def_struct_body( s32 num, Code* codes ) } switch (entry->Type) { - GEN_AST_BODY_STRUCT_UNALLOWED_TYPES: + GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES: log_failure("gen::" "def_struct_body" ": Entry type is not allowed: %s", code_debug_str(entry) ); return InvalidCode; @@ -5596,6 +5740,158 @@ 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(); + + while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) { + move_forward(); + name.Text.Len++; + } + + Specifier spec = str_to_specifier( name.Text ); + TokType attrib = str_to_toktype( name.Text ); + b32 not_specifier = spec == Spec_Invalid; + b32 not_attribute = attrib <= Tok___Attributes_Start; + + Macro macro = { name.Text, MT_Expression, (MacroFlags)0 }; + Macro* registered_macro = lookup_macro(name.Text); + + if ( registered_macro == nullptr && not_specifier && not_attribute ) { + log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a expression macro\n" + , name.Text + ); + // GEN_DEBUG_TRAP(); + } + 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\n" + , name.Text + ); + // GEN_DEBUG_TRAP(); + } + 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(); + + Token last_parameter; + // We need to tokenize the define's arguments now: + while( ctx->left && * ctx->scanner != ')') + { + skip_whitespace(); + + Str possible_varadic = { ctx->scanner, 3 }; + if ( ctx->left > 3 && str_are_equal( txt("..."), possible_varadic ) ) { + Token parameter = { { ctx->scanner, 3 }, Tok_Preprocess_Define_Param, ctx->line, ctx->column, TF_Preprocess }; + move_forward(); + move_forward(); + move_forward(); + + array_append(_ctx->Lexer_Tokens, parameter); + skip_whitespace(); + last_parameter = parameter; + + while ( (* ctx->scanner) == '\\' ) { + move_forward(); + skip_whitespace(); + } + if (* ctx->scanner != ')' ) + { + log_failure("lex_preprocessor_define(%d, %d): Expected a ')' after '...' (varaidc macro param) %S\n" + , ctx->line + , ctx->column + , name.Text + ); + return Lex_ReturnNull; + } + break; + } + else if ( (* ctx->scanner) == '\\' ) { + move_forward(); + skip_whitespace(); + continue; + } + else 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(); + last_parameter = parameter; + } + 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; + } + + if (* ctx->scanner == ')' ) + break; + + // 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 + , last_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 + , last_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(); + } + else if ( registered_macro && macro_is_functional( * registered_macro) ) { + if (registered_macro && ! macro_is_functional(* registered_macro)) { + log_fmt("Warning: %S registered macro is flagged as functional yet the definition detects no opening parenthesis '(' for arguments\n" + , name.Text + ); + GEN_DEBUG_TRAP(); + } + } + + if ( registered_macro == nullptr ) { + register_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 ) { @@ -5699,28 +5995,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(); - - 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 ( ) - 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 }; @@ -5770,7 +6047,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 ) @@ -5806,6 +6083,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; } } @@ -5833,30 +6111,24 @@ s32 lex_preprocessor_directive( LexContext* ctx ) FORCEINLINE void lex_found_token( LexContext* ctx ) { - if ( ctx->token.Type != Tok_Invalid ) - { + if ( ctx->token.Type != Tok_Invalid ) { array_append( _ctx->Lexer_Tokens, ctx->token ); return; } TokType type = str_to_toktype( tok_to_str(ctx->token) ); - if (type <= Tok_Access_Public && type >= Tok_Access_Private ) - { + if (type <= Tok_Access_Public && type >= Tok_Access_Private ) { ctx->token.Flags |= TF_AccessSpecifier; } - - if ( type > Tok___Attributes_Start ) - { + if ( type > Tok___Attributes_Start ) { ctx->token.Flags |= TF_Attribute; } - if ( type == Tok_Decl_Extern_Linkage ) { skip_whitespace(); - if ( (* ctx->scanner) != '"' ) - { + if ( (* ctx->scanner) != '"' ) { type = Tok_Spec_Extern; ctx->token.Flags |= TF_Specifier; } @@ -5865,7 +6137,6 @@ void lex_found_token( LexContext* ctx ) array_append( _ctx->Lexer_Tokens, ctx->token ); return; } - if ( ( type <= Tok_Star && type >= Tok_Spec_Alignas) || type == Tok_Ampersand || type == Tok_Ampersand_DBL ) @@ -5875,8 +6146,6 @@ void lex_found_token( LexContext* ctx ) array_append( _ctx->Lexer_Tokens, ctx->token ); return; } - - if ( type != Tok_Invalid ) { ctx->token.Type = type; @@ -5884,38 +6153,40 @@ void lex_found_token( LexContext* ctx ) return; } - 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 ); - - Str* define = hashtable_get(ctx->defines, key ); - if ( define ) + Macro* macro = lookup_macro( ctx->token.Text ); + b32 has_args = ctx->left && (* ctx->scanner) == '('; + b32 resolved_to_macro = false; + if (macro) { + ctx->token.Type = macrotype_to_toktype(macro->Type); + b32 is_functional = macro_is_functional(* macro); + resolved_to_macro = has_args ? is_functional : ! is_functional; + } + if ( resolved_to_macro ) { - ctx->token.Type = Tok_Preprocess_Macro; - + // TODO(Ed): When we introduce a macro AST (and expression support), we'll properly lex this section. // Want to ignore any arguments the define may have as they can be execution expressions. - if ( ctx->left && (* ctx->scanner) == '(' ) + if ( has_args ) { - move_forward(); - ctx->token.Text.Len++; + ctx->token.Flags |= TF_Macro_Functional; - s32 level = 0; - while ( ctx->left && ((* ctx->scanner) != ')' || level > 0) ) - { - if ( (* ctx->scanner) == '(' ) - level++; + // move_forward(); + // ctx->token.Text.Len++; - else if ( (* ctx->scanner) == ')' && level > 0 ) - level--; + // s32 level = 0; + // while ( ctx->left && ((* ctx->scanner) != ')' || level > 0) ) + // { + // if ( (* ctx->scanner) == '(' ) + // level++; - move_forward(); - ctx->token.Text.Len++; - } + // else if ( (* ctx->scanner) == ')' && level > 0 ) + // level--; - move_forward(); - ctx->token.Text.Len++; + // move_forward(); + // ctx->token.Text.Len++; + // } + + // move_forward(); + // ctx->token.Text.Len++; } //if ( (* ctx->scanner) == '\r' && ctx->scanner[1] == '\n' ) @@ -5937,6 +6208,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 tokens, Str content ) TokArray lex( Str content ) @@ -5945,7 +6217,6 @@ TokArray lex( Str content ) c.content = content; c.left = content.Len; c.scanner = content.Ptr; - c.defines = _ctx->Lexer_defines; char const* word = c.scanner; s32 word_length = 0; @@ -5961,26 +6232,10 @@ TokArray lex( Str content ) return null_array; } - 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 @@ -6422,7 +6677,7 @@ TokArray lex( Str content ) goto FoundToken; } - // Dash is unfortunatlly a bit more complicated... + // Dash is unfortunately a bit more complicated... case '-': { Str text = { c.scanner, 1 }; @@ -6559,8 +6814,7 @@ TokArray lex( Str content ) c.token.Text = text; move_forward(); - while ( c.left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) - { + while ( c.left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) { move_forward(); c.token.Text.Len++; } @@ -6586,8 +6840,7 @@ TokArray lex( Str content ) move_forward(); c.token.Text.Len++; - while ( c.left && char_is_hex_digit((* ctx->scanner)) ) - { + while ( c.left && char_is_hex_digit((* ctx->scanner)) ) { move_forward(); c.token.Text.Len++; } @@ -6595,8 +6848,7 @@ TokArray lex( Str content ) goto FoundToken; } - while ( c.left && char_is_digit((* ctx->scanner)) ) - { + while ( c.left && char_is_digit((* ctx->scanner)) ) { move_forward(); c.token.Text.Len++; } @@ -6606,8 +6858,7 @@ TokArray lex( Str content ) move_forward(); c.token.Text.Len++; - while ( c.left && char_is_digit((* ctx->scanner)) ) - { + while ( c.left && char_is_digit((* ctx->scanner)) ) { move_forward(); c.token.Text.Len++; } @@ -6625,8 +6876,7 @@ TokArray lex( Str content ) c.token.Text.Len++; // Handle 'll'/'LL' as a special case when we just processed an 'l'/'L' - if (c.left && (prev == 'l' || prev == 'L') && ((* ctx->scanner) == 'l' || (* ctx->scanner) == 'L')) - { + if (c.left && (prev == 'l' || prev == 'L') && ((* ctx->scanner) == 'l' || (* ctx->scanner) == 'L')) { move_forward(); c.token.Text.Len++; } @@ -6652,8 +6902,7 @@ TokArray lex( Str content ) log_failure( "Failed to lex token '%c' (%d, %d)\n%s", (* ctx->scanner), c.line, c.column, context_str ); // Skip to next whitespace since we can't know if anything else is valid until then. - while ( c.left && ! char_is_space( (* ctx->scanner) ) ) - { + while ( c.left && ! char_is_space( (* ctx->scanner) ) ) { move_forward(); } } @@ -6662,17 +6911,15 @@ TokArray lex( Str content ) { lex_found_token( ctx ); TokType last_type = array_back(_ctx->Lexer_Tokens)->Type; - if ( last_type == Tok_Preprocess_Macro ) + if ( last_type == Tok_Preprocess_Macro_Stmt || last_type == Tok_Preprocess_Macro_Expr ) { Token thanks_c = { { c.scanner, 0 }, Tok_Invalid, c.line, c.column, TF_Null }; c.token = thanks_c; - if ( (* ctx->scanner) == '\r') - { + if ( (* ctx->scanner) == '\r') { move_forward(); c.token.Text.Len = 1; } - - if ( (* ctx->scanner) == '\n' ) + if ( (* ctx->scanner) == '\n' ) { c.token.Type = Tok_NewLine; c.token.Text.Len++; @@ -6685,23 +6932,127 @@ TokArray lex( Str content ) } } - if ( array_num(_ctx->Lexer_Tokens) == 0 ) - { + if ( array_num(_ctx->Lexer_Tokens) == 0 ) { log_failure( "Failed to lex any tokens" ); - { - TokArray tok_array = {}; - return tok_array; - } + TokArray tok_array = {}; + return tok_array; } - hashtable_clear(_ctx->Lexer_defines); - // defines_map_arena.free(); TokArray result = { _ctx->Lexer_Tokens, 0 }; return result; } + #undef move_forward #undef skip_whitespace #undef end_line +// These macros are used in the swtich cases within parser.cpp + +#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES \ +case Tok_Spec_Consteval: \ +case Tok_Spec_Constexpr: \ +case Tok_Spec_Constinit: \ +case Tok_Spec_Explicit: \ +case Tok_Spec_ForceInline: \ +case Tok_Spec_ForceInline_Debuggable: \ +case Tok_Spec_Inline: \ +case Tok_Spec_Mutable: \ +case Tok_Spec_NeverInline: \ +case Tok_Spec_Static: \ +case Tok_Spec_Volatile: \ +case Tok_Spec_Virtual + +#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES \ +case Spec_Constexpr: \ +case Spec_Constinit: \ +case Spec_Explicit: \ +case Spec_Inline: \ +case Spec_ForceInline: \ +case Spec_ForceInline_Debuggable: \ +case Spec_Mutable: \ +case Spec_NeverInline: \ +case Spec_Static: \ +case Spec_Volatile: \ +case Spec_Virtual + +#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \ +case Tok_Spec_Consteval: \ +case Tok_Spec_Constexpr: \ +case Tok_Spec_Constinit: \ +case Tok_Spec_Extern: \ +case Tok_Spec_ForceInline: \ +case Tok_Spec_ForceInline_Debuggable: \ +case Tok_Spec_Global: \ +case Tok_Spec_Inline: \ +case Tok_Spec_Internal_Linkage: \ +case Tok_Spec_NeverInline: \ +case Tok_Spec_Static + +#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES \ +case Spec_Constexpr: \ +case Spec_Constinit: \ +case Spec_ForceInline: \ +case Spec_ForceInline_Debuggable: \ +case Spec_Global: \ +case Spec_External_Linkage: \ +case Spec_Internal_Linkage: \ +case Spec_Inline: \ +case Spec_Mutable: \ +case Spec_NeverInline: \ +case Spec_Static: \ +case Spec_Volatile + +#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES \ +case Spec_Const: \ +case Spec_Inline: \ +case Spec_ForceInline + +#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES \ +case Spec_Const: \ +case Spec_Consteval: \ +case Spec_Constexpr: \ +case Spec_External_Linkage: \ +case Spec_Internal_Linkage: \ +case Spec_ForceInline: \ +case Spec_ForceInline_Debuggable: \ +case Spec_Inline: \ +case Spec_NeverInline: \ +case Spec_Static + +#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES \ +case Spec_Const: \ +case Spec_Constexpr: \ +case Spec_ForceInline: \ +case Spec_Inline: \ +case Spec_NeverInline: \ +case Spec_Static + +#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES \ +case Spec_Const: \ +case Spec_Constexpr: \ +case Spec_Constinit: \ +case Spec_External_Linkage: \ +case Spec_Global: \ +case Spec_Inline: \ +case Spec_ForceInline: \ +case Spec_ForceInline_Debuggable: \ +case Spec_Local_Persist: \ +case Spec_Mutable: \ +case Spec_Static: \ +case Spec_Thread_Local: \ +case Spec_Volatile + +#define GEN_PARSER_VARIABLE_ALLOWED_SPECIFIER_CASES \ +case Spec_Const: \ +case Spec_Constexpr: \ +case Spec_Constinit: \ +case Spec_External_Linkage: \ +case Spec_Global: \ +case Spec_Inline: \ +case Spec_Local_Persist: \ +case Spec_Mutable: \ +case Spec_Static: \ +case Spec_Thread_Local: \ +case Spec_Volatile // TODO(Ed) : Rename ETok_Capture_Start, ETok_Capture_End to Open_Parenthesis adn Close_Parenthesis @@ -6761,12 +7112,10 @@ StrBuilder parser_to_strbuilder(ParseContext ctx) s32 level = 0; do { - if ( curr_scope->Name.Ptr ) - { + if ( curr_scope->Name.Ptr ) { strbuilder_append_fmt(& result, "\t%d: %s, AST Name: %.*s\n", level, curr_scope->ProcName.Ptr, curr_scope->Name.Len, curr_scope->Name.Ptr ); } - else - { + else { strbuilder_append_fmt(& result, "\t%d: %s\n", level, curr_scope->ProcName.Ptr ); } @@ -6779,8 +7128,7 @@ StrBuilder parser_to_strbuilder(ParseContext ctx) bool lex__eat(TokArray* self, TokType type ) { - if ( array_num(self->Arr) - self->Idx <= 0 ) - { + if ( array_num(self->Arr) - self->Idx <= 0 ) { log_failure( "No tokens left.\n%s", parser_to_strbuilder(_ctx->parser) ); return false; } @@ -6793,7 +7141,15 @@ bool lex__eat(TokArray* self, TokType type ) self->Idx ++; } - if ( at_idx.Type != type ) + b32 not_accepted = at_idx.Type != type; + b32 is_identifier = at_idx.Type == Tok_Identifier; + if ( not_accepted ) + { + Macro* macro = lookup_macro(at_idx.Text); + b32 accept_as_identifier = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Identifier ); + not_accepted = type == Tok_Identifier && accept_as_identifier ? false : true; + } + if ( not_accepted ) { Token tok = * lex_current( self, lex_skip_formatting ); log_failure( "Parse Error, TokArray::eat, Expected: ' %s ' not ' %.*s ' (%d, %d)`\n%s" @@ -6818,11 +7174,7 @@ bool lex__eat(TokArray* self, TokType type ) internal void parser_init() { - _ctx->Lexer_Tokens = array_init_reserve(Token, arena_allocator_info( & _ctx->LexArena) - , ( _ctx->InitSize_LexArena - sizeof( ArrayHeader ) ) / sizeof(Token) - ); - - _ctx->Lexer_defines = hashtable_init_reserve(Str, _ctx->Allocator_DyanmicContainers, 256 ); + _ctx->Lexer_Tokens = array_init_reserve(Token, _ctx->Allocator_DyanmicContainers, _ctx->InitSize_LexerTokens ); } internal @@ -6892,7 +7244,6 @@ internal CodeComment parse_comment (); internal Code parse_complicated_definition ( TokType which ); internal CodeBody parse_class_struct_body ( TokType which, Token name ); internal Code parse_class_struct ( TokType which, bool inplace_def ); -internal CodeDefine parse_define (); internal Code parse_expression (); internal Code parse_forward_or_definition ( TokType which, bool is_inplace ); internal CodeFn parse_function_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type, Token name ); @@ -6906,14 +7257,15 @@ internal Code parse_operator_function_or_variable( bool expects_fu internal CodePragma parse_pragma (); internal CodeParams parse_params ( bool use_template_capture ); internal CodePreprocessCond parse_preprocess_cond (); -internal Code parse_simple_preprocess ( TokType which, bool dont_consume_braces ); +internal Code parse_simple_preprocess ( TokType which ); internal Code parse_static_assert (); internal void parse_template_args ( Token* token ); internal CodeVar parse_variable_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename type, Str name ); internal CodeVar parse_variable_declaration_list (); -internal CodeClass parser_parse_class ( bool inplace_def ); +internal CodeClass parser_parse_class ( bool inplace_def ); internal CodeConstructor parser_parse_constructor ( CodeSpecifiers specifiers ); +internal CodeDefine parser_parse_define (); internal CodeDestructor parser_parse_destructor ( CodeSpecifiers specifiers ); internal CodeEnum parser_parse_enum ( bool inplace_def ); internal CodeBody parser_parse_export_body (); @@ -6963,8 +7315,7 @@ StrBuilder parser_strip_formatting( Str raw_text, bool preserve_newlines ) sptr last_cut = 0; char const* scanner = raw_text.Ptr; - if ( scanner[0] == ' ' ) - { + if ( scanner[0] == ' ' ) { move_fwd(); last_cut = 1; } @@ -7174,8 +7525,7 @@ StrBuilder parser_strip_formatting( Str raw_text, bool preserve_newlines ) move_fwd(); } - if ( last_cut < raw_text.Len ) - { + if ( last_cut < raw_text.Len ) { strbuilder_append_c_str_len( & content, cut_ptr, raw_text.Len - last_cut ); } @@ -7381,8 +7731,7 @@ CodeAttributes parse_attributes() internal Code parse_class_struct( TokType which, bool inplace_def ) { - if ( which != Tok_Decl_Class && which != Tok_Decl_Struct ) - { + if ( which != Tok_Decl_Class && which != Tok_Decl_Struct ) { log_failure( "Error, expected class or struct, not %s\n%s", toktype_to_str( which ), parser_to_strbuilder(_ctx->parser) ); return InvalidCode; } @@ -7397,8 +7746,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) Code result = InvalidCode; - if ( check(Tok_Module_Export) ) - { + if ( check(Tok_Module_Export) ) { mflags = ModuleFlag_Export; eat( Tok_Module_Export ); } @@ -7410,8 +7758,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) attributes = parse_attributes(); // - if ( check( Tok_Identifier ) ) - { + if ( check( Tok_Identifier ) ) { name = parse_identifier(nullptr); _ctx->parser.Scope->Name = name.Text; } @@ -7430,8 +7777,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) eat( Tok_Assign_Classifer ); // : - if ( tok_is_access_specifier(currtok) ) - { + if ( tok_is_access_specifier(currtok) ) { access = tok_to_access_specifier(currtok); // : eat( currtok.Type ); @@ -7446,8 +7792,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) eat( Tok_Comma ); // : , - if ( tok_is_access_specifier(currtok) ) - { + if ( tok_is_access_specifier(currtok) ) { eat(currtok.Type); } Token interface_tok = parse_identifier(nullptr); @@ -7457,8 +7802,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) } } - if ( check( Tok_BraceCurly_Open ) ) - { + if ( check( Tok_BraceCurly_Open ) ) { body = parse_class_struct_body( which, name ); } // : , ... { } @@ -7518,93 +7862,91 @@ CodeBody parse_class_struct_body( TokType which, Token name ) if ( currtok_noskip.Type == Tok_Preprocess_Hash ) eat( Tok_Preprocess_Hash ); - b32 macro_found = true; - 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; - - case Tok_Access_Public: + break; + } + case Tok_Access_Public: { member = access_public; eat( Tok_Access_Public ); eat( Tok_Assign_Classifer ); // public: - break; - - case Tok_Access_Protected: + break; + } + case Tok_Access_Protected: { member = access_protected; eat( Tok_Access_Protected ); eat( Tok_Assign_Classifer ); // protected: - break; - - case Tok_Access_Private: + break; + } + case Tok_Access_Private: { member = access_private; eat( Tok_Access_Private ); eat( Tok_Assign_Classifer ); // private: - break; - - case Tok_Decl_Class: + break; + } + case Tok_Decl_Class: { member = parse_complicated_definition( Tok_Decl_Class ); // class - break; - - case Tok_Decl_Enum: + break; + } + case Tok_Decl_Enum: { member = parse_complicated_definition( Tok_Decl_Enum ); // enum - break; - - case Tok_Decl_Friend: + break; + } + case Tok_Decl_Friend: { member = cast(Code, parser_parse_friend()); // friend - break; - - case Tok_Decl_Operator: + break; + } + case Tok_Decl_Operator: { member = cast(Code, parser_parse_operator_cast(NullCode)); // operator () - break; - - case Tok_Decl_Struct: + break; + } + case Tok_Decl_Struct: { member = parse_complicated_definition( Tok_Decl_Struct ); // struct - break; - - case Tok_Decl_Template: + break; + } + case Tok_Decl_Template: { member = cast(Code, parser_parse_template()); // template< ... > - break; - - case Tok_Decl_Typedef: + break; + } + case Tok_Decl_Typedef: { member = cast(Code, parser_parse_typedef()); // typedef - break; - - case Tok_Decl_Union: + break; + } + case Tok_Decl_Union: { member = parse_complicated_definition( Tok_Decl_Union ); // union - break; - - case Tok_Decl_Using: + break; + } + case Tok_Decl_Using: { member = cast(Code, parser_parse_using()); // using - break; - + break; + } case Tok_Operator: + { //if ( currtok.Text[0] != '~' ) //{ // log_failure( "Operator token found in global body but not destructor unary negation\n%s", to_strbuilder(_ctx->parser) ); @@ -7613,17 +7955,19 @@ CodeBody parse_class_struct_body( TokType which, Token name ) member = cast(Code, parser_parse_destructor(NullCode)); // ~() - break; - - case Tok_Preprocess_Define: - member = cast(Code, parse_define()); + break; + } + case Tok_Preprocess_Define: { + member = cast(Code, parser_parse_define()); // #define - break; - + break; + } case Tok_Preprocess_Include: + { member = cast(Code, parse_include()); // #include - break; + break; + } case Tok_Preprocess_If: case Tok_Preprocess_IfDef: @@ -7633,38 +7977,51 @@ CodeBody parse_class_struct_body( TokType which, Token name ) // # break; - case Tok_Preprocess_Else: + case Tok_Preprocess_Else: { member = cast(Code, preprocess_else); eat( Tok_Preprocess_Else ); // #else - break; - - case Tok_Preprocess_EndIf: + break; + } + case Tok_Preprocess_EndIf: { member = cast(Code, preprocess_endif); eat( Tok_Preprocess_EndIf ); // #endif - break; + break; + } - case Tok_Preprocess_Macro: - // - macro_found = true; - goto Preprocess_Macro_Bare_In_Body; - break; + case Tok_Preprocess_Macro_Stmt: { + member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Macro_Stmt )); + break; + } + case Tok_Preprocess_Macro_Expr: { + log_failure("Unbounded macro expression residing in class/struct body\n%S", parser_to_strbuilder(_ctx->parser)); + return InvalidCode; + } - case Tok_Preprocess_Pragma: + // case Tok_Preprocess_Macro: + // // + // macro_found = true; + // goto Preprocess_Macro_Bare_In_Body; + // break; + + case Tok_Preprocess_Pragma: { member = cast(Code, parse_pragma()); // #pragma - break; + break; + } - case Tok_Preprocess_Unsupported: - member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Unsupported, parser_consume_braces )); + case Tok_Preprocess_Unsupported: { + member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Unsupported )); // # - break; + break; + } - case Tok_StaticAssert: + case Tok_StaticAssert: { member = parse_static_assert(); // static_assert - break; + break; + } case Tok_Attribute_Open: case Tok_Decl_GNU_Attribute: @@ -7677,17 +8034,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) // } //! Fallthrough intended - case Tok_Spec_Consteval: - case Tok_Spec_Constexpr: - case Tok_Spec_Constinit: - case Tok_Spec_Explicit: - case Tok_Spec_ForceInline: - case Tok_Spec_Inline: - case Tok_Spec_Mutable: - case Tok_Spec_NeverInline: - case Tok_Spec_Static: - case Tok_Spec_Volatile: - case Tok_Spec_Virtual: + GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES: { Specifier specs_found[16] = { Spec_NumSpecifiers }; s32 NumSpecifiers = 0; @@ -7700,16 +8047,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) switch ( spec ) { - case Spec_Constexpr: - case Spec_Constinit: - case Spec_Explicit: - case Spec_Inline: - case Spec_ForceInline: - case Spec_Mutable: - case Spec_NeverInline: - case Spec_Static: - case Spec_Volatile: - case Spec_Virtual: + GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES: break; case Spec_Consteval: @@ -7721,7 +8059,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) break; default: - log_failure( "Invalid specifier %S for variable\n%S", spec_to_str(spec), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); + log_failure( "Invalid specifier %S for class/struct member\n%S", spec_to_str(spec), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); parser_pop(& _ctx->parser); return InvalidCode; } @@ -7776,6 +8114,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) } //! Fallthrough intentional case Tok_Identifier: + case Tok_Preprocess_Macro_Typename: case Tok_Spec_Const: case Tok_Type_Unsigned: case Tok_Type_Signed: @@ -7796,28 +8135,6 @@ CodeBody parse_class_struct_body( TokType which, Token name ) } } - if (macro_found) - { - Preprocess_Macro_Bare_In_Body: - b32 lone_macro = nexttok.Type == Tok_Statement_End || nexttok_noskip.Type == Tok_NewLine; - if (lone_macro) - { - member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Macro, parser_consume_braces )); - // ; - - if ( member == Code_Invalid ) - { - log_failure( "Failed to parse member\n%s", parser_to_strbuilder(_ctx->parser) ); - parser_pop(& _ctx->parser); - return InvalidCode; - } - continue; - } - - // We have a macro but its most likely behaving as a typename - // operator ... // or @@ -7827,13 +8144,11 @@ CodeBody parse_class_struct_body( TokType which, Token name ) default: Token untyped_tok = currtok; - while ( left && currtok.Type != Tok_BraceCurly_Close ) { untyped_tok.Text.Len = ( (sptr)currtok.Text.Ptr + currtok.Text.Len ) - (sptr)untyped_tok.Text.Ptr; eat( currtok.Type ); } - member = untyped_str( tok_to_str(untyped_tok) ); // Something unknown break; @@ -7845,7 +8160,6 @@ CodeBody parse_class_struct_body( TokType which, Token name ) parser_pop(& _ctx->parser); return InvalidCode; } - body_append(result, member ); } @@ -8027,54 +8341,6 @@ Code parse_complicated_definition( TokType which ) } } -internal inline -CodeDefine parse_define() -{ - push_scope(); - eat( Tok_Preprocess_Define ); - // #define - - CodeDefine - define = (CodeDefine) make_code(); - define->Type = CT_Preprocess_Define; - - if ( ! check( Tok_Identifier ) ) - { - log_failure( "Error, expected identifier after #define\n%s", parser_to_strbuilder(_ctx->parser) ); - parser_pop(& _ctx->parser); - return InvalidCode; - } - - _ctx->parser.Scope->Name = currtok.Text; - define->Name = cache_str( tok_to_str(currtok) ); - eat( Tok_Identifier ); - // #define - - if ( ! check( Tok_Preprocess_Content )) - { - log_failure( "Error, expected content after #define %s\n%s", define->Name, parser_to_strbuilder(_ctx->parser) ); - parser_pop(& _ctx->parser); - return InvalidCode; - } - - if ( currtok.Text.Len == 0 ) - { - define->Content = cache_str( tok_to_str(currtok) ); - eat( Tok_Preprocess_Content ); - // #define - - parser_pop(& _ctx->parser); - return define; - } - - define->Content = cache_str( strbuilder_to_str( parser_strip_formatting( tok_to_str(currtok), parser_strip_formatting_dont_preserve_newlines )) ); - eat( Tok_Preprocess_Content ); - // #define - - parser_pop(& _ctx->parser); - return define; -} - internal inline Code parse_assignment_expression() { @@ -8410,7 +8676,7 @@ CodeBody parse_global_nspace( CodeType which ) break; case Tok_Preprocess_Define: - member = cast(Code, parse_define()); + member = cast(Code, parser_parse_define()); // #define ... break; @@ -8439,12 +8705,14 @@ CodeBody parse_global_nspace( CodeType which ) // #endif break; - case Tok_Preprocess_Macro: { - // - macro_found = true; - goto Preprocess_Macro_Bare_In_Body; + case Tok_Preprocess_Macro_Stmt: { + member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Macro_Stmt )); + break; + } + case Tok_Preprocess_Macro_Expr: { + log_failure("Unbounded macro expression residing in class/struct body\n%S", parser_to_strbuilder(_ctx->parser)); + return InvalidCode; } - break; case Tok_Preprocess_Pragma: { member = cast(Code, parse_pragma()); @@ -8453,7 +8721,7 @@ CodeBody parse_global_nspace( CodeType which ) break; case Tok_Preprocess_Unsupported: { - member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Unsupported, parser_consume_braces )); + member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Unsupported )); // # ... } break; @@ -8490,16 +8758,7 @@ CodeBody parse_global_nspace( CodeType which ) // } //! Fallthrough intentional - case Tok_Spec_Consteval: - case Tok_Spec_Constexpr: - case Tok_Spec_Constinit: - case Tok_Spec_Extern: - case Tok_Spec_ForceInline: - case Tok_Spec_Global: - case Tok_Spec_Inline: - case Tok_Spec_Internal_Linkage: - case Tok_Spec_NeverInline: - case Tok_Spec_Static: + GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES: { Specifier specs_found[16] = { Spec_NumSpecifiers }; s32 NumSpecifiers = 0; @@ -8512,17 +8771,7 @@ CodeBody parse_global_nspace( CodeType which ) switch ( spec ) { - case Spec_Constexpr: - case Spec_Constinit: - case Spec_ForceInline: - case Spec_Global: - case Spec_External_Linkage: - case Spec_Internal_Linkage: - case Spec_Inline: - case Spec_Mutable: - case Spec_NeverInline: - case Spec_Static: - case Spec_Volatile: + GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES: break; case Spec_Consteval: @@ -8557,6 +8806,7 @@ CodeBody parse_global_nspace( CodeType which ) } //! Fallthrough intentional case Tok_Identifier: + case Tok_Preprocess_Macro_Typename: case Tok_Spec_Const: case Tok_Type_Long: case Tok_Type_Short: @@ -8608,34 +8858,11 @@ CodeBody parse_global_nspace( CodeType which ) } } - if (macro_found) - { - Preprocess_Macro_Bare_In_Body: - b32 lone_macro = nexttok.Type == Tok_Statement_End || nexttok_noskip.Type == Tok_NewLine; - if (lone_macro) - { - member = parse_simple_preprocess( Tok_Preprocess_Macro, parser_consume_braces ); - // ; - - if ( member == Code_Invalid ) - { - log_failure( "Failed to parse member\n%s", parser_to_strbuilder(_ctx->parser) ); - parser_pop(& _ctx->parser); - return InvalidCode; - } - goto Member_Resolved_To_Lone_Macro; - } - - // We have a macro but its most likely behaving as a typename - // ... } } - Member_Resolved_To_Lone_Macro: if ( member == Code_Invalid ) { log_failure( "Failed to parse member\nToken: %SB\nContext:\n%SB", tok_to_strbuilder(currtok_noskip), parser_to_strbuilder(_ctx->parser) ); @@ -9255,24 +9482,10 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes Code result = InvalidCode; -#ifndef GEN_PARSER_DISABLE_MACRO_FUNCTION_SIGNATURES - b32 lone_macro = false; - - if ( currtok.Type == Tok_Preprocess_Macro && nexttok.Type == Tok_Statement_End ) - { - // Were dealing with a lone macro after attributes/specifiers, there was a end statement ';' after. - result = parse_simple_preprocess( Tok_Preprocess_Macro, parser_consume_braces ); - parser_pop(& _ctx->parser); - return result; - // - } -#endif - CodeTypename type = parser_parse_type( parser_not_from_template, nullptr ); // - if ( type == InvalidCode ) - { + if ( type == InvalidCode ) { parser_pop(& _ctx->parser); return InvalidCode; } @@ -9318,7 +9531,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes // Example : // idx +1 +2 bool detected_comma = _ctx->parser.Tokens.Arr[ _ctx->parser.Tokens.Idx + 2 ].Type == Tok_Comma; - if ( detected_capture && ! detected_comma ) + if ( detected_capture && ! detected_comma ) { // Dealing with a function result = cast(Code, parse_function_after_name( ModuleFlag_None, attributes, specifiers, type, name )); @@ -9326,13 +9539,11 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes } else { - if ( expects_function ) - { + if ( expects_function ) { log_failure( "Expected function declaration (consteval was used)\n%s", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; } - // Dealing with a variable result = cast(Code, parse_variable_after_name( ModuleFlag_None, attributes, specifiers, type, tok_to_str(name) )); // ... @@ -9354,8 +9565,7 @@ CodePragma parse_pragma() eat( Tok_Preprocess_Pragma ); // #pragma - if ( ! check( Tok_Preprocess_Content )) - { + if ( ! check( Tok_Preprocess_Content )) { log_failure( "Error, expected content after #pragma\n%s", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; @@ -9376,15 +9586,14 @@ CodeParams parse_params( bool use_template_capture ) { push_scope(); - if ( ! use_template_capture ) + if ( ! use_template_capture ) { eat( Tok_Capture_Start ); - // ( - - else - { + // ( + } + else { if ( check( Tok_Operator ) && currtok.Text.Ptr[ 0 ] == '<' ) eat( Tok_Operator ); - // < + // < } if ( ! use_template_capture && check( Tok_Capture_End ) ) @@ -9394,7 +9603,7 @@ CodeParams parse_params( bool use_template_capture ) parser_pop(& _ctx->parser); return NullCode; } - else if ( check( Tok_Operator ) && currtok.Text.Ptr[ 0 ] == '>' ) + else if ( check( Tok_Operator ) && currtok.Text.Ptr[ 0 ] == '>' ) { eat( Tok_Operator ); // > @@ -9422,13 +9631,14 @@ CodeParams parse_params( bool use_template_capture ) #define CheckEndParams() \ (use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Capture_End)) + // TODO(Ed): Use expression macros or this? macro as attribute? // Ex: Unreal has this type of macro: vvvvvvvvv // COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function ); // and: vvvv // AddComponentByClass(UPARAM(meta = (AllowAbstract = "false")) TSubclassOf Class, bool bManualAttachment, ... - if ( check(Tok_Preprocess_Macro)) + if ( check(Tok_Preprocess_Macro_Expr)) { - macro = parse_simple_preprocess(Tok_Preprocess_Macro, parser_consume_braces); + macro = parse_simple_preprocess(Tok_Preprocess_Macro_Expr); // ( } if ( currtok.Type != Tok_Comma ) @@ -9448,27 +9658,28 @@ CodeParams parse_params( bool use_template_capture ) // ( } + // TODO(Ed): Use expression macro for this? // Unreal has yet another type of macro: // template::Value)> // class T ... and then ^this^ UE_REQUIRES shows up // So we need to consume that. - if ( check( Tok_Preprocess_Macro )) + if ( check( Tok_Preprocess_Macro_Expr )) { - post_name_macro = parse_simple_preprocess( Tok_Preprocess_Macro, parser_consume_braces ); + post_name_macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr ); + // ( } // 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 ); - // ( = + // ( = Token value_tok = currtok; - if ( currtok.Type == Tok_Comma ) - { + if ( currtok.Type == Tok_Comma ) { log_failure( "Expected value after assignment operator\n%s.", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; @@ -9536,10 +9747,10 @@ CodeParams parse_params( bool use_template_capture ) // COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function ); // and: vvvv // AddComponentByClass(UPARAM(meta = (AllowAbstract = "false")) TSubclassOf Class, bool bManualAttachment, ... - if ( check(Tok_Preprocess_Macro)) + if ( check(Tok_Preprocess_Macro_Expr)) { - macro = parse_simple_preprocess(Tok_Preprocess_Macro, parser_dont_consume_braces); - // ( + macro = parse_simple_preprocess(Tok_Preprocess_Macro_Expr); + // ( = , } if ( currtok.Type != Tok_Comma ) { @@ -9564,23 +9775,22 @@ CodeParams parse_params( bool use_template_capture ) // template::Value)> // class T ... and then ^this^ UE_REQUIRES shows up // So we need to consume that. - if ( check( Tok_Preprocess_Macro )) - { - post_name_macro = parse_simple_preprocess( Tok_Preprocess_Macro, parser_dont_consume_braces ); + if ( check( Tok_Preprocess_Macro_Expr )) { + post_name_macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr ); + // ( = , } // 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 ); - // ( = , = + // ( = , = Token value_tok = currtok; - if ( currtok.Type == Tok_Comma ) - { + if ( currtok.Type == Tok_Comma ) { log_failure( "Expected value after assignment operator\n%s", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; @@ -9612,9 +9822,9 @@ CodeParams parse_params( bool use_template_capture ) } value = untyped_str( strbuilder_to_str(parser_strip_formatting( tok_to_str(value_tok), parser_strip_formatting_dont_preserve_newlines )) ); - // ( = , = + // ( = , = } - // ( = , = , .. + // ( = , = , .. } CodeParams param = ( CodeParams )make_code(); @@ -9635,21 +9845,20 @@ CodeParams parse_params( bool use_template_capture ) } if ( ! use_template_capture ) + { eat( Tok_Capture_End ); - // ( = , = , .. ) - + // ( = , = , .. ) + } else { - if ( ! check( Tok_Operator ) || currtok.Text.Ptr[ 0 ] != '>' ) - { + if ( ! check( Tok_Operator ) || currtok.Text.Ptr[ 0 ] != '>' ) { log_failure( "Expected '<' after 'template' keyword\n%s", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; } eat( Tok_Operator ); - // < = , = , .. > + // < = , = , .. > } - parser_pop(& _ctx->parser); return result; #undef context @@ -9690,18 +9899,46 @@ CodePreprocessCond parse_preprocess_cond() } internal -Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) +Code parse_simple_preprocess( TokType which ) { // TODO(Ed): We can handle a macro a bit better than this. It's AST can be made more robust.. // Make an AST_Macro, it should have an Name be the macro itself, with the function body being an optional function body node. // If we want it to terminate or have an inline comment we can possbily use its parent typedef for that info... push_scope(); - Token tok = currtok; + Token full_macro = currtok; eat( which ); // - if ( ! dont_consume_braces && peektok.Type == Tok_BraceCurly_Open ) + Macro* macro = lookup_macro( full_macro.Text ); + if ( which != Tok_Preprocess_Unsupported && macro == nullptr ) { + log_failure("Expected the macro %S to be registered\n%S", full_macro, parser_to_strbuilder(_ctx->parser)); + return NullCode; + } + + // TODO(Ed) : Parse this properly later (expression and statement support) + if ( macro && macro_is_functional(* macro) ) + { + eat( Tok_Capture_Start ); + + s32 level = 0; + while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) ) + { + if ( currtok.Type == Tok_Capture_Start ) + level++; + + else if ( currtok.Type == Tok_Capture_End && level > 0 ) + level--; + + eat( currtok.Type ); + } + eat( Tok_Capture_End ); + // ( ) + + full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr; + } + + if ( macro && macro_expects_body(* macro) && peektok.Type == Tok_BraceCurly_Open ) { // Eat the block scope right after the macro. Were assuming the macro defines a function definition's signature eat( Tok_BraceCurly_Open ); @@ -9722,8 +9959,9 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) eat( Tok_BraceCurly_Close ); // { } + // TODO(Ed): Review this? Str prev_proc = _ctx->parser.Scope->Prev->ProcName; - if ( c_str_compare_len( prev_proc.Ptr, "parser_parse_typedef", prev_proc.Len ) != 0 ) + if ( macro->Type == MT_Typename && c_str_compare_len( prev_proc.Ptr, "parser_parse_typedef", prev_proc.Len ) != 0 ) { if ( check( Tok_Statement_End )) { @@ -9737,7 +9975,7 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) } } - tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)tok.Text.Ptr; + full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr; } else { @@ -9750,16 +9988,15 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) // Do nothing goto Leave_Scope_Early; } - else if (str_contains(_ctx->parser.Scope->Prev->ProcName, txt("parser_parse_typedef"))) + else if (macro && macro->Type == MT_Typename && str_contains(_ctx->parser.Scope->Prev->ProcName, txt("parser_parse_typedef"))) { - // TODO(Ed): Reveiw the context for this? if ( peektok.Type == Tok_Statement_End ) { Token stmt_end = currtok; eat( Tok_Statement_End ); // ; - tok.Text.Len += prevtok.Text.Len; + full_macro.Text.Len += prevtok.Text.Len; // TODO(Ed): Reveiw the context for this? (ESPECIALLY THIS) if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) @@ -9767,7 +10004,7 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) eat( Tok_Comment ); // ; - tok.Text.Len += prevtok.Text.Len; + full_macro.Text.Len += prevtok.Text.Len; } } } @@ -9781,19 +10018,14 @@ Code parse_simple_preprocess( TokType which, bool dont_consume_braces ) Token stmt_end = currtok; eat( Tok_Statement_End ); // ; - tok.Text.Len += prevtok.Text.Len; + full_macro.Text.Len += prevtok.Text.Len; } - } - // tok.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)tok.Text; } Leave_Scope_Early: - - char const* content = c_str_fmt_buf( "%.*s ", tok.Text.Len, tok.Text.Ptr ); - - Code result = untyped_str( to_str_from_c_str(content) ); - _ctx->parser.Scope->Name = tok.Text; + Code result = untyped_str( full_macro.Text ); + _ctx->parser.Scope->Name = full_macro.Text; parser_pop(& _ctx->parser); return result; @@ -9888,19 +10120,18 @@ CodeVar parse_variable_after_name( , CodeAttributes attributes , CodeSpecifiers specifiers , CodeTypename type - , Str name + , Str name ) { push_scope(); Code array_expr = parse_array_decl(); - Code expr = { nullptr }; - Code bitfield_expr = { nullptr }; + Code expr = NullCode; + Code bitfield_expr = NullCode; b32 using_constructor_initializer = false; - if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) - { + if ( bitfield_is_set( u32, currtok.Flags, TF_Assign ) ) { // = expr = parse_assignment_expression(); } @@ -9964,15 +10195,13 @@ CodeVar parse_variable_after_name( Token expr_tok = currtok; - if ( currtok.Type == Tok_Statement_End ) - { + if ( currtok.Type == Tok_Statement_End ) { log_failure( "Expected expression after bitfield \n%SB", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; } - while ( left && currtok.Type != Tok_Statement_End ) - { + while ( left && currtok.Type != Tok_Statement_End ) { eat( currtok.Type ); } @@ -9986,8 +10215,7 @@ CodeVar parse_variable_after_name( CodeComment inline_cmt = NullCode; if ( type ) { - if ( currtok.Type == Tok_Comma ) - { + if ( currtok.Type == Tok_Comma ) { // Were dealing with a statement with more than one declaration // This is only handled this way if its the first declaration // Otherwise its looped through in parse_variable_declaration_list @@ -10006,8 +10234,7 @@ CodeVar parse_variable_after_name( // { }, ...; // Check for inline comment : = ; // - if ( left && ( currtok_noskip.Type == Tok_Comment ) && currtok_noskip.Line == stmt_end.Line ) - { + if ( left && ( currtok_noskip.Type == Tok_Comment ) && currtok_noskip.Line == stmt_end.Line ) { inline_cmt = parse_comment(); // : , ...; // = , ...; @@ -10020,35 +10247,20 @@ CodeVar parse_variable_after_name( result->Type = CT_Variable; result->Name = cache_str( name ); result->ModuleFlags = mflags; + result->ValueType = type; + result->BitfieldSize = bitfield_expr; + result->Attributes = attributes; + result->Specs = specifiers; + result->Value = expr; + result->InlineCmt = inline_cmt; - // Type can be null if we're dealing with a declaration from a variable declaration-list - if ( type ) - result->ValueType = type; - - if (array_expr ) + if (array_expr) type->ArrExpr = array_expr; - if ( bitfield_expr ) - result->BitfieldSize = bitfield_expr; - - if ( attributes ) - result->Attributes = attributes; - - if ( specifiers ) - result->Specs = specifiers; - - if ( expr ) - result->Value = expr; - - if ( inline_cmt ) - result->InlineCmt = inline_cmt; - - if ( next_var ) - { + if ( next_var ) { result->NextVar = next_var; result->NextVar->Parent = cast(Code, result); } - result->VarParenthesizedInit = using_constructor_initializer; parser_pop(& _ctx->parser); @@ -10237,6 +10449,93 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers ) return result; } +internal inline +CodeDefine parser_parse_define() +{ + push_scope(); + if ( check(Tok_Preprocess_Hash)) { + // If parse_define is called by the user the hash reach here. + eat(Tok_Preprocess_Hash); + } + + eat( Tok_Preprocess_Define ); + // #define + + CodeDefine + define = (CodeDefine) make_code(); + define->Type = CT_Preprocess_Define; + if ( ! check( Tok_Identifier ) ) { + log_failure( "Error, expected identifier after #define\n%s", parser_to_strbuilder(_ctx->parser) ); + parser_pop(& _ctx->parser); + return InvalidCode; + } + _ctx->parser.Scope->Name = currtok.Text; + define->Name = cache_str( tok_to_str(currtok) ); + eat( Tok_Identifier ); + // #define + + Macro* macro = lookup_macro(define->Name); + if (macro_is_functional(* macro)) { + eat( Tok_Capture_Start ); + // #define ( + + // We provide the define params even if empty to make sure '()' are serialized. + CodeDefineParams + params = (CodeDefineParams) make_code(); + params->Type = CT_Parameters_Define; + + if ( left && currtok.Type != Tok_Capture_End ) { + params->Name = currtok.Text; + params->NumEntries ++; + + eat( Tok_Preprocess_Define_Param ); + // #define ( + } + + while( left && currtok.Type != Tok_Capture_End ) { + eat( Tok_Comma ); + // #define ( , + + CodeDefineParams next_param = (CodeDefineParams) make_code(); + next_param->Type = CT_Parameters_Define; + next_param->Name = currtok.Text; + define_params_append(params, next_param); + + // #define ( , ... + eat( Tok_Preprocess_Define_Param ); + } + + eat( Tok_Capture_End ); + // #define ( ) + + define->Params = params; + } + + if ( ! check( Tok_Preprocess_Content )) + { + log_failure( "Error, expected content after #define %s\n%s", define->Name, parser_to_strbuilder(_ctx->parser) ); + parser_pop(& _ctx->parser); + return InvalidCode; + } + + if ( currtok.Text.Len == 0 ) + { + define->Body = untyped_str( txt("\n") ); + eat( Tok_Preprocess_Content ); + // #define ( ) + + parser_pop(& _ctx->parser); + return define; + } + + define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( tok_to_str(currtok), parser_strip_formatting_dont_preserve_newlines )) ); + eat( Tok_Preprocess_Content ); + // #define ( ) + + parser_pop(& _ctx->parser); + return define; +} + internal CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) { @@ -10294,7 +10593,7 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) specifiers_append(specifiers, Spec_Pure ); } - else if ( left && c_str_compare_len( upcoming.Text.Ptr, "default", sizeof("default") - 1 ) == 0) + else if ( left && c_str_compare_len( upcoming.Text.Ptr, "default", sizeof("default") - 1 ) == 0) { body = cast(CodeBody, parse_assignment_expression()); // ~< @@ -10310,8 +10609,10 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) } if ( ! pure_virtual && check( Tok_BraceCurly_Open ) ) + { body = cast(CodeBody, parse_function_body()); - // ~() { ... } + // ~() { ... } + } else { Token stmt_end = currtok; @@ -10325,8 +10626,7 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) CodeDestructor result = ( CodeDestructor )make_code(); - if ( tok_is_valid(prefix_identifier) ) - { + if ( tok_is_valid(prefix_identifier) ) { prefix_identifier.Text.Len += 1 + identifier.Text.Len; result->Name = cache_str( tok_to_str(prefix_identifier) ); } @@ -10334,8 +10634,7 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) if ( specifiers ) result->Specs = specifiers; - if ( body && body->Type == CT_Function_Body ) - { + if ( body && body->Type == CT_Function_Body ) { result->Body = cast(Code, body); result->Type = CT_Destructor; } @@ -10405,13 +10704,13 @@ CodeEnum parser_parse_enum( bool inplace_def ) } // enum : } - else if ( currtok.Type == Tok_Preprocess_Macro ) + else if ( currtok.Type == Tok_Preprocess_Macro_Expr ) { // We'll support the enum_underlying macro - if ( str_contains( tok_to_str(currtok), enum_underlying_sig) ) + if ( str_contains( tok_to_str(currtok), enum_underlying_macro.Name) ) { use_macro_underlying = true; - underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro, parser_dont_consume_braces ); + underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr ); } } @@ -10452,7 +10751,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) break; case Tok_Preprocess_Define: - member = cast(Code, parse_define()); + member = cast(Code, parser_parse_define()); // #define break; @@ -10474,10 +10773,11 @@ CodeEnum parser_parse_enum( bool inplace_def ) eat( Tok_Preprocess_EndIf ); break; - case Tok_Preprocess_Macro: - member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Macro, parser_consume_braces)); + case Tok_Preprocess_Macro_Stmt: { + member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Macro_Stmt )); // - break; + break; + } case Tok_Preprocess_Pragma: member = cast(Code, parse_pragma()); @@ -10485,11 +10785,12 @@ CodeEnum parser_parse_enum( bool inplace_def ) break; case Tok_Preprocess_Unsupported: - member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Unsupported, parser_consume_braces )); + member = cast(Code, parse_simple_preprocess( Tok_Preprocess_Unsupported )); // # break; default: + { Token entry = currtok; eat( Tok_Identifier); @@ -10500,17 +10801,15 @@ CodeEnum parser_parse_enum( bool inplace_def ) eat( Tok_Operator ); // = - while ( currtok.Type != Tok_Comma && currtok.Type != Tok_BraceCurly_Close ) - { + while ( currtok.Type != Tok_Comma && currtok.Type != Tok_BraceCurly_Close ) { eat( currtok.Type ); } } // = // Unreal UMETA macro support - if ( currtok.Type == Tok_Preprocess_Macro ) - { - eat( Tok_Preprocess_Macro ); + if ( currtok.Type == Tok_Preprocess_Macro_Expr ) { + eat( Tok_Preprocess_Macro_Expr ); // = } @@ -10534,11 +10833,11 @@ CodeEnum parser_parse_enum( bool inplace_def ) entry.Text.Len = ( (sptr)prev.Text.Ptr + prev.Text.Len ) - (sptr)entry.Text.Ptr; member = untyped_str( tok_to_str(entry) ); + } break; } - if ( member == Code_Invalid ) - { + if ( member == Code_Invalid ) { log_failure( "Failed to parse member\n%s", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; @@ -10669,10 +10968,8 @@ CodeFriend parser_parse_friend() switch ( spec ) { - case Spec_Const : - case Spec_Inline : - case Spec_ForceInline : - break; + GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES: + break; default : log_failure( "Invalid specifier %S for friend definition\n%S", spec_to_str( spec ), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); @@ -10689,8 +10986,7 @@ CodeFriend parser_parse_friend() eat( currtok.Type ); } - if ( NumSpecifiers ) - { + if ( NumSpecifiers ) { specifiers = def_specifiers( NumSpecifiers, specs_found ); } // @@ -10698,8 +10994,7 @@ CodeFriend parser_parse_friend() // Type declaration or return type CodeTypename type = parser_parse_type(parser_not_from_template, nullptr); - if ( cast(Code, type) == Code_Invalid ) - { + if ( cast(Code, type) == Code_Invalid ) { parser_pop(& _ctx->parser); return InvalidCode; } @@ -10729,8 +11024,7 @@ CodeFriend parser_parse_friend() } // Operator declaration or definition - if ( currtok.Type == Tok_Decl_Operator ) - { + if ( currtok.Type == Tok_Decl_Operator ) { op = parse_operator_after_ret_type( ModuleFlag_None, NullCode, specifiers, type ); } @@ -10777,8 +11071,7 @@ CodeFn parser_parse_function() CodeSpecifiers specifiers = { nullptr }; ModuleFlag mflags = ModuleFlag_None; - if ( check(Tok_Module_Export) ) - { + if ( check(Tok_Module_Export) ) { mflags = ModuleFlag_Export; eat( Tok_Module_Export ); } @@ -10793,14 +11086,7 @@ CodeFn parser_parse_function() switch ( spec ) { - case Spec_Const: - case Spec_Consteval: - case Spec_Constexpr: - case Spec_External_Linkage: - case Spec_ForceInline: - case Spec_Inline: - case Spec_NeverInline: - case Spec_Static: + GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES: break; default: @@ -10817,15 +11103,13 @@ CodeFn parser_parse_function() eat( currtok.Type ); } - if ( NumSpecifiers ) - { + if ( NumSpecifiers ) { specifiers = def_specifiers( NumSpecifiers, specs_found ); } // CodeTypename ret_type = parser_parse_type(parser_not_from_template, nullptr); - if ( cast(Code, ret_type) == Code_Invalid ) - { + if ( cast(Code, ret_type) == Code_Invalid ) { parser_pop(& _ctx->parser); return InvalidCode; } @@ -10833,8 +11117,7 @@ CodeFn parser_parse_function() Token name = parse_identifier(nullptr); _ctx->parser.Scope->Name = name.Text; - if ( ! tok_is_valid(name) ) - { + if ( ! tok_is_valid(name) ) { parser_pop(& _ctx->parser); return InvalidCode; } @@ -10860,8 +11143,7 @@ CodeNS parser_parse_namespace() // namespace CodeBody body = parse_global_nspace( CT_Namespace_Body ); - if ( cast(Code, body) == Code_Invalid ) - { + if ( cast(Code, body) == Code_Invalid ) { parser_pop(& _ctx->parser); return InvalidCode; } @@ -10890,8 +11172,7 @@ CodeOperator parser_parse_operator() Specifier specs_found[16] = { Spec_NumSpecifiers }; s32 NumSpecifiers = 0; - if ( check(Tok_Module_Export) ) - { + if ( check(Tok_Module_Export) ) { mflags = ModuleFlag_Export; eat( Tok_Module_Export ); } @@ -10906,12 +11187,7 @@ CodeOperator parser_parse_operator() switch ( spec ) { - case Spec_Const: - case Spec_Constexpr: - case Spec_ForceInline: - case Spec_Inline: - case Spec_NeverInline: - case Spec_Static: + GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES: break; default: @@ -10928,8 +11204,7 @@ CodeOperator parser_parse_operator() eat( currtok.Type ); } - if ( NumSpecifiers ) - { + if ( NumSpecifiers ) { specifiers = def_specifiers( NumSpecifiers, specs_found ); } // @@ -11040,13 +11315,11 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers ) if ( tok_is_valid(name) ) result->Name = cache_str( tok_to_str(name) ); - if (body) - { + if (body) { result->Type = CT_Operator_Cast; result->Body = cast(CodeBody, body); } - else - { + else { result->Type = CT_Operator_Cast_Fwd; } @@ -11077,8 +11350,7 @@ CodeTemplate parser_parse_template() ModuleFlag mflags = ModuleFlag_None; - if ( check( Tok_Module_Export ) ) - { + if ( check( Tok_Module_Export ) ) { mflags = ModuleFlag_Export; eat( Tok_Module_Export ); } @@ -11088,8 +11360,7 @@ CodeTemplate parser_parse_template() // template CodeParams params = parse_params( UseTemplateCapture ); - if ( cast(Code, params) == Code_Invalid ) - { + if ( cast(Code, params) == Code_Invalid ) { parser_pop(& _ctx->parser); return InvalidCode; } @@ -11149,19 +11420,8 @@ CodeTemplate parser_parse_template() switch ( spec ) { - case Spec_Const : - case Spec_Constexpr : - case Spec_Constinit : - case Spec_External_Linkage : - case Spec_Global : - case Spec_Inline : - case Spec_ForceInline : - case Spec_Local_Persist : - case Spec_Mutable : - case Spec_Static : - case Spec_Thread_Local : - case Spec_Volatile : - break; + GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES: + break; case Spec_Consteval : expects_function = true; @@ -11182,8 +11442,7 @@ CodeTemplate parser_parse_template() eat( currtok.Type ); } - if ( NumSpecifiers ) - { + if ( NumSpecifiers ) { specifiers = def_specifiers( NumSpecifiers, specs_found ); } // template< > @@ -11196,7 +11455,7 @@ CodeTemplate parser_parse_template() if (is_in_global_nspace) { Code constructor_destructor = parse_global_nspace_constructor_destructor( specifiers ); - if ( constructor_destructor ) + if ( constructor_destructor ) { definition = constructor_destructor; // :: () { ... } @@ -11230,8 +11489,7 @@ CodeTemplate parser_parse_template() break; } - if ( found_operator_cast_outside_class_implmentation ) - { + if ( found_operator_cast_outside_class_implmentation ) { definition = cast(Code, parser_parse_operator_cast( specifiers )); // :: operator () { ... } break; @@ -11290,8 +11548,7 @@ CodeTypename parser_parse_type( bool from_template, bool* typedef_is_function ) { Specifier spec = str_to_specifier( tok_to_str(currtok) ); - if ( spec != Spec_Const ) - { + if ( spec != Spec_Const ) { log_failure( "Error, invalid specifier used in type definition: %S\n%SB", tok_to_str(currtok), parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; @@ -11303,8 +11560,7 @@ CodeTypename parser_parse_type( bool from_template, bool* typedef_is_function ) } // - if ( left == 0 ) - { + if ( left == 0 ) { log_failure( "Error, unexpected end of type definition\n%SB", parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; @@ -11403,16 +11659,17 @@ else if ( currtok.Type == Tok_DeclType ) } } } - else if ( currtok.Type == Tok_Preprocess_Macro ) { + // TODO(Ed): This needs updating + else if ( currtok.Type == Tok_Preprocess_Macro_Typename ) { // Typename is a macro name = currtok; - eat(Tok_Preprocess_Macro); + eat(Tok_Preprocess_Macro_Typename); } // The usual Identifier type signature that may have namespace qualifiers else { - name = parse_identifier(nullptr); + name = parse_identifier(nullptr); _ctx->parser.Scope->Name = name.Text; if ( ! tok_is_valid(name) ) { @@ -11746,25 +12003,37 @@ CodeTypedef parser_parse_typedef() const bool from_typedef = true; + // TODO(Ed): UPDATE MACRO USAGE HERE #if GEN_PARSER_DISABLE_MACRO_TYPEDEF if ( false ) #else - if ( check( Tok_Preprocess_Macro )) + b32 valid_macro = false; + valid_macro |= left && currtok.Type == Tok_Preprocess_Macro_Typename; + valid_macro |= left && currtok.Type == Tok_Preprocess_Macro_Stmt; + // if (currtok.Type == Tok_Preprocess_Macro_Stmt) + // { + // PreprocessMacro* macro = lookup_macro(currtok.Text); + // valid_macro |= macro && macro_expects_body(* macro)); + // } + + Code macro; + if ( valid_macro ) #endif { - type = cast(Code, t_empty); - name = currtok; + type = cast(Code, t_empty); + name = currtok; + Code macro = parse_simple_preprocess(currtok.Type); + name.Text.Len = macro->Content.Len; _ctx->parser.Scope->Name = name.Text; - eat( Tok_Preprocess_Macro ); // typedef if ( currtok.Type == Tok_Identifier ) { - type = untyped_str(name.Text); + type = macro; name = currtok; eat(Tok_Identifier); + // typedef } - // typedef } else { @@ -11958,7 +12227,7 @@ CodeUnion parser_parse_union( bool inplace_def ) Str name = { nullptr, 0 }; if ( check( Tok_Identifier ) ) -{ + { name = tok_to_str(currtok); _ctx->parser.Scope->Name = currtok.Text; eat( Tok_Identifier ); @@ -12011,7 +12280,7 @@ CodeUnion parser_parse_union( bool inplace_def ) break; case Tok_Preprocess_Define: - member = cast(Code, parse_define()); + member = cast(Code, parser_parse_define()); break; case Tok_Preprocess_If: @@ -12031,14 +12300,13 @@ CodeUnion parser_parse_union( bool inplace_def ) eat( Tok_Preprocess_EndIf ); break; - case Tok_Preprocess_Macro: - if ( nexttok.Type == Tok_Identifier ) { - // Its a variable with a macro typename - member = cast(Code, parser_parse_variable()); - break; - } + case Tok_Preprocess_Macro_Typename: + // Its a variable with a macro typename + member = cast(Code, parser_parse_variable()); + break; - member = parse_simple_preprocess( Tok_Preprocess_Macro, parser_consume_braces ); + case Tok_Preprocess_Macro_Stmt: + member = parse_simple_preprocess( Tok_Preprocess_Macro_Stmt ); break; case Tok_Preprocess_Pragma: @@ -12046,7 +12314,7 @@ CodeUnion parser_parse_union( bool inplace_def ) break; case Tok_Preprocess_Unsupported: - member = parse_simple_preprocess( Tok_Preprocess_Unsupported, parser_consume_braces ); + member = parse_simple_preprocess( Tok_Preprocess_Unsupported ); break; default: @@ -12109,7 +12377,7 @@ CodeUsing parser_parse_using() eat( Tok_Decl_Using ); // using - if ( currtok.Type == Tok_Decl_Namespace ) + if ( currtok.Type == Tok_Decl_Namespace ) { is_namespace = true; eat( Tok_Decl_Namespace ); @@ -12123,7 +12391,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(); // using @@ -12144,8 +12412,7 @@ CodeUsing parser_parse_using() // using = ; CodeComment inline_cmt = NullCode; - if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) - { + if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) { inline_cmt = parse_comment(); } // using = ; @@ -12192,8 +12459,7 @@ CodeVar parser_parse_variable() CodeAttributes attributes = { nullptr }; CodeSpecifiers specifiers = { nullptr }; - if ( check(Tok_Module_Export) ) - { + if ( check(Tok_Module_Export) ) { mflags = ModuleFlag_Export; eat( Tok_Module_Export ); } @@ -12207,17 +12473,7 @@ CodeVar parser_parse_variable() Specifier spec = str_to_specifier( tok_to_str(currtok) ); switch ( spec ) { - case Spec_Const: - case Spec_Constexpr: - case Spec_Constinit: - case Spec_External_Linkage: - case Spec_Global: - case Spec_Inline: - case Spec_Local_Persist: - case Spec_Mutable: - case Spec_Static: - case Spec_Thread_Local: - case Spec_Volatile: + GEN_PARSER_VARIABLE_ALLOWED_SPECIFIER_CASES: break; default: @@ -12235,8 +12491,7 @@ CodeVar parser_parse_variable() eat( currtok.Type ); } - if ( NumSpecifiers ) - { + if ( NumSpecifiers ) { specifiers = def_specifiers( NumSpecifiers, specs_found ); } // @@ -12344,6 +12599,21 @@ CodeConstructor parse_constructor( Str def ) return result; } +CodeDefine parse_define( Str def ) +{ + check_parse_args( def ); + + TokArray toks = lex( def ); + if ( toks.Arr == nullptr ) + return InvalidCode; + + _ctx->parser.Tokens = toks; + push_scope(); + CodeDefine result = parser_parse_define(); + parser_pop(& _ctx->parser); + return result; +} + CodeDestructor parse_destructor( Str def ) { check_parse_args( def ); diff --git a/Project/Source/GasaGen/gen.dep.hpp b/Project/Source/GasaGen/gen.dep.hpp index bae8278..b44ca0f 100644 --- a/Project/Source/GasaGen/gen.dep.hpp +++ b/Project/Source/GasaGen/gen.dep.hpp @@ -215,8 +215,8 @@ GEN_NS_BEGIN #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 @@ -567,11 +567,15 @@ GEN_NS_BEGIN #define neverinline __attribute__( ( __noinline__ ) ) #else #define FORCEINLINE + #define neverinline + #endif #else #define FORCEINLINE + #define neverinline + #endif #endif @@ -587,9 +591,11 @@ GEN_NS_BEGIN #define neverinline __attribute__( ( __noinline__ ) ) #else #define neverinline + #endif #else #define neverinline + #endif #endif @@ -624,10 +630,10 @@ GEN_NS_BEGIN #define typeof decltype #elif defined( _MSC_VER ) -#define typeof( x ) __typeof__( x ) +#define typeof __typeof__ #elif defined( __GNUC__ ) || defined( __clang__ ) -#define typeof( x ) __typeof__( x ) +#define typeof __typeof__ #else #error "Compiler not supported" #endif @@ -636,7 +642,9 @@ GEN_NS_BEGIN #ifndef GEN_API_C_BEGIN #if GEN_COMPILER_C #define GEN_API_C_BEGIN + #define GEN_API_C_END + #else #define GEN_API_C_BEGIN \ extern "C" \ @@ -650,6 +658,7 @@ GEN_NS_BEGIN #define enum_underlying( type ) : type #else #define enum_underlying( type ) + #endif #else #define enum_underlying( type ) : type @@ -669,6 +678,7 @@ GEN_NS_BEGIN #define GEN_PARAM_DEFAULT = {} #else #define GEN_PARAM_DEFAULT + #endif #if GEN_COMPILER_CPP @@ -690,7 +700,9 @@ GEN_NS_BEGIN #endif #else #define GEN_OPTIMIZE_MAPPINGS_BEGIN + #define GEN_OPITMIZE_MAPPINGS_END + #endif #pragma endregion Macros @@ -1122,7 +1134,7 @@ FORCEINLINE ssize size_remaining(Arena& arena, ssize alignment) { return // This id is defined by Unreal for asserts #pragma push_macro("check") #undef check -FORCEINLINE void check(Arena& arena) { return arena_check(& arena); }; +FORCEINLINE void check(Arena& arena) { return arena_check(& arena); } #pragma pop_macro("check") #endif @@ -2036,7 +2048,7 @@ usize array_grow_formula(ssize value) { template inline bool array_append_array(Array* array, Array other) { - return array_append_items(array, (Type*)other, num(other)); + return array_append_items(array, (Type*)other, array_num(other)); } template inline @@ -2066,13 +2078,13 @@ bool array_append_items(Array* array, Type* items, usize item_num) GEN_ASSERT(* array != nullptr); GEN_ASSERT(items != nullptr); GEN_ASSERT(item_num > 0); - ArrayHeader* header = array_get_header(array); + ArrayHeader* header = array_get_header(* array); if (header->Num + item_num > header->Capacity) { - if ( ! grow(array, header->Capacity + item_num)) + if ( ! array_grow(array, header->Capacity + item_num)) return false; - header = array_get_header(array); + header = array_get_header(* array); } mem_copy((Type*)array + header->Num, items, item_num * sizeof(Type)); @@ -2725,9 +2737,9 @@ struct Str #ifndef txt # if GEN_COMPILER_CPP -# define txt( text ) Str { ( text ), sizeof( text ) - 1 } +# define txt( text ) GEN_NS Str { ( text ), sizeof( text ) - 1 } # else -# define txt( text ) (Str){ ( text ), sizeof( text ) - 1 } +# define txt( text ) (GEN_NS Str){ ( text ), sizeof( text ) - 1 } # endif #endif diff --git a/Project/Source/GasaGen/gen.hpp b/Project/Source/GasaGen/gen.hpp index 7fdcd66..d1bb693 100644 --- a/Project/Source/GasaGen/gen.hpp +++ b/Project/Source/GasaGen/gen.hpp @@ -249,6 +249,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, @@ -277,7 +278,7 @@ enum CodeType : u32 inline Str codetype_to_str( CodeType type ) { - local_persist Str lookup[61] = { + local_persist Str lookup[] = { { "Invalid", sizeof( "Invalid" ) - 1 }, { "Untyped", sizeof( "Untyped" ) - 1 }, { "NewLine", sizeof( "NewLine" ) - 1 }, @@ -317,6 +318,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 }, @@ -345,7 +347,7 @@ inline Str codetype_to_str( CodeType type ) inline Str codetype_to_keyword_str( CodeType type ) { - local_persist Str lookup[61] = { + local_persist Str lookup[] = { { "__NA__", sizeof( "__NA__" ) - 1 }, { "__NA__", sizeof( "__NA__" ) - 1 }, { "__NA__", sizeof( "__NA__" ) - 1 }, @@ -385,6 +387,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 }, @@ -476,7 +479,7 @@ enum Operator : u32 inline Str operator_to_str( Operator op ) { - local_persist Str lookup[47] = { + local_persist Str lookup[] = { { "INVALID", sizeof( "INVALID" ) - 1 }, { "=", sizeof( "=" ) - 1 }, { "+=", sizeof( "+=" ) - 1 }, @@ -542,6 +545,7 @@ enum Specifier : u32 Spec_Explicit, Spec_External_Linkage, Spec_ForceInline, + Spec_ForceInline_Debuggable, Spec_Global, Spec_Inline, Spec_Internal_Linkage, @@ -567,33 +571,34 @@ enum Specifier : u32 inline Str spec_to_str( Specifier type ) { - local_persist Str lookup[26] = { - { "INVALID", sizeof( "INVALID" ) - 1 }, - { "consteval", sizeof( "consteval" ) - 1 }, - { "constexpr", sizeof( "constexpr" ) - 1 }, - { "constinit", sizeof( "constinit" ) - 1 }, - { "explicit", sizeof( "explicit" ) - 1 }, - { "extern", sizeof( "extern" ) - 1 }, - { "FORCEINLINE", sizeof( "FORCEINLINE" ) - 1 }, - { "global", sizeof( "global" ) - 1 }, - { "inline", sizeof( "inline" ) - 1 }, - { "internal", sizeof( "internal" ) - 1 }, - { "local_persist", sizeof( "local_persist" ) - 1 }, - { "mutable", sizeof( "mutable" ) - 1 }, - { "neverinline", sizeof( "neverinline" ) - 1 }, - { "*", sizeof( "*" ) - 1 }, - { "&", sizeof( "&" ) - 1 }, - { "register", sizeof( "register" ) - 1 }, - { "&&", sizeof( "&&" ) - 1 }, - { "static", sizeof( "static" ) - 1 }, - { "thread_local", sizeof( "thread_local" ) - 1 }, - { "virtual", sizeof( "virtual" ) - 1 }, - { "const", sizeof( "const" ) - 1 }, - { "final", sizeof( "final" ) - 1 }, - { "noexcept", sizeof( "noexcept" ) - 1 }, - { "override", sizeof( "override" ) - 1 }, - { "= 0", sizeof( "= 0" ) - 1 }, - { "volatile", sizeof( "volatile" ) - 1 }, + local_persist Str lookup[] = { + { "INVALID", sizeof( "INVALID" ) - 1 }, + { "consteval", sizeof( "consteval" ) - 1 }, + { "constexpr", sizeof( "constexpr" ) - 1 }, + { "constinit", sizeof( "constinit" ) - 1 }, + { "explicit", sizeof( "explicit" ) - 1 }, + { "extern", sizeof( "extern" ) - 1 }, + { "FORCEINLINE", sizeof( "FORCEINLINE" ) - 1 }, + { "FORCEINLINE_DEBUGGABLE", sizeof( "FORCEINLINE_DEBUGGABLE" ) - 1 }, + { "global", sizeof( "global" ) - 1 }, + { "inline", sizeof( "inline" ) - 1 }, + { "internal", sizeof( "internal" ) - 1 }, + { "local_persist", sizeof( "local_persist" ) - 1 }, + { "mutable", sizeof( "mutable" ) - 1 }, + { "neverinline", sizeof( "neverinline" ) - 1 }, + { "*", sizeof( "*" ) - 1 }, + { "&", sizeof( "&" ) - 1 }, + { "register", sizeof( "register" ) - 1 }, + { "&&", sizeof( "&&" ) - 1 }, + { "static", sizeof( "static" ) - 1 }, + { "thread_local", sizeof( "thread_local" ) - 1 }, + { "virtual", sizeof( "virtual" ) - 1 }, + { "const", sizeof( "const" ) - 1 }, + { "final", sizeof( "final" ) - 1 }, + { "noexcept", sizeof( "noexcept" ) - 1 }, + { "override", sizeof( "override" ) - 1 }, + { "= 0", sizeof( "= 0" ) - 1 }, + { "volatile", sizeof( "volatile" ) - 1 }, }; return lookup[type]; } @@ -696,7 +701,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, @@ -707,6 +714,7 @@ enum TokType : u32 Tok_Spec_Extern, Tok_Spec_Final, Tok_Spec_ForceInline, + Tok_Spec_ForceInline_Debuggable, Tok_Spec_Global, Tok_Spec_Inline, Tok_Spec_Internal_Linkage, @@ -751,108 +759,111 @@ enum TokType : u32 inline Str toktype_to_str( TokType type ) { local_persist Str lookup[] = { - { "__invalid__", sizeof( "__invalid__" ) - 1 }, - { "private", sizeof( "private" ) - 1 }, - { "protected", sizeof( "protected" ) - 1 }, - { "public", sizeof( "public" ) - 1 }, - { ".", sizeof( "." ) - 1 }, - { "::", sizeof( "::" ) - 1 }, - { "&", sizeof( "&" ) - 1 }, - { "&&", sizeof( "&&" ) - 1 }, - { ":", sizeof( ":" ) - 1 }, - { "[[", sizeof( "[[" ) - 1 }, - { "]]", sizeof( "]]" ) - 1 }, - { "{", sizeof( "{" ) - 1 }, - { "}", sizeof( "}" ) - 1 }, - { "[", sizeof( "[" ) - 1 }, - { "]", sizeof( "]" ) - 1 }, - { "(", sizeof( "(" ) - 1 }, - { ")", sizeof( ")" ) - 1 }, - { "__comment__", sizeof( "__comment__" ) - 1 }, - { "__comment_end__", sizeof( "__comment_end__" ) - 1 }, - { "__comment_start__", sizeof( "__comment_start__" ) - 1 }, - { "__character__", sizeof( "__character__" ) - 1 }, - { ",", sizeof( "," ) - 1 }, - { "class", sizeof( "class" ) - 1 }, - { "__attribute__", sizeof( "__attribute__" ) - 1 }, - { "__declspec", sizeof( "__declspec" ) - 1 }, - { "enum", sizeof( "enum" ) - 1 }, - { "extern", sizeof( "extern" ) - 1 }, - { "friend", sizeof( "friend" ) - 1 }, - { "module", sizeof( "module" ) - 1 }, - { "namespace", sizeof( "namespace" ) - 1 }, - { "operator", sizeof( "operator" ) - 1 }, - { "struct", sizeof( "struct" ) - 1 }, - { "template", sizeof( "template" ) - 1 }, - { "typedef", sizeof( "typedef" ) - 1 }, - { "using", sizeof( "using" ) - 1 }, - { "union", sizeof( "union" ) - 1 }, - { "__identifier__", sizeof( "__identifier__" ) - 1 }, - { "import", sizeof( "import" ) - 1 }, - { "export", sizeof( "export" ) - 1 }, - { "__new_line__", sizeof( "__new_line__" ) - 1 }, - { "__number__", sizeof( "__number__" ) - 1 }, - { "__operator__", sizeof( "__operator__" ) - 1 }, - { "#", sizeof( "#" ) - 1 }, - { "define", sizeof( "define" ) - 1 }, - { "if", sizeof( "if" ) - 1 }, - { "ifdef", sizeof( "ifdef" ) - 1 }, - { "ifndef", sizeof( "ifndef" ) - 1 }, - { "elif", sizeof( "elif" ) - 1 }, - { "else", sizeof( "else" ) - 1 }, - { "endif", sizeof( "endif" ) - 1 }, - { "include", sizeof( "include" ) - 1 }, - { "pragma", sizeof( "pragma" ) - 1 }, - { "__macro_content__", sizeof( "__macro_content__" ) - 1 }, - { "__macro__", sizeof( "__macro__" ) - 1 }, - { "__unsupported__", sizeof( "__unsupported__" ) - 1 }, - { "alignas", sizeof( "alignas" ) - 1 }, - { "const", sizeof( "const" ) - 1 }, - { "consteval", sizeof( "consteval" ) - 1 }, - { "constexpr", sizeof( "constexpr" ) - 1 }, - { "constinit", sizeof( "constinit" ) - 1 }, - { "explicit", sizeof( "explicit" ) - 1 }, - { "extern", sizeof( "extern" ) - 1 }, - { "final", sizeof( "final" ) - 1 }, - { "FORCEINLINE", sizeof( "FORCEINLINE" ) - 1 }, - { "global", sizeof( "global" ) - 1 }, - { "inline", sizeof( "inline" ) - 1 }, - { "internal", sizeof( "internal" ) - 1 }, - { "local_persist", sizeof( "local_persist" ) - 1 }, - { "mutable", sizeof( "mutable" ) - 1 }, - { "neverinline", sizeof( "neverinline" ) - 1 }, - { "override", sizeof( "override" ) - 1 }, - { "static", sizeof( "static" ) - 1 }, - { "thread_local", sizeof( "thread_local" ) - 1 }, - { "volatile", sizeof( "volatile" ) - 1 }, - { "virtual", sizeof( "virtual" ) - 1 }, - { "*", sizeof( "*" ) - 1 }, - { ";", sizeof( ";" ) - 1 }, - { "static_assert", sizeof( "static_assert" ) - 1 }, - { "__string__", sizeof( "__string__" ) - 1 }, - { "typename", sizeof( "typename" ) - 1 }, - { "unsigned", sizeof( "unsigned" ) - 1 }, - { "signed", sizeof( "signed" ) - 1 }, - { "short", sizeof( "short" ) - 1 }, - { "long", sizeof( "long" ) - 1 }, - { "bool", sizeof( "bool" ) - 1 }, - { "char", sizeof( "char" ) - 1 }, - { "int", sizeof( "int" ) - 1 }, - { "double", sizeof( "double" ) - 1 }, - { "__int8", sizeof( "__int8" ) - 1 }, - { "__int16", sizeof( "__int16" ) - 1 }, - { "__int32", sizeof( "__int32" ) - 1 }, - { "__int64", sizeof( "__int64" ) - 1 }, - { "_W64", sizeof( "_W64" ) - 1 }, - { "...", sizeof( "..." ) - 1 }, - { "__attrib_start__", sizeof( "__attrib_start__" ) - 1 }, - { "GEN_API_Export_Code", sizeof( "GEN_API_Export_Code" ) - 1 }, - { "GEN_API_Import_Code", sizeof( "GEN_API_Import_Code" ) - 1 }, - { "COREUOBJECT_API", sizeof( "COREUOBJECT_API" ) - 1 }, - { "ENGINE_API", sizeof( "ENGINE_API" ) - 1 }, - { "GAMEPLAYABILITIES_API", sizeof( "GAMEPLAYABILITIES_API" ) - 1 }, - { "UMG_API", sizeof( "UMG_API" ) - 1 }, - { "UE_DEPRECATED", sizeof( "UE_DEPRECATED" ) - 1 }, + { "__invalid__", sizeof( "__invalid__" ) - 1 }, + { "private", sizeof( "private" ) - 1 }, + { "protected", sizeof( "protected" ) - 1 }, + { "public", sizeof( "public" ) - 1 }, + { ".", sizeof( "." ) - 1 }, + { "::", sizeof( "::" ) - 1 }, + { "&", sizeof( "&" ) - 1 }, + { "&&", sizeof( "&&" ) - 1 }, + { ":", sizeof( ":" ) - 1 }, + { "[[", sizeof( "[[" ) - 1 }, + { "]]", sizeof( "]]" ) - 1 }, + { "{", sizeof( "{" ) - 1 }, + { "}", sizeof( "}" ) - 1 }, + { "[", sizeof( "[" ) - 1 }, + { "]", sizeof( "]" ) - 1 }, + { "(", sizeof( "(" ) - 1 }, + { ")", sizeof( ")" ) - 1 }, + { "__comment__", sizeof( "__comment__" ) - 1 }, + { "__comment_end__", sizeof( "__comment_end__" ) - 1 }, + { "__comment_start__", sizeof( "__comment_start__" ) - 1 }, + { "__character__", sizeof( "__character__" ) - 1 }, + { ",", sizeof( "," ) - 1 }, + { "class", sizeof( "class" ) - 1 }, + { "__attribute__", sizeof( "__attribute__" ) - 1 }, + { "__declspec", sizeof( "__declspec" ) - 1 }, + { "enum", sizeof( "enum" ) - 1 }, + { "extern", sizeof( "extern" ) - 1 }, + { "friend", sizeof( "friend" ) - 1 }, + { "module", sizeof( "module" ) - 1 }, + { "namespace", sizeof( "namespace" ) - 1 }, + { "operator", sizeof( "operator" ) - 1 }, + { "struct", sizeof( "struct" ) - 1 }, + { "template", sizeof( "template" ) - 1 }, + { "typedef", sizeof( "typedef" ) - 1 }, + { "using", sizeof( "using" ) - 1 }, + { "union", sizeof( "union" ) - 1 }, + { "__identifier__", sizeof( "__identifier__" ) - 1 }, + { "import", sizeof( "import" ) - 1 }, + { "export", sizeof( "export" ) - 1 }, + { "__new_line__", sizeof( "__new_line__" ) - 1 }, + { "__number__", sizeof( "__number__" ) - 1 }, + { "__operator__", sizeof( "__operator__" ) - 1 }, + { "#", sizeof( "#" ) - 1 }, + { "define", sizeof( "define" ) - 1 }, + { "if", sizeof( "if" ) - 1 }, + { "ifdef", sizeof( "ifdef" ) - 1 }, + { "ifndef", sizeof( "ifndef" ) - 1 }, + { "elif", sizeof( "elif" ) - 1 }, + { "else", sizeof( "else" ) - 1 }, + { "endif", sizeof( "endif" ) - 1 }, + { "include", sizeof( "include" ) - 1 }, + { "pragma", sizeof( "pragma" ) - 1 }, + { "__macro_content__", sizeof( "__macro_content__" ) - 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 }, + { "consteval", sizeof( "consteval" ) - 1 }, + { "constexpr", sizeof( "constexpr" ) - 1 }, + { "constinit", sizeof( "constinit" ) - 1 }, + { "explicit", sizeof( "explicit" ) - 1 }, + { "extern", sizeof( "extern" ) - 1 }, + { "final", sizeof( "final" ) - 1 }, + { "FORCEINLINE", sizeof( "FORCEINLINE" ) - 1 }, + { "FORCEINLINE_DEBUGGABLE", sizeof( "FORCEINLINE_DEBUGGABLE" ) - 1 }, + { "global", sizeof( "global" ) - 1 }, + { "inline", sizeof( "inline" ) - 1 }, + { "internal", sizeof( "internal" ) - 1 }, + { "local_persist", sizeof( "local_persist" ) - 1 }, + { "mutable", sizeof( "mutable" ) - 1 }, + { "neverinline", sizeof( "neverinline" ) - 1 }, + { "override", sizeof( "override" ) - 1 }, + { "static", sizeof( "static" ) - 1 }, + { "thread_local", sizeof( "thread_local" ) - 1 }, + { "volatile", sizeof( "volatile" ) - 1 }, + { "virtual", sizeof( "virtual" ) - 1 }, + { "*", sizeof( "*" ) - 1 }, + { ";", sizeof( ";" ) - 1 }, + { "static_assert", sizeof( "static_assert" ) - 1 }, + { "__string__", sizeof( "__string__" ) - 1 }, + { "typename", sizeof( "typename" ) - 1 }, + { "unsigned", sizeof( "unsigned" ) - 1 }, + { "signed", sizeof( "signed" ) - 1 }, + { "short", sizeof( "short" ) - 1 }, + { "long", sizeof( "long" ) - 1 }, + { "bool", sizeof( "bool" ) - 1 }, + { "char", sizeof( "char" ) - 1 }, + { "int", sizeof( "int" ) - 1 }, + { "double", sizeof( "double" ) - 1 }, + { "__int8", sizeof( "__int8" ) - 1 }, + { "__int16", sizeof( "__int16" ) - 1 }, + { "__int32", sizeof( "__int32" ) - 1 }, + { "__int64", sizeof( "__int64" ) - 1 }, + { "_W64", sizeof( "_W64" ) - 1 }, + { "...", sizeof( "..." ) - 1 }, + { "__attrib_start__", sizeof( "__attrib_start__" ) - 1 }, + { "GEN_API_Export_Code", sizeof( "GEN_API_Export_Code" ) - 1 }, + { "GEN_API_Import_Code", sizeof( "GEN_API_Import_Code" ) - 1 }, + { "COREUOBJECT_API", sizeof( "COREUOBJECT_API" ) - 1 }, + { "ENGINE_API", sizeof( "ENGINE_API" ) - 1 }, + { "GAMEPLAYABILITIES_API", sizeof( "GAMEPLAYABILITIES_API" ) - 1 }, + { "UMG_API", sizeof( "UMG_API" ) - 1 }, + { "UE_DEPRECATED", sizeof( "UE_DEPRECATED" ) - 1 }, }; return lookup[type]; } @@ -876,17 +887,19 @@ inline TokType str_to_toktype( Str str ) enum TokFlags : u32 { - TF_Operator = bit(0), - TF_Assign = bit(1), - TF_Preprocess = bit(2), - TF_Preprocess_Cond = bit(3), - TF_Attribute = bit(6), - TF_AccessOperator = bit( 7 ), - TF_AccessSpecifier = bit( 8 ), - TF_Specifier = bit( 9 ), - TF_EndDefinition = bit( 10 ), // Either ; or } - TF_Formatting = bit( 11 ), - TF_Literal = bit( 12 ), + TF_Operator = bit(0), + TF_Assign = bit(1), + TF_Preprocess = bit(2), + TF_Preprocess_Cond = bit(3), + TF_Attribute = bit(6), + TF_AccessOperator = bit(7), + TF_AccessSpecifier = bit(8), + TF_Specifier = bit(9), + TF_EndDefinition = bit(10), // Either ; or } + TF_Formatting = bit(11), + TF_Literal = bit(12), + TF_Macro_Functional = bit(13), + TF_Macro_Expects_Body = bit(14), TF_Null = 0, TF_UnderlyingType = GEN_U32_MAX, @@ -920,42 +933,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); @@ -973,7 +986,7 @@ struct LexContext char const* scanner; s32 line; s32 column; - StringTable defines; + // StringTable defines; Token token; }; @@ -991,6 +1004,83 @@ struct ParseContext TokArray Tokens; StackNode* Scope; }; + +enum MacroType : u16 +{ + MT_Expression, // A macro is assumed to be a expression if not resolved. + MT_Statement, + MT_Typename, + MT_Attribute, // More of a note to the parser than anythign else (attributes should be defined in the user attribues def). + MT_Specifier, // More of a note to the parser than anythign else (specifiers should be defined in the user attribues def). + MT_Block_Start, // Not Supported yet + MT_Block_End, // Not Supported yet + MT_Case_Statement, // Not Supported yet + + MT_UnderlyingType = GEN_U16_MAX, +}; + +FORCEINLINE +TokType macrotype_to_toktype( MacroType type ) { + switch ( type ) { + case MT_Statement : return Tok_Preprocess_Macro_Stmt; + case MT_Expression : return Tok_Preprocess_Macro_Expr; + case MT_Typename : return Tok_Preprocess_Macro_Typename; + } + // All others unsupported for now. + return Tok_Invalid; +} + +Str macrotype_to_str( MacroType type ) +{ + local_persist + Str lookup[] = { + { "Statement", sizeof("Statement") - 1 }, + { "Expression", sizeof("Expression") - 1 }, + { "Typename", sizeof("Typename") - 1 }, + { "Attribute(Macro)", sizeof("Attribute(Macro)") - 1 }, + { "Specifier(Macro)", sizeof("Specifier(Macro)") - 1 }, + { "Block_Start", sizeof("Block_Start") - 1 }, + { "Block_End", sizeof("Block_End") - 1 }, + { "Case_Statement", sizeof("Case_Statement") - 1 }, + }; + local_persist + Str invalid = { "Invalid", sizeof("Invalid") }; + if ( type > MT_Case_Statement ) + return invalid; + + return lookup[ type ]; +} + +enum EMacroFlags : 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_Allow_As_Identifier = bit(2), // lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one. + // ^^^ This is a sort of kludge because we don't support push/pop macro programs rn. ^^^ + + MF_Null = 0, + MF_UnderlyingType = GEN_U16_MAX, +}; +typedef u16 MacroFlags; + +struct Macro +{ + StrCached Name; + MacroType Type; + MacroFlags Flags; +}; + +FORCEINLINE +b32 macro_is_functional( Macro macro ) { + return bitfield_is_set( b16, macro.Flags, MF_Functional ); +} + +FORCEINLINE +b32 macro_expects_body( Macro macro ) { + return bitfield_is_set( b16, macro.Flags, MF_Expects_Body ); +} + +typedef HashTable(Macro) MacroTable; #pragma endregion Types #pragma region AST @@ -1015,6 +1105,7 @@ struct AST_Constructor; // struct AST_BaseClass; struct AST_Class; struct AST_Define; +struct AST_DefineParams; struct AST_Destructor; struct AST_Enum; struct AST_Exec; @@ -1087,6 +1178,7 @@ typedef AST_Comment* CodeComment; typedef AST_Class* CodeClass; typedef AST_Constructor* CodeConstructor; typedef AST_Define* CodeDefine; +typedef AST_DefineParams* CodeDefineParams; typedef AST_Destructor* CodeDestructor; typedef AST_Enum* CodeEnum; typedef AST_Exec* CodeExec; @@ -1109,6 +1201,7 @@ struct CodeComment; struct CodeClass; struct CodeConstructor; struct CodeDefine; +struct CodeDefineParams; struct CodeDestructor; struct CodeEnum; struct CodeExec; @@ -1294,6 +1387,7 @@ struct Code operator CodeClass() const; operator CodeConstructor() const; operator CodeDefine() const; + operator CodeDefineParams() const; operator CodeDestructor() const; operator CodeExec() const; operator CodeEnum() const; @@ -1354,6 +1448,7 @@ int AST_ArrSpecs_Cap = /* Simple AST POD with functionality to seralize into C++ syntax. + TODO(Ed): Eventually haven't a transparent AST like this will longer be viable once statements & expressions are in (most likely....) */ struct AST { @@ -1361,7 +1456,7 @@ struct AST struct { Code InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable - Code Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable + Code Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable // TODO(Ed): Parameters can have attributes Code Specs; // Destructor, Function, Operator, Typename, Variable union { Code InitializerList; // Constructor @@ -1373,12 +1468,12 @@ struct AST union { Code Macro; // Parameter Code BitfieldSize; // Variable (Class/Struct Data Member) - Code Params; // Constructor, Function, Operator, Template, Typename + Code Params; // Constructor, Define, Function, Operator, Template, Typename Code UnderlyingTypeMacro; // Enum }; union { Code ArrExpr; // Typename - Code Body; // Class, Constructor, Destructor, Enum, Friend, Function, Namespace, Struct, Union + Code Body; // Class, Constructor, Define, Destructor, Enum, Friend, Function, Namespace, Struct, Union Code Declaration; // Friend, Template Code Value; // Parameter, Variable }; @@ -1469,7 +1564,17 @@ GEN_API StrBuilder class_to_strbuilder ( CodeClass self ); GEN_API void class_to_strbuilder_def( CodeClass self, StrBuilder* result ); GEN_API void class_to_strbuilder_fwd( CodeClass self, StrBuilder* result ); -GEN_API void params_append (CodeParams params, CodeParams param ); +GEN_API void define_params_append (CodeDefineParams appendee, CodeDefineParams other ); +GEN_API CodeDefineParams define_params_get (CodeDefineParams params, s32 idx); +GEN_API bool define_params_has_entries (CodeDefineParams params ); +GEN_API StrBuilder define_params_to_strbuilder (CodeDefineParams params ); +GEN_API void define_params_to_strbuilder_ref(CodeDefineParams params, StrBuilder* result ); + +GEN_API CodeDefineParams begin_CodeDefineParams(CodeDefineParams params); +GEN_API CodeDefineParams end_CodeDefineParams (CodeDefineParams params); +GEN_API CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter); + +GEN_API void params_append (CodeParams appendee, CodeParams other ); GEN_API CodeParams params_get (CodeParams params, s32 idx); GEN_API bool params_has_entries (CodeParams params ); GEN_API StrBuilder params_to_strbuilder (CodeParams params ); @@ -1629,12 +1734,11 @@ struct CodeParams { #if ! GEN_C_LIKE_CPP Using_Code( CodeParams ); - FORCEINLINE void append( CodeParams other ); - FORCEINLINE CodeParams get( s32 idx ); - FORCEINLINE bool has_entries(); - FORCEINLINE StrBuilder to_strbuilder(); - FORCEINLINE void to_strbuilder( StrBuilder& result ); - + FORCEINLINE void append( CodeParams other ) { return params_append(* this, other); } + FORCEINLINE CodeParams get( s32 idx ) { return params_get( * this, idx); } + FORCEINLINE bool has_entries() { return params_has_entries(* this); } + FORCEINLINE StrBuilder to_strbuilder() { return params_to_strbuilder(* this); } + FORCEINLINE void to_strbuilder( StrBuilder& result ) { return params_to_strbuilder_ref(*this, & result); } #endif Using_CodeOps( CodeParams ); FORCEINLINE CodeParams begin() { return begin_CodeParams(* this); } @@ -1649,6 +1753,29 @@ struct CodeParams AST_Params* ast; }; +struct CodeDefineParams +{ +#if ! GEN_C_LIKE_CPP + Using_Code( CodeDefineParams ); + FORCEINLINE void append( CodeDefineParams other ) { return params_append( cast(CodeParams, * this), cast(CodeParams, other)); } + FORCEINLINE CodeDefineParams get( s32 idx ) { return (CodeDefineParams) (Code) params_get( cast(CodeParams, * this), idx); } + FORCEINLINE bool has_entries() { return params_has_entries( cast(CodeParams, * this)); } + FORCEINLINE StrBuilder to_strbuilder() { return define_params_to_strbuilder(* this); } + FORCEINLINE void to_strbuilder( StrBuilder& result ) { return define_params_to_strbuilder_ref(* this, & result); } +#endif + Using_CodeOps( CodeDefineParams ); + FORCEINLINE CodeDefineParams begin() { return (CodeDefineParams) (Code) begin_CodeParams( cast(CodeParams, * this)); } + FORCEINLINE CodeDefineParams end() { return (CodeDefineParams) (Code) end_CodeParams( cast(CodeParams, * this)); } + FORCEINLINE operator Code() { return { (AST*)ast }; } + FORCEINLINE CodeDefineParams operator *() { return * this; } // Required to support for-range iteration. + FORCEINLINE AST_DefineParams* operator->() { + GEN_ASSERT(ast); + return ast; + } + FORCEINLINE CodeDefineParams& operator++(); + AST_DefineParams* ast; +}; + struct CodeSpecifiers { #if ! GEN_C_LIKE_CPP @@ -2378,6 +2505,7 @@ struct InvalidCode_ImplictCaster operator CodeClass () const { return cast(CodeClass, Code_Invalid); } operator CodeConstructor () const { return cast(CodeConstructor, Code_Invalid); } operator CodeDefine () const { return cast(CodeDefine, Code_Invalid); } + operator CodeDefineParams () const { return cast(CodeDefineParams, Code_Invalid); } operator CodeDestructor () const { return cast(CodeDestructor, Code_Invalid); } operator CodeExec () const { return cast(CodeExec, Code_Invalid); } operator CodeEnum () const { return cast(CodeEnum, Code_Invalid); } @@ -2411,6 +2539,7 @@ struct NullCode_ImplicitCaster operator CodeClass () const { return {nullptr}; } operator CodeConstructor () const { return {nullptr}; } operator CodeDefine () const { return {nullptr}; } + operator CodeDefineParams () const { return {nullptr}; } operator CodeDestructor () const { return {nullptr}; } operator CodeExec () const { return {nullptr}; } operator CodeEnum () const { return {nullptr}; } @@ -2461,17 +2590,23 @@ FORCEINLINE StrBuilder to_strbuilder ( CodeClass self ) FORCEINLINE void to_strbuilder_def( CodeClass self, StrBuilder& result ) { return class_to_strbuilder_def(self, & result); } FORCEINLINE void to_strbuilder_fwd( CodeClass self, StrBuilder& result ) { return class_to_strbuilder_fwd(self, & result); } -FORCEINLINE void append (CodeParams params, CodeParams param ) { return params_append(params, param); } -FORCEINLINE CodeParams get (CodeParams params, s32 idx) { return params_get(params, idx); } -FORCEINLINE bool has_entries (CodeParams params ) { return params_has_entries(params); } -FORCEINLINE StrBuilder to_strbuilder(CodeParams params ) { return params_to_strbuilder(params); } -FORCEINLINE void to_strbuilder(CodeParams params, StrBuilder& result ) { return params_to_strbuilder_ref(params, & result); } +FORCEINLINE void append (CodeDefineParams appendee, CodeDefineParams other ) { params_append(cast(CodeParams, appendee), cast(CodeParams, other)); } +FORCEINLINE CodeDefineParams get (CodeDefineParams params, s32 idx) { return (CodeDefineParams) (Code) params_get(cast(CodeParams, params), idx); } +FORCEINLINE bool has_entries (CodeDefineParams params ) { return params_has_entries(cast(CodeParams, params)); } +FORCEINLINE StrBuilder to_strbuilder(CodeDefineParams params ) { return define_params_to_strbuilder(params); } +FORCEINLINE void to_strbuilder(CodeDefineParams params, StrBuilder& result ) { return define_params_to_strbuilder_ref(params, & result); } + +FORCEINLINE void append (CodeParams appendee, CodeParams other ) { return params_append(appendee, other); } +FORCEINLINE CodeParams get (CodeParams params, s32 idx) { return params_get(params, idx); } +FORCEINLINE bool has_entries (CodeParams params ) { return params_has_entries(params); } +FORCEINLINE StrBuilder to_strbuilder(CodeParams params ) { return params_to_strbuilder(params); } +FORCEINLINE void to_strbuilder(CodeParams params, StrBuilder& result ) { return params_to_strbuilder_ref(params, & result); } FORCEINLINE bool append (CodeSpecifiers specifiers, Specifier spec) { return specifiers_append(specifiers, spec); } FORCEINLINE s32 has (CodeSpecifiers specifiers, Specifier spec) { return specifiers_has(specifiers, spec); } FORCEINLINE s32 remove (CodeSpecifiers specifiers, Specifier to_remove ) { return specifiers_remove(specifiers, to_remove); } FORCEINLINE StrBuilder to_strbuilder(CodeSpecifiers specifiers) { return specifiers_to_strbuilder(specifiers); } -FORCEINLINE void to_strbuilder(CodeSpecifiers specifiers, StrBuilder& result) { return specifiers_to_strbuilder_ref(specifiers, & result); } +FORCEINLINE void to_strbuilder(CodeSpecifiers specifiers, StrBuilder& result) { return specifiers_to_strbuilder_ref(specifiers, & result); } FORCEINLINE void add_interface (CodeStruct self, CodeTypename interface) { return struct_add_interface(self, interface); } FORCEINLINE StrBuilder to_strbuilder (CodeStruct self) { return struct_to_strbuilder(self); } @@ -2710,9 +2845,15 @@ struct AST_Define { union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; - StrCached Content; + struct + { + char _PAD_PROPERTIES_ [ sizeof(AST*) * 4 ]; + CodeDefineParams Params; + Code Body; // Should be completely serialized for now to a: StrCached Content. + char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 1 ]; + }; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2722,6 +2863,22 @@ struct AST_Define }; static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the same size as AST"); +struct AST_DefineParams +{ + union { + char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; + }; + StrCached Name; + CodeDefineParams Last; + CodeDefineParams Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + s32 NumEntries; +}; +static_assert( sizeof(AST_DefineParams) == sizeof(AST), "ERROR: AST_DefineParams is not the same size as AST"); + struct AST_Destructor { union { @@ -3224,6 +3381,7 @@ struct AST_Params char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; struct { + // TODO(Ed): Support attributes for parameters (Some prefix macros can be converted to that...) char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ]; CodeTypename ValueType; Code Macro; @@ -3232,7 +3390,7 @@ struct AST_Params // char _PAD_PROPERTIES_3_[sizeof( AST* )]; }; }; - StrCached Name; + StrCached Name; CodeParams Last; CodeParams Next; Token* Tok; @@ -3768,7 +3926,7 @@ struct Context u32 CodePool_NumBlocks; // TODO(Ed): Review these... (No longer needed if using the proper allocation strategy) - u32 InitSize_LexArena; + u32 InitSize_LexerTokens; u32 SizePer_StringArena; // TODO(Ed): Symbol Table @@ -3779,7 +3937,7 @@ struct Context // Used by the lexer to persistently treat all these identifiers as preprocessor defines. // Populate with strings via gen::cache_str. // Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments. - Array(StrCached) PreprocessorDefines; + MacroTable Macros; // Backend @@ -3795,9 +3953,6 @@ struct Context StringTable StrCache; // TODO(Ed): This needs to be just handled by a parser context - - Arena LexArena; - StringTable Lexer_defines; Array(Token) Lexer_Tokens; // TODO(Ed): Active parse context vs a parse result need to be separated conceptually @@ -3817,9 +3972,17 @@ GEN_API void reset(Context* ctx); GEN_API void set_context(Context* ctx); +// Mostly intended for the parser +GEN_API Macro* lookup_macro( Str Name ); + // Alternative way to add a preprocess define entry for the lexer & parser to utilize // if the user doesn't want to use def_define -GEN_API void set_preprocess_define( Str id, b32 is_functional ); +// Macros are tracked by name so if the name already exists the entry will be overwritten. +GEN_API void register_macro( Macro macro ); + +// Ease of use batch registration +GEN_API void register_macros( s32 num, ... ); +GEN_API void register_macros( s32 num, Macro* macros ); // Used internally to retrive or make string allocations. // Strings are stored in a series of string arenas of fixed size (SizePer_StringArena) @@ -3858,9 +4021,12 @@ struct Opts_def_constructor { GEN_API CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEFAULT ); struct Opts_def_define { - b32 dont_append_preprocess_defines; + CodeDefineParams params; + Str content; + MacroFlags flags; + b32 dont_register_to_preprocess_macros; }; -GEN_API CodeDefine def_define( Str name, Str content, Opts_def_define opts GEN_PARAM_DEFAULT ); +GEN_API CodeDefine def_define( Str name, MacroType type, Opts_def_define opts GEN_PARAM_DEFAULT ); struct Opts_def_destructor { Code body; @@ -3971,28 +4137,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 @@ -4034,6 +4202,7 @@ CodeBody parse_file( Str path ); GEN_API CodeClass parse_class ( Str class_def ); GEN_API CodeConstructor parse_constructor ( Str constructor_def ); +GEN_API CodeDefine parse_define ( Str define_def ); GEN_API CodeDestructor parse_destructor ( Str destructor_def ); GEN_API CodeEnum parse_enum ( Str enum_def ); GEN_API CodeBody parse_export_body ( Str export_def ); @@ -4388,6 +4557,25 @@ CodeParams next_CodeParams(CodeParams params, CodeParams param_iter) } #pragma endregion CodeParams +#pragma region CodeDefineParams +FORCEINLINE void define_params_append (CodeDefineParams appendee, CodeDefineParams other ) { params_append( cast(CodeParams, appendee), cast(CodeParams, other) ); } +FORCEINLINE CodeDefineParams define_params_get (CodeDefineParams self, s32 idx ) { return (CodeDefineParams) (Code) params_get( cast(CodeParams, self), idx); } +FORCEINLINE bool define_params_has_entries(CodeDefineParams self) { return params_has_entries( cast(CodeParams, self)); } + +CodeDefineParams begin_CodeDefineParams(CodeDefineParams params) { return (CodeDefineParams) (Code) begin_CodeParams( cast(CodeParams, (Code)params)); } +CodeDefineParams end_CodeDefineParams (CodeDefineParams params) { return (CodeDefineParams) (Code) end_CodeParams ( cast(CodeParams, (Code)params)); } +CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter) { return (CodeDefineParams) (Code) next_CodeParams ( cast(CodeParams, (Code)params), cast(CodeParams, (Code)entry_iter)); } + +#if GEN_COMPILER_CPP +FORCEINLINE +CodeDefineParams& CodeDefineParams::operator ++() +{ + * this = ast->Next; + return * this; +} +#endif +#pragma endregion CodeDefineParams + #pragma region CodeSpecifiers inline bool specifiers_append(CodeSpecifiers self, Specifier spec ) @@ -4718,6 +4906,22 @@ inline AST_Define* CodeDefine::operator->() return ast; } +inline CodeDefineParams& CodeDefineParams::operator=( Code other ) +{ + if ( other.ast != nullptr && other->Parent != nullptr ) + { + ast = rcast( decltype( ast ), code_duplicate( other ).ast ); + ast->Parent = { nullptr }; + } + ast = rcast( decltype( ast ), other.ast ); + return *this; +} + +inline CodeDefineParams::operator bool() +{ + return ast != nullptr; +} + inline CodeDestructor& CodeDestructor::operator=( Code other ) { if ( other.ast != nullptr && other->Parent != nullptr ) @@ -5390,6 +5594,11 @@ FORCEINLINE Code::operator CodeDefine() const return { (AST_Define*)ast }; } +FORCEINLINE Code::operator CodeDefineParams() const +{ + return { (AST_DefineParams*)ast }; +} + FORCEINLINE Code::operator CodeDestructor() const { return { (AST_Destructor*)ast }; @@ -5507,7 +5716,7 @@ GEN_OPITMIZE_MAPPINGS_END #pragma region Constants -extern Str enum_underlying_sig; +extern Macro enum_underlying_macro; extern Code access_public; extern Code access_protected; diff --git a/scripts/helpers/vendor_toolchain.ps1 b/scripts/helpers/vendor_toolchain.ps1 index 329881c..6093cb9 100644 --- a/scripts/helpers/vendor_toolchain.ps1 +++ b/scripts/helpers/vendor_toolchain.ps1 @@ -195,11 +195,11 @@ if ( $vendor -match "clang" ) $compiler_args += $flag_no_optimization } if ( $debug ) { - $compiler_args += ( $flag_define + 'Build_Debug=1' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=1' ) $compiler_args += $flag_debug, $flag_debug_codeview, $flag_profiling_debug } else { - $compiler_args += ( $flag_define + 'Build_Debug=0' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=0' ) } $warning_ignores | ForEach-Object { @@ -275,11 +275,11 @@ if ( $vendor -match "clang" ) $compiler_args += $flag_no_optimization } if ( $debug ) { - $compiler_args += ( $flag_define + 'Build_Debug=1' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=1' ) $compiler_args += $flag_debug, $flag_debug_codeview, $flag_profiling_debug } else { - $compiler_args += ( $flag_define + 'Build_Debug=0' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=0' ) } $warning_ignores | ForEach-Object { @@ -399,7 +399,7 @@ if ( $vendor -match "msvc" ) if ( $debug ) { $compiler_args += $flag_debug - $compiler_args += ( $flag_define + 'Build_Debug=1' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=1' ) $compiler_args += ( $flag_path_debug + $path_output + '\' ) $compiler_args += $flag_link_win_rt_static_debug @@ -408,7 +408,7 @@ if ( $vendor -match "msvc" ) } } else { - $compiler_args += ( $flag_define + 'Build_Debug=0' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=0' ) $compiler_args += $flag_link_win_rt_static } $compiler_args += $includes | ForEach-Object { $flag_include + $_ } @@ -485,7 +485,7 @@ if ( $vendor -match "msvc" ) if ( $debug ) { $compiler_args += $flag_debug - $compiler_args += ( $flag_define + 'Build_Debug=1' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=1' ) $compiler_args += ( $flag_path_debug + $path_output + '\' ) $compiler_args += $flag_link_win_rt_static_debug @@ -494,7 +494,7 @@ if ( $vendor -match "msvc" ) } } else { - $compiler_args += ( $flag_define + 'Build_Debug=0' ) + $compiler_args += ( $flag_define + 'GEN_BUILD_DEBUG=0' ) $compiler_args += $flag_link_win_rt_static } $compiler_args += $includes | ForEach-Object { $flag_include + $_ }