diff --git a/base/components/code_serialization.cpp b/base/components/code_serialization.cpp index 9ec168b..39dacb5 100644 --- a/base/components/code_serialization.cpp +++ b/base/components/code_serialization.cpp @@ -38,13 +38,13 @@ void body_to_strbuilder_export( CodeBody body, StrBuilder* result ) GEN_ASSERT(result != nullptr); strbuilder_append_fmt( result, "export\n{\n" ); - Code curr = cast(Code, body); + Code curr = body->Front; s32 left = body->NumEntries; while ( left-- ) { code_to_strbuilder_ref(curr, result); // strbuilder_append_fmt( result, "%SB", code_to_strbuilder(curr) ); - ++curr; + curr = curr->Next; } strbuilder_append_fmt( result, "};\n" ); diff --git a/base/components/inlines.hpp b/base/components/inlines.hpp index 5bf6bf5..45e572c 100644 --- a/base/components/inlines.hpp +++ b/base/components/inlines.hpp @@ -38,7 +38,7 @@ void body_to_strbuilder_ref( CodeBody body, StrBuilder* result ) { code_to_strbuilder_ref(curr, result); // strbuilder_append_fmt( result, "%SB", code_to_strbuilder(curr) ); - ++curr; + curr = curr->Next; } } diff --git a/base/components/interface.cpp b/base/components/interface.cpp index b3eaf45..7d65eda 100644 --- a/base/components/interface.cpp +++ b/base/components/interface.cpp @@ -283,6 +283,15 @@ void init(Context* ctx) ctx->InitSize_Fallback_Allocator_Bucket_Size = megabytes(8); } + if (ctx->InitSize_StrCacheTable == 0) + { + ctx->InitSize_StrCacheTable = kilobytes(8); + } + if (ctx->InitSize_MacrosTable == 0) + { + ctx->InitSize_MacrosTable = kilobytes(8); + } + // Override the current context (user has to put it back if unwanted). _ctx = ctx; @@ -311,11 +320,11 @@ void init(Context* ctx) } // Setup the hash tables { - ctx->StrCache = hashtable_init(StrCached, ctx->Allocator_DyanmicContainers); + ctx->StrCache = hashtable_init_reserve(StrCached, ctx->Allocator_DyanmicContainers, ctx->InitSize_StrCacheTable); if ( ctx->StrCache.Entries == nullptr ) GEN_FATAL( "gen::init: Failed to initialize the StringCache"); - ctx->Macros = hashtable_init(Macro, ctx->Allocator_DyanmicContainers); + ctx->Macros = hashtable_init_reserve(Macro, ctx->Allocator_DyanmicContainers, ctx->InitSize_MacrosTable); if (ctx->Macros.Hashes == nullptr || ctx->Macros.Entries == nullptr) { GEN_FATAL( "gen::init: Failed to initialize the PreprocessMacros table" ); } diff --git a/base/components/interface.hpp b/base/components/interface.hpp index 7578f1c..da0a1b3 100644 --- a/base/components/interface.hpp +++ b/base/components/interface.hpp @@ -64,6 +64,9 @@ struct Context u32 InitSize_LexerTokens; u32 SizePer_StringArena; + u32 InitSize_StrCacheTable; + u32 InitSize_MacrosTable; + // TODO(Ed): Symbol Table // Keep track of all resolved symbols (naemspaced identifiers) diff --git a/base/components/parser.cpp b/base/components/parser.cpp index b064e04..b786613 100644 --- a/base/components/parser.cpp +++ b/base/components/parser.cpp @@ -1443,6 +1443,22 @@ CodeFn parse_function_after_name( } // ( ) + // Check for trailing specifiers... + CodeAttributes post_rt_attributes = parse_attributes(); + if (post_rt_attributes) + { + if (attributes) + { + StrBuilder merged = strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S %S", attributes->Content, post_rt_attributes->Content); + attributes->Content = cache_str(strbuilder_to_str(merged)); + } + else + { + attributes = post_rt_attributes; + } + } + // ( ) + CodeBody body = NullCode; CodeComment inline_cmt = NullCode; if ( check( Tok_BraceCurly_Open ) ) @@ -1481,17 +1497,19 @@ CodeFn parse_function_after_name( if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) inline_cmt = parse_comment(); - // ( ) ; + // ( ) < = 0 or delete > ; } - else + + + if (body == nullptr) { Token stmt_end = currtok; eat( Tok_Statement_End ); - // ( ) ; + // ( ) < = 0 or delete > ; if ( currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line ) inline_cmt = parse_comment(); - // ( ) ; + // ( ) < = 0 or delete > ; } StrBuilder @@ -1766,7 +1784,7 @@ CodeBody parse_global_nspace( CodeType which ) case Tok_Preprocess_Macro_Expr: { - if (tok_is_attribute(currtok)) + if ( ! tok_is_attribute(currtok)) { log_failure("Unbounded macro expression residing in class/struct body\n%S", parser_to_strbuilder(_ctx->parser)); return InvalidCode; @@ -2049,11 +2067,20 @@ Token parse_identifier( bool* possible_member_function ) Macro* macro = lookup_macro(currtok.Text); b32 accept_as_identifier = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Identifier ); + b32 is_decarator = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Identifier_Decorator ); // Typename can be: '::' // If that is the case first option will be Tok_Access_StaticSymbol below - if (check(Tok_Identifier) || accept_as_identifier) - eat( Tok_Identifier ); + if (check(Tok_Identifier) || accept_as_identifier) + { + if (is_decarator) { + Code name_macro = parse_simple_preprocess(currtok.Type); + name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr; + } + else { + eat(Tok_Identifier); + } + } // parse_template_args( & name ); @@ -4714,21 +4741,37 @@ CodeTypename parser_parse_type( bool from_template, bool* typedef_is_function ) else if ( currtok.Type == Tok_Decl_Class || currtok.Type == Tok_Decl_Enum || currtok.Type == Tok_Decl_Struct || currtok.Type == Tok_Decl_Union ) { - switch (currtok.Type) { - case Tok_Decl_Class : tag = Tag_Class; break; - case Tok_Decl_Enum : tag = Tag_Enum; break; - case Tok_Decl_Struct : tag = Tag_Struct; break; - case Tok_Decl_Union : tag = Tag_Union; break; - default: - break; + Token next = nexttok; + + if (next.Type == Tok_Identifier) + { + switch (currtok.Type) { + case Tok_Decl_Class : tag = Tag_Class; break; + case Tok_Decl_Enum : tag = Tag_Enum; break; + case Tok_Decl_Struct : tag = Tag_Struct; break; + case Tok_Decl_Union : tag = Tag_Union; break; + default: + break; + } + eat( currtok.Type ); + // + + name = parse_identifier(nullptr); + // } - eat( currtok.Type ); - // + else if (next.Type == Tok_BraceCurly_Open) + { + name = currtok; + // We have an inplace definition, we need to consume that... - name = parse_identifier(nullptr); + // TODO(Ed): we need to add a way for AST_CodeTypename to track an implace definition.. + b32 const inplace = true; + Code indplace_def = cast(Code, parser_parse_struct(inplace)); - // name.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )name.Text; - // eat( Tok_Identifier ); + // For now we lose the structural information, + name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr; + // + } _ctx->parser.Scope->Name = name.Text; // } diff --git a/base/components/parser_types.hpp b/base/components/parser_types.hpp index 2393945..a2bd57a 100644 --- a/base/components/parser_types.hpp +++ b/base/components/parser_types.hpp @@ -168,26 +168,36 @@ Str macrotype_to_str( MacroType 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. + // Macro has parameters (args expected to be passed) + MF_Functional = bit(0), + + // Expects to assign a braced scope to its body. + MF_Expects_Body = bit(1), // lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one. - // ^^^ This is a kludge because we don't support push/pop macro pragmas rn. + // This is a kludge because we don't support push/pop macro pragmas rn. MF_Allow_As_Identifier = bit(2), + // When parsing identifiers, it will allow the consumption of the macro parameters (as its expected to be a part of constructing the identifier) + // Example of a decarator macro from stb_sprintf.h: + // STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char* buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); + // ^^ STB_SPRINTF_DECORATE is decorating sprintf + MF_Identifier_Decorator = bit(3), + // lex__eat wil treat this macro as an attribute if the parser attempts to consume it as one. - // ^^^ This a kludge because unreal has a macro that behaves as both a 'statement' and an attribute (UE_DEPRECATED, PRAGMA_ENABLE_DEPRECATION_WARNINGS, etc) + // This a kludge because unreal has a macro that behaves as both a 'statement' and an attribute (UE_DEPRECATED, PRAGMA_ENABLE_DEPRECATION_WARNINGS, etc) // TODO(Ed): We can keep the MF_Allow_As_Attribute flag for macros, however, we need to add the ability of AST_Attributes to chain themselves. // Its thats already a thing in the standard language anyway // & it would allow UE_DEPRECATED, (UE_PROPERTY / UE_FUNCTION) to chain themselves as attributes of a resolved member function/variable definition - MF_Allow_As_Attribute = bit(3), + MF_Allow_As_Attribute = bit(4), // When a macro is encountered after attributes and specifiers while parsing a function, or variable: - // It will consume the macro and treat it as resolving the definition. (Yes this is for Unreal Engine) + // It will consume the macro and treat it as resolving the definition. // (MUST BE OF MT_Statement TYPE) - MF_Allow_As_Definition = bit(4), + MF_Allow_As_Definition = bit(5), - MF_Allow_As_Specifier = bit(5), // Created for Unreal's PURE_VIRTUAL + // Created for Unreal's PURE_VIRTUAL + MF_Allow_As_Specifier = bit(6), MF_Null = 0, MF_UnderlyingType = GEN_U16_MAX, diff --git a/base/dependencies/macros.hpp b/base/dependencies/macros.hpp index c8ad2d7..24b3163 100644 --- a/base/dependencies/macros.hpp +++ b/base/dependencies/macros.hpp @@ -198,21 +198,16 @@ #ifndef forceinline # if GEN_COMPILER_MSVC # define forceinline __forceinline -# define neverinline __declspec( noinline ) # elif GEN_COMPILER_GCC # define forceinline inline __attribute__((__always_inline__)) -# define neverinline __attribute__( ( __noinline__ ) ) # elif GEN_COMPILER_CLANG # if __has_attribute(__always_inline__) # define forceinline inline __attribute__((__always_inline__)) -# define neverinline __attribute__( ( __noinline__ ) ) # else # define forceinline -# define neverinline # endif # else # define forceinline -# define neverinline # endif #endif diff --git a/base/dependencies/memory.hpp b/base/dependencies/memory.hpp index eaad19d..70e5508 100644 --- a/base/dependencies/memory.hpp +++ b/base/dependencies/memory.hpp @@ -138,7 +138,7 @@ constexpr AllocatorInfo heap( void ) { AllocatorInfo allocator = { heap_allocato #define malloc( sz ) alloc( heap(), sz ) //! Helper to free memory allocated by heap allocator. -#define mfree( ptr ) free( heap(), ptr ) +#define mfree( ptr ) allocator_free( heap(), ptr ) struct VirtualMemory { diff --git a/gen_c_library/c_library.refactor b/gen_c_library/c_library.refactor index 4e1d247..96021a1 100644 --- a/gen_c_library/c_library.refactor +++ b/gen_c_library/c_library.refactor @@ -53,6 +53,7 @@ word enum_underlying, gen_enum_underlying word nullptr, gen_nullptr word struct_init, gen_struct_init word hash, gen_hash +word txt, gen_txt // Basic Types @@ -410,6 +411,8 @@ namespace var_, gen_var_ word _ctx, gen__ctx +word get_context, gen_get_context + word init, gen_init word deinit, gen_deinit word reset, gen_reset diff --git a/scripts/helpers/vendor_toolchain.ps1 b/scripts/helpers/vendor_toolchain.ps1 index f1f1baa..9d5f005 100644 --- a/scripts/helpers/vendor_toolchain.ps1 +++ b/scripts/helpers/vendor_toolchain.ps1 @@ -404,7 +404,7 @@ if ( $vendor -match "msvc" ) $flag_optimize_intrinsics = '/Oi' $flag_optimized_debug_forceinline = '/d2Obforceinline' $flag_optimized_debug = '/Zo' - $flag_ + # $flag_ # $flag_out_name = '/OUT:' $flag_path_interm = '/Fo' $flag_path_debug = '/Fd'