diff --git a/Project/Source/GasaEditor/GasaGen/GasaGen.cpp b/Project/Source/GasaEditor/GasaGen/GasaGen.cpp index 839e7e4..8891bf8 100644 --- a/Project/Source/GasaEditor/GasaGen/GasaGen.cpp +++ b/Project/Source/GasaEditor/GasaGen/GasaGen.cpp @@ -128,8 +128,8 @@ void Execute_GasaModule_Codegen() generate_AttributeSets(); generate_DevOptionsCache(); // generate_HostWidgetController(); - change_SBlueprintActionMenu_Construct(); - change_EditorContentList(); + // change_SBlueprintActionMenu_Construct(); + // change_EditorContentList(); gen::deinit( & gen_ctx); }); diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/AST_Design.md b/Project/Source/GasaEditor/GasaGen/gencpp/AST_Design.md index 2f3175a..52486c0 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/AST_Design.md +++ b/Project/Source/GasaEditor/GasaGen/gencpp/AST_Design.md @@ -53,6 +53,7 @@ StrBuilder _to_strbuilder(Code code); Where the first generates strings allocated using Allocator_StringArena and the other appends an existing strings with their backed allocator. -Serialization of for the AST is defined for `Code` in [`ast.chpp`](../base/components/ast.cpp) with `code_to_strbuilder_ptr` & `code_to_strbuilder`. +Serialization of for the AST is defined for `Code` in [`ast.cpp`](../base/components/ast.cpp) with `code_to_strbuilder_ptr` & `code_to_strbuilder`. Serializtion for the rest of the code types is within [`code_serialization.cpp`](../base/components/code_serialization.cpp). + Gencpp's serialization does not provide coherent formatting of the code. The user should use a formatter after serializing. diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/AST_Types.md b/Project/Source/GasaEditor/GasaGen/gencpp/AST_Types.md index 2541162..8d17f1f 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/AST_Types.md +++ b/Project/Source/GasaEditor/GasaGen/gencpp/AST_Types.md @@ -25,13 +25,13 @@ These are containers representing a scope body of a definition that can be of th Fields: ```cpp -StrCached Name; -Code Front; -Code Back; -Token* Tok; -Code Parent; -CodeT Type; -s32 NumEntries; +StrCached Name; +Code Front; +Code Back; +Token* Tok; +Code Parent; +CodeType Type; +s32 NumEntries; ``` The `Front` member represents the start of the link list and `Back` the end. @@ -56,13 +56,13 @@ Represent standard or vendor specific C/C++ attributes. Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +StrCached Content; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -80,13 +80,13 @@ Stores a comment. Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +StrCached Content; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -109,12 +109,12 @@ CodeComment InlineCmt; // Only supported by forward declarations CodeAttributes Attributes; CodeType ParentType; CodeBody Body; -StrCached Name; +StrCached Name; CodeType Prev; CodeType Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ModuleFlag ModuleFlags; AccessSpec ParentAccess; ``` @@ -139,16 +139,16 @@ You'll notice that only one parent type is supported only with parent access. Th Fields: ```cpp -CodeComment InlineCmt; // Only supported by forward declarations -Code InitializerList; -CodeParams Params; -Code Body; +CodeComment InlineCmt; // Only supported by forward declarations +Code InitializerList; +CodeParams Params; +Code Body; StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -178,13 +178,14 @@ Represents a preprocessor define Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +CodeDefineParams Params; +Code Body; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -193,6 +194,28 @@ Serialization: #define ``` +## DefineParams + +Preprocessor define's parameters. + +Fields: + +```cpp +StrCached Name; +Code Last; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; +s32 NumEntries; +``` + +Serialization: + +```cpp +, ... +``` + ## Destructor Fields: @@ -201,12 +224,12 @@ Fields: CodeComment InlineCmt; CodeSpecifiers Specs; Code Body; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ``` Serialization: @@ -242,8 +265,8 @@ Code Prev; Code Next; Token* Tok; Code Parent; -StrCached Name; -CodeT Type; +StrCached Name; +CodeType Type; ModuleFlag ModuleFlags; ``` @@ -271,13 +294,13 @@ Will be obsolute when function body parsing is implemented. Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +StrCached Content; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -286,18 +309,18 @@ Serialization: ``` -## External Linkage +## External Linkage (Extern) Fields: ```cpp -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +CodeBody Body; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -314,13 +337,13 @@ extern "" Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Code Parent; -Token* Tok; -CodeT Type; +StrCached Content; +StrCached Name; +Code Prev; +Code Next; +Code Parent; +Token* Tok; +CodeType Type; ``` Serialization: @@ -336,14 +359,14 @@ This library (until its necessary become some third-party library to do otherwis Fields: ```cpp -CodeComment InlineCmt; -Code Declaration; +CodeComment InlineCmt; +Code Declaration; StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -363,12 +386,12 @@ CodeSpecifiers Specs; CodeType ReturnType; CodeParams Params; CodeBody Body; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ModuleFlag ModuleFlags; ``` @@ -390,13 +413,13 @@ Serialization: Fields: ```cpp -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; -ModuleFlag ModuleFlags; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; +ModuleFlag ModuleFlags; ``` Serialization: @@ -410,14 +433,14 @@ Serialization: Fields: ```cpp -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; -ModuleFlag ModuleFlags; +CodeBody Body; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; +ModuleFlag ModuleFlags; ``` Serialization: @@ -440,12 +463,12 @@ CodeSpecifiers Specs; CodeType ReturnType; CodeParams Params; CodeBody Body; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ModuleFlag ModuleFlags; OperatorT Op; ``` @@ -472,12 +495,12 @@ CodeComment InlineCmt; CodeSpecifiers Specs; CodeType ValueType; CodeBody Body; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ``` Serialization: @@ -498,17 +521,17 @@ Serialization: Fields: ```cpp -CodeType ValueType; -Code Macro; -Code Value; -Code PostNameMacro; -StrCached Name; -CodeParams Last; -CodeParams Next; -Token* Tok; -Code Parent; -CodeT Type; -s32 NumEntries; +CodeType ValueType; +Code Macro; +Code Value; +Code PostNameMacro; +StrCached Name; +CodeParams Last; +CodeParams Next; +Token* Tok; +Code Parent; +CodeType Type; +s32 NumEntries; ``` Serialization: @@ -524,13 +547,13 @@ Serialization: Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +StrCached Content; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -544,13 +567,13 @@ Serialization: Fields: ```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; +StrCached Content; +StrCached Name; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; ``` Serialization: @@ -566,12 +589,12 @@ Fields: ```cpp SpecifierT ArrSpecs[ AST_ArrSpecs_Cap ]; CodeSpecifiers NextSpecs; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; s32 NumEntries; ``` @@ -586,15 +609,15 @@ Serialization: Fields: ```cpp -CodeParams Params; -Code Declaration; +CodeParams Params; +Code Declaration; StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeT Type; -ModuleFlag ModuleFlags; +Code Prev; +Code Next; +Token* Tok; +Code Parent; +CodeType Type; +ModuleFlag ModuleFlags; ``` Serialization: @@ -621,8 +644,8 @@ Code Prev; Code Next; Token* Tok; Code Parent; -StrCached Name; -CodeT Type; +StrCached Name; +CodeType Type; b32 IsParamPack; ETypenameTag TypeTag; ``` @@ -647,16 +670,16 @@ Those (macros) don't use the underlying type field as everything was serialized Fields: ```cpp -CodeComment InlineCmt; -Code UnderlyingType; -StrCached Name; -Code Prev; -Code Next; -Token* Tok -Code Parent; -CodeT Type; -ModuleFlag ModuleFlags; -b32 IsFunction; +CodeComment InlineCmt; +Code UnderlyingType; +StrCached Name; +Code Prev; +Code Next; +Token* Tok +Code Parent; +CodeType Type; +ModuleFlag ModuleFlags; +b32 IsFunction; ``` Serialization: @@ -682,12 +705,12 @@ Fields: ```cpp CodeAttributes Attributes; CodeBody Body; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ModuleFlag ModuleFlags; ``` @@ -708,12 +731,12 @@ Fields: CodeComment InlineCmt; CodeAttributes Attributes; CodeType UnderlyingType; -StrCached Name; +StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ModuleFlag ModuleFlags; ``` @@ -740,13 +763,13 @@ CodeSpecifiers Specs; CodeType ValueType; Code BitfieldSize; Code Value; -StrCached Name; +StrCached Name; CodeVar NextVar; Code Prev; Code Next; Token* Tok; Code Parent; -CodeT Type; +CodeType Type; ModuleFlag ModuleFlags; s32 VarParenthesizedInit; ``` diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/LICENSE b/Project/Source/GasaEditor/GasaGen/gencpp/LICENSE index 90e47fc..3ce62f8 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/LICENSE +++ b/Project/Source/GasaEditor/GasaGen/gencpp/LICENSE @@ -26,3 +26,19 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Source URL: https://github.com/Ed94/gencpp + +Acknowledgements + +* The dependencies for gencpp source are derived from the zpl library: https://github.com/zpl-c/zpl + +Special thanks to: + +* The Handmade Community. + +* Casey Muratori, Ginger Bill (Bill Hall), Mr. 4th (Allen Webster), Ryan Fluery: Influnced conceptually how to handle staged metaprograming. + +* Jonathan Blow: Jai's metaprogramming influenced the design of this library. + +* My friends for putting up with discord spam on this library. diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/Parser_Algo.md b/Project/Source/GasaEditor/GasaGen/gencpp/Parser_Algo.md index 8180168..842eb2a 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/Parser_Algo.md +++ b/Project/Source/GasaEditor/GasaGen/gencpp/Parser_Algo.md @@ -12,7 +12,9 @@ gencpp uses a hand-written recursive descent parser. Both the lexer and parser c ### Lexer -The lex procedure does the lexical pass of content provided as a `Str` type. +File: [lexer.cpp](../base/components/lexer.cpp) + +The `lex` procedure does the lexical pass of content provided as a `Str` type. The tokens are stored (for now) in `Lexer_Tokens`. Fields: @@ -24,17 +26,15 @@ s32 Idx; What token types are supported can be found in [ETokType.csv](../base/enums/ETokType.csv) you can also find the token types in [ETokType.h](../base/components/gen/etoktype.cpp) , which is the generated enum from the csv file. -Tokens are defined with the struct `gen::parser::Token`: - -Fields: - ```cpp -char const* Text; -sptr Length; -TokType Type; -s32 Line; -s32 Column; -u32 Flags; +struct Token +{ + Str Text; + TokType Type; + s32 Line; + s32 Column; + u32 Flags; +} ``` Flags is a bitfield made up of TokFlags (Token Flags): @@ -52,25 +52,17 @@ Flags is a bitfield made up of TokFlags (Token Flags): * `TF_EndDefinition` : Can be interpreted as an end definition for a scope. * `TF_Formatting` : Considered a part of the formatting * `TF_Literal` : Anything considered a literal by C++. - -I plan to replace IsAssign with a general flags field and properly keep track of all operator types instead of abstracting it away to `ETokType::Operator`. - -Traversing the tokens is done with the following interface macros: - -| Macro | Description | -| --- | --- | -| `currtok_noskip` | Get the current token without skipping whitespace | -| `currtok` | Get the current token, skip any whitespace tokens | -| `prevtok` | Get the previous token (does not skip whitespace) | -| `nexttok` | Get the next token (does not skip whitespace) | -| `eat( Token Type )` | Check to see if the current token is of the given type, if so, advance Token's index to the next token | -| `left` | Get the number of tokens left in the token array | -| `check_noskip` | Check to see if the current token is of the given type, without skipping whitespace | -| `check` | Check to see if the current token is of the given type, skip any whitespace tokens | +* `TF_Macro_Functional` : Used to indicate macro token is flagged as `MF_Functional`. +* `TF_Macro_Expects_Body` : Used to indicate macro token is flagged as `MF_Expects_Body`. ### Parser -The parser has a limited user interface, only specific types of definitions or statements are expected to be provided by the user directly when using to construct an AST dynamically (See SOA for example). It however does attempt to provide capability to parse a full C/C++ from production codebases. +Files: + +* [interface.parsering.cpp](../base/components/interface.parsing.cpp) +* [parser.cpp](../base/components/parser.cpp) + +The parser has a limited user interface, only specific types of definitions or statements are expected to be provided by the user directly when using to construct an AST dynamically. It however does attempt to provide capability to parse a full C/C++ from production codebases. Each public user interface procedure has the following format: @@ -89,8 +81,7 @@ Each public user interface procedure has the following format: } ``` -The most top-level parsing procedure used for C/C++ file parsing is `parse_global_body`: - +The most top-level parsing procedure used for C/C++ file parsing is `parse_global_body`. It uses a helper procedure called `parse_global_nspace`. Each internal procedure will have the following format: @@ -111,126 +102,300 @@ internal } ``` +The parsing implementation contains throughut the codeapths to indicate how far their contextual AST node has been resolved. + +Example: + +```c +internal +CodeFn parser_parse_function() +{ + push_scope(); + + Specifier specs_found[16] = { Spec_NumSpecifiers }; + s32 NumSpecifiers = 0; + + CodeAttributes attributes = { nullptr }; + CodeSpecifiers specifiers = { nullptr }; + ModuleFlag mflags = ModuleFlag_None; + + if ( check(Tok_Module_Export) ) { + mflags = ModuleFlag_Export; + eat( Tok_Module_Export ); + } + // + + attributes = parse_attributes(); + // + + while ( left && tok_is_specifier(currtok) ) + { + Specifier spec = str_to_specifier( tok_to_str(currtok) ); + + switch ( spec ) + { + GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES: + break; + + default: + log_failure( "Invalid specifier %S for functon\n%SB", spec_to_str(spec), parser_to_strbuilder(_ctx->parser) ); + parser_pop(& _ctx->parser); + return InvalidCode; + } + + if ( spec == Spec_Const ) + continue; + + specs_found[NumSpecifiers] = spec; + NumSpecifiers++; + eat( currtok.Type ); + } + + if ( NumSpecifiers ) { + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); + } + // + + CodeTypename ret_type = parser_parse_type(parser_not_from_template, nullptr); + if ( cast(Code, ret_type) == Code_Invalid ) { + parser_pop(& _ctx->parser); + return InvalidCode; + } + // + + Token name = parse_identifier(nullptr); + _ctx->parser.Scope->Name = name.Text; + if ( ! tok_is_valid(name) ) { + parser_pop(& _ctx->parser); + return InvalidCode; + } + // + + CodeFn result = parse_function_after_name( mflags, attributes, specifiers, ret_type, name ); + // ... + + parser_pop(& _ctx->parser); + return result; +} +``` + +In the above `parse_function` implementation: + +`// ...` + +Will be conventionlly used where by that point in time for the codepath: `` should be resolved for the AST. + +## Outline of parsing codepaths + Below is an outline of the general alogirithim used for these internal procedures. The intention is to provide a basic briefing to aid the user in traversing the actual code definitions. These appear in the same order as they are in the `parser.cpp` file ***NOTE: This is still heavily in an alpha state. A large swaph of this can change, make sure these docs are up to date before considering them 1:1 with the repo commit your considering.*** ## `parse_array_decl` -1. Check if its an array declaration with no expression. - 1. Consume and return empty array declaration -2. Opening square bracket -3. Consume expression -4. Closing square bracket -5. If adjacent opening bracket - 1. Repeat array declaration parse until no brackets remain - -## `parse_assignment_expression` - -1. Eat the assignment operator -2. Make sure there is content or at least an end statement after. -3. Flatten the assignment expression to an untyped Code string. +1. Push parser scope +2. Check for empty array `[]` + 1. Return untyped string with single space if found +3. Check for opening bracket `[` + 1. Validate parser not at EOF + 2. Reject empty array expression + 3. Capture expression tokens until closing bracket + 4. Calculate expression span length + 5. Convert to untyped string +4. Validate and consume closing bracket `]` +5. Handle multi-dimensional case + 1. If adjacent `[` detected, recursively parse + 2. Link array expressions via Next pointer +6. Pop parser scope +7. Return array expression or NullCode on failure ## `parse_attributes` -1. Check for standard attribute -2. Check for GNU attribute -3. Check for MSVC attribute -4. Check for a token registered as an attribute - a. Check and grab the arguments of a token registered of an attribute if it has any. -5. Repeat for chained attributes. Flatten them to a single attribute AST node. +1. Push parser scope and initialize tracking + 1. Store initial token position + 2. Initialize length counter +2. Process attributes while available + 1. Handle C++ style attributes `[[...]]` + 1. Consume opening `[[` + 2. Capture content until closing `]]` + 3. Calculate attribute span length + 2. Handle GNU style `__attribute__((...))` + 1. Consume `__attribute__` keyword and opening `((` + 2. Capture content until closing `))` + 3. Calculate attribute span length + 3. Handle MSVC style `__declspec(...)` + 1. Consume `__declspec` and opening `(` + 2. Capture content until closing `)` + 3. Calculate attribute span length + 4. Handle macro-style attributes + 1. Consume attribute token + 2. If followed by parentheses + 1. Handle nested parentheses tracking + 2. Capture content maintaining paren balance + 3. Calculate attribute span length +3. Generate attribute code if content captured + 1. Create attribute text span from start position and length + 2. Strip formatting from attribute text + 3. Construct Code node + 1. Set type to `CT_PlatformAttributes` + 2. Cache and set Name and Content fields + 4. Return as CodeAttributes +4. Pop parser scope +5. Return NullCode if no attributes found ## `parse_class_struct` -1. Check for export module specifier -2. class or struct keyword -3. `parse_attributes` -4. If identifier : `parse_identifier` -5. Parse inherited parent or interfaces -6. If opening curly brace : `parse_class_struct_body` -7. If not an inplace definition - 1. End statement - 2. Check for inline comment +1. Validate token type is class or struct + 1. Return InvalidCode if validation fails +2. Initialize class/struct metadata + 1. Access specifier (default) + 2. Parent class/struct reference + 3. Class/struct body + 4. Attributes + 5. Module flags +3. Parse module export flag if present + 1. Set ModuleFlag_Export + 2. Consume export token +4. Consume class/struct token +5. Parse attributes via `parse_attributes()` +6. Parse class/struct identifier + 1. Update parser scope name +7. Initialize interface array (4KB arena) +8. Parse inheritance/implementation + 1. If classifier token (`:`) present + 1. Parse access specifier if exists + 2. Parse parent class/struct name + 3. Parse additional interfaces + 1. Separated by commas + 2. Optional access specifiers + 3. Store in interface array +9. Parse class body if present + 1. Triggered by opening brace + 2. Parse via `parse_class_struct_body` +10. Handle statement termination + 1. Skip for inplace definitions + 2. Consume semicolon + 3. Parse inline comment if present +11. Construct result node + 1. Create class definition if Tok_Decl_Class + 2. Create struct definition if Tok_Decl_Struct + 3. Attach inline comment if exists +12. Cleanup interface array and return result ## `parse_class_struct_body` -1. Opening curly brace -2. Parse the body (Possible options): - 1. Ignore dangling end statements - 2. Newline : ast constant - 3. Comment : `parse_comment` - 4. Access_Public : ast constant - 5. Access_Protected : ast constant - 6. Access_Private : ast constant - 7. Decl_Class : `parse_complicated_definition` - 8. Decl_Enum : `parse_complicated_definition` - 9. Decl_Friend : `parse_friend` - 10. Decl_Operator : `parse_operator_cast` - 11. Decl_Struct : `parse_complicated_definition` - 12. Decl_Template : `parse_template` - 13. Decl_Typedef : `parse_typedef` - 14. Decl_Union : `parse_complicated_definition` - 15. Decl_Using : `parse_using` - 16. Operator == '~' - 1. `parse_destructor` - 17. Preprocess_Define : `parse_define` - 18. Preprocess_Include : `parse_include` - 19. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif) : `parse_preprocess_cond` or else/endif ast constant - 20. Preprocess_Macro : `parse_simple_preprocess` - 21. Preprocess_Pragma : `parse_pragma` - 22. Preprocess_Unsupported : `parse_simple_preprocess` - 23. StaticAssert : `parse_static_assert` - 24. The following compound into a resolved definition or declaration: - 1. Attributes (Standard, GNU, MSVC) : `parse_attributes` - 2. Specifiers (consteval, constexpr, constinit, explicit, forceinline, inline, mutable, neverinline, static, volatile, virtual) - 3. Possible Destructor : `parse_destructor` - 4. Possible User defined operator cast : `parse_operator_cast` - 5. Possible Constructor : `parse_constructor` - 6. Something that has the following: (identifier, const, unsigned, signed, short, long, bool, char, int, double) - 1. Possible Constructor `parse_constructor` - 2. Possible Operator, Function, or varaible : `parse_operator_function_or_variable` - 25. Something completely unknown (will just make untyped...) : `parse_untyped` +1. Initialize scope and body structure + 1. Push parser scope + 2. Consume opening brace + 3. Create code node with `CT_Class_Body` or `CT_Struct_Body` type +2. Parse body members while not at closing brace + 1. Initialize member parsing state + 1. Code member (InvalidCode) + 2. Attributes (null) + 3. Specifiers (null) + 4. Function expectation flag + 2. Handle preprocessor hash if present + 3. Process member by token type in switch statement + 1. Statement termination - warn and skip + 2. Newline - format member + 3. Comments - parse comment + 4. Access specifiers - `public/protected/private` + 5. Declarations - `class/enum/struct/union/typedef/using` + 6. Operators - `destructors/casts` + 7. Preprocessor directives - `define/include/conditionals/pragmas` + 8. Preprocessor statement macros + 9. Report naked preprocossor expression macros detected as an error. + 10. Static assertions + 11. Attributes and specifiers + 1. Parse attributes + 2. Parse valid member specifiers + 3. Handle `attribute-specifier-attribute` case + 12. Identifiers and types + 1. Check for constructors + 2. Parse `operator/function/variable` + 13. Default - capture unknown content until closing brace + 4. Validate member parsing + 1. Return InvalidCode if member invalid + 2. Append valid member to body +3. Finalize body + 1. Consume closing brace + 2. Pop parser scope + 3. Return completed CodeBody ## `parse_comment` 1. Just wrap the token into a cached string ( the lexer did the processing ) -## `parse_compilcated_definition` +## `parse_complicated_definition` -This is a helper function used by the following functions to help resolve a declaration or definition: +1. Initialize parsing context + 1. Push scope + 2. Set inplace flag false + 3. Get token array reference +2. Scan ahead for statement termination + 1. Track brace nesting level + 2. Find first semicolon at level 0 +3. Handle declaration variants + 1. Forward declaration case + 1. Check if only 2 tokens before semicolon + 2. Parse via `parse_forward_or_definition` + 2. Function with trailing specifiers + 1. Identify trailing specifiers + 2. Check for function pattern + 3. Parse as `operator/function/variable` + 4. Return `InvalidCode` if pattern invalid + 3. Identifier-based declarations + 1. Check identifier patterns + 1. Inplace definition `{...} id;` + 2. Namespace type variable `which id id;` + 3. Enum with class qualifier + 4. `Pointer/reference` types + 2. Parse as `operator/function/variable` if valid + 3. Return `InvalidCode` if pattern invalid + 4. Basic type declarations + 1. Validate enum class pattern + 2. Parse via `parser_parse_enum` + 3. Return `InvalidCode` if invalid + 5. Direct definitions + 1. Handle closing brace - `parse_forward_or_definition` + 2. Handle array definitions - `parse_operator_function_or_variable` + 3. Return InvalidCode for unknown patterns -* `parse_class_struct_body` -* `parse_global_nspace` -* `parse_union` +## `parse_assignment_expression` -A portion of the code in `parse_typedef` is very similar to this as both have to resolve a similar issue. - -1. Look ahead to the termination token (End statement) -2. Check to see if it fits the pattern for a forward declare -3. If the previous token was an identifier ( `token[-1]` ): - 1. Look back one more token : `[-2]` - 2. If the token has a closing brace its an inplace definition - 3. If the `token[-2]` is an identifier & `token[-3]` is the declaration type, its a variable using a namespaced type. - 4. If the `token[-2]` is an indirection, then its a variable using a namespaced/forwarded type. - 5. If the `token[-2]` is an assign classifier, and the starting tokens were the which type with possible `class` token after, its an enum forward declaration. - 6. If any of the above is the case, `parse_operator_function_or_variable` -4. If the `token[2]` is a vendor fundamental type (builtin) then it is an enum forward declaration. -5. If the previous token was a closing curly brace, its a definition : `parse_forward_or_definition` -6. If the previous token was a closing square brace, its an array definition : `parse_operator_function_or_variable` - -## `parse_define` - -1. Define directive -2. Get identifier -3. Get Content (Optional) +1. Initialize expression parsing + 1. Null expression pointer + 2. Consume assignment operator token + 3. Capture initial expression token +2. Validate expression presence + 1. Check for immediate termination + 2. Return `InvalidCode` if missing expression +3. Parse balanced expression + 1. Track nesting level for + 1. Curly braces + 2. Parentheses + 2. Continue until + 1. End of input, or + 2. Statement terminator, or + 3. Unnested comma + 3. Consume tokens sequentially +4. Generate expression code + 1. Calculate expression span length + 2. Convert to untyped string + 3. Return expression node ## `parse_forward_or_definition` -* Parse any of the following for either a forward declaration or definition: - 1. Decl_Class : `parse_class` - 2. Decl_Enum : `parse_enum` - 3. Decl_Struct : `parse_struct` - 4. Decl_Union : `parse_union` +1. Declaration type routing + 1. Class (`Tok_Decl_Class`) -> `parser_parse_class` + 2. Enum (`Tok_Decl_Enum`) -> `parser_parse_enum` + 3. Struct (`Tok_Decl_Struct`) -> `parser_parse_struct` + 4. Union (`Tok_Decl_Union`) -> `parser_parse_union` +2. Error handling + 1. Return `InvalidCode` for unsupported token types + 2. Log failure with parser context + +`is_inplace` flag propagates to specialized codepaths to maintain parsing context. ## `parse_function_after_name` @@ -239,80 +404,189 @@ after its been made ceratin that the type of declaration or definition is indeed By the point this function is called the following are known : export module flag, attributes, specifiers, return type, & name -1. `parse_parameters` -2. parse postfix specifiers (we do not check if the specifier here is correct or not to be here... yet) -3. If there is a body : `parse_body` -4. Otherwise : - 1. Statment end - 2. Check for inline comment +1. Parameter parsing + 1. Push scope + 2. Parse parameter list with parentheses +2. Post-parameter specifier processing + 1. Collect trailing specifiers + 2. Initialize or append to existing specifiers +3. Parse function termination + 1. Function body case + 1. Parse body if open brace found + 2. Validate body type (`CT_Function_Body` or `CT_Untyped`) + 2. Pure virtual case + 1. Handle "`= 0`" syntax + 2. Append pure specifier + 3. Forward declaration case + 1. Consume statement terminator + 4. Handle inline comments for all cases +4. Construct function node + 1. Strip whitespace from name + 2. Initialize `CodeFn` with base properties + 1. Name (cached, stripped) + 2. Module flags + 3. Set node type + 1. `CT_Function` if body present + 2. `CT_Function_Fwd` if declaration only + 4. Attach components + 1. Attributes if present + 2. Specifiers if present + 3. Return type + 4. Parameters if present + 5. Inline comment if present +5. Cleanup and return + 1. Pop scope + 2. Return completed function node ## `parse_function_body` Currently there is no actual parsing of the function body. Any content with the braces is shoved into an execution AST node. In the future statements and expressions will be parsed. -1. Open curly brace -2. Grab all tokens between the brace and the closing brace, shove them in a execution AST node. -3. Closing curly brace +1. Initialize body parsing + 1. Push scope + 2. Consume opening brace + 3. Create CodeBody with CT_Function_Body type +2. Capture function content + 1. Record start token position + 2. Track brace nesting level + 3. Consume tokens while + 1. Input remains AND + 2. Not at unmatched closing brace + 4. Update level counters + 1. Increment on open brace + 2. Decrement on closing brace when level > 0 +3. Process captured content + 1. Calculate content length via pointer arithmetic + 2. Create execution block if content exists + 1. Construct string span from start position and length + 2. Wrap in execution node + 3. Append to body +4. Finalize + 1. Consume closing brace + 2. Pop scope + 3. Return cast body node ## `parse_global_nspace` -1. Make sure this is being called for a valid type (namespace, global body, export body, linkage body) -2. If its not a global body, consume the opening curly brace -3. Parse the body (Possible options): - 1. Ignore dangling end statements - 2. NewLine : ast constant - 3. Comment : `parse_comment` - 4. Decl_Cass : `parse_complicated_definition` - 5. Decl_Enum : `parse_complicated_definition` - 6. Decl_Extern_Linkage : `parse_extern_link` - 7. Decl_Namespace : `parse_namespace` - 8. Decl_Struct : `parse_complicated_definition` - 9. Decl_Template : `parse_template` - 10. Decl_Typedef : `parse_typedef` - 11. Decl_Union : `parse_complicated_definition` - 12. Decl_Using : `parse_using` - 13. Preprocess_Define : `parse_define` - 14. Preprocess_Include : `parse_include` - 15. Preprocess_If, IfDef, IfNotDef, Elif : `parse_preprocess_cond` - 16. Preprocess_Else : ast constant - 17. Preprocess_Endif : ast constant - 18. Preprocess_Macro : `parse_simple_preprocess` - 19. Preprocess_Pragma : `parse_pragma` - 20. Preprocess_Unsupported : `parse_simple_preprocess` - 21. StaticAssert : `parse_static_assert` - 22. Module_Export : `parse_export_body` - 23. Module_Import : NOT_IMPLEMENTED - 24. The following compound into a resolved definition or declaration: - 1. Attributes ( Standard, GNU, MSVC, Macro ) : `parse_attributes` - 2. Specifiers ( consteval, constexpr, constinit, extern, forceinline, global, inline, internal_linkage, neverinline, static ) - 3. Is either ( identifier, const specifier, long, short, signed, unsigned, bool, char, double, int) - 1. Attempt to parse as construtor or destructor : `parse_global_nspace_constructor_destructor` - 2. If its an operator cast (definition outside class) : `parse_operator_cast` - 3. Its an operator, function, or varaible : `parse_operator_function_or_varaible` -4. If its not a global body, consume the closing curly brace +1. State initialization + 1. Push parser scope + 2. Validate namespace type (Global, Namespace, Export, Extern Linkage) + 3. Consume opening brace for non-global scopes + 4. Initialize `CodeBody` with specified body type: `which` +2. Member parsing loop (while not at closing brace) + 1. Reset parse state + * Member code + * Attributes + * Specifiers + * Function expectation flag + 2. Member type handling + 1. Declarations + * `Class/Struct/Union/Enum` via `parse_complicated_definition` + * `Template/Typedef/Using` via dedicated parsers + * `Namespace/Export/Extern` declarations + 2. Preprocessor directivess + * Include/Define + * Conditionals `(if / ifdef / ifndef / elif / else / endif)` + * Pragmas + * Preprocessor statement macros + * Report naked preprocossor expression macros detected as an error. + 3. Comments/Formatting + * Newlines + * Comments + 4. Static assertions + 3. Attributes and specifiers + 1. Parse attributes if present + 2. Collect valid specifiers (max 16) + 3. Handle `consteval` for function expectation + 4. Identifier resolution + 1. Check `constructor/destructor` implementation + 2. Look ahead for user defined operator implementation outside of class + 3. Default to `operator/function/variable` parse +3. Member validation/storage + 1. Validate parsed member + 2. Append to body if valid + 3. Return `InvalidCode` on parse failure +4. Scope finalization + 1. Consume closing brace for non-global scopes + 2. Pop parser scope + 3. Return completed body ## `parse_global_nspace_constructor_destructor` -1. Look ahead for the start of the arguments for a possible constructor/destructor -2. Go back past the identifier -3. Check to see if its a destructor by checking for the `~` -4. Continue the next token should be a `::` -5. Determine if the next valid identifier (ignoring possible template parameters) is the same as the first identifier of the function. -6. If it is we have either a constructor or destructor so parse using their respective functions (`parse_constructor`, `parse_destructor`). +1. Forward Token Analysis + 1. Scan for parameter list opening parenthesis + 2. Template Expression Handling + * Track template nesting depth + * Account for nested parentheses within templates + * Skip until template closure or parameter start + +```cpp + // Valid patterns: + ClassName :: ClassName(...) + ClassName :: ~ClassName(...) + ClassName< T ... > :: ClassName(...) +``` + +2. Constructor/Destructor Identification + 1. Token Validation Sequence + * Verify identifier preceding parameters + * Check for destructor indicator (`~`) + * Validate scope resolution operator (`::`) + 2. Left-side Token Analysis + * Process nested template expressions + * Maintain template/capture level tracking + * Locate matching identifier token +3. Parser Resolution + 1. Name Pattern Validation + * Compare identifier tokens for exact match + 2. Specialized Parsing + * Route to `parser_parse_destructor` for '~' prefix + * Route to `parser_parse_constructor` for direct match + 3. Apply specifiers to resulting node +4. Return result (`NullCode` on pattern mismatch) + +### Implementation Constraints + +* Cannot definitively distinguish nested namespaces with identical names +* Return type detection requires parser enhancement +* Template parameter validation is syntax-based only +* Future enhancement: Implement type parsing with rollback capability ## `parse_identifier` This is going to get heavily changed down the line to have a more broken down "identifier expression" so that the qualifier, template args, etc, can be distinguished between the targeted identifier. The function can parse all of them, however the AST node compresses them all into a string. -1. Consume first identifier -2. `parse_template_args` -3. While there is a static symbol accessor ( `::` ) - 1. Consume `::` - 2. Consume member identifier - 3. `parse_template args` (for member identifier) - 4. If a `~` is encounted and the scope is for a destructor's identifier, do not consume it and return with what parsed. +1. Initialize identifier context + 1. Push parser scope + 2. Capture initial token as name + 3. Set scope name from token text +2. Process initial identifier component + 1. Consume identifier token + 2. Parse template arguments if present +3. Handle qualified identifiers (loop while `::` found) + 1. Consume static access operator + 2. Validate token sequence: + 1. Handle destructor operator (`~`) + * Validate destructor parsing context + * Update name span if valid + * Return invalid on context mismatch + 2. Process member function pointer (`*`) + * Set possible_member_function flag if context allows + * Return invalid if pointer unexpected + 3. Verify identifier token follows + 3. Update identifier span + 1. Extend name length to include new qualifier + 2. Consume identifier token + 3. Parse additional template arguments +4. Return completed identifier token + +Notes: + +* Current implementation treats identifier as single token span +* TODO: Refactor to AST-based identifier representation for: + * Better support for nested symbol resolution ## `parse_include` @@ -323,29 +597,100 @@ The function can parse all of them, however the AST node compresses them all int This is needed as a operator defintion is not easily resolvable early on, as such this function handles resolving a operator after its been made ceratin that the type of declaration or definition is indeed for a operator signature. -By the point this function is called the following are known : export module flag, attributes, specifiers, return type +By the point this function is called the following are known : export module flag, attributes, specifiers, and return type -1. If there is any qualifiers for the operator, parse them -2. Consume operator keyword -3. Determine the operator type (This will be offloaded to the lexer moreso than how it is now) & consume -4. `parse_params` -5. If there is no parameters this is operator is a member of pointer if its symbols is a *. -6. Parse postfix specifiers -7. If there is a opening curly brace, `parse function_body` -8. Otherwise: consume end statement, check for inline comment. +1. Initialize operator context + 1. Push scope + 2. Parse qualified namespace identifier + 3. Consume `operator` keyword +2. Operator identification + 1. Validate operator token presence + 2. Set scope name from operator token + 3. Map operator token to internal operator enum: + * Arithmetic: `+, -, *, /, %` + * Assignment: `+=, -=, *=, /=, %=, =` + * Bitwise: `&, |, ^, ~, >>` + * Logical: `&&, ||, !, ==` + * Comparison: `<, >, <=, >=` + * Member access: `->, ->*` + * Special: `(), [], new, delete` + 4. Handle array variants for new/delete +3. Parameter and specifier processing + 1. Parse parameter list + 2. Handle multiply/member-pointer ambiguity + 3. Collect trailing specifiers + 4. Merge with existing specifiers +4. Function body handling + 1. Parse implementation if present + 2. Otherwise consume statement terminator + 3. Capture inline comments +5. Result construction + 1. Create operator node with: + * Operator type + * Namespace qualification + * Parameters + * Return type + * Implementation body + * Specifiers + * Attributes + * Module flags + 2. Attach inline comments +6. Pop scope ## `parse_operator_function_or_variable` When this function is called, attribute and specifiers may have been resolved, however what comes next can still be either an operator, function, or varaible. -1. Check for preprocessor macro, if there is one : `parse_simple_preprocess` -2. `parse_type` (Does the bulk of the work) -3. Begin lookahead to see if we get qualifiers or we eventually find the operator declaration -4. If we find an operator keyword : `parse_operator_after_ret_type` -5. otherwise : - 1. `parse_identifier` - 2. If we se a opening parenthesis (capture start), its a function : `parse_function_after_name` - 3. Its a variable : `parse_variable_after_name` +1. Initial Type Resolution + 1. Push parsing scope + 2. Handle macro definitions via `parse_macro_as_definition` + 3. Parse base type, validate result + 4. Exit on invalid type +2. Declaration Classification + 1. Scan token stream for `operator` keyword + 2. Track static symbol access + 3. Branch handling: + * Operator overload: Forward to `parse_operator_after_ret_type` + * Function/variable: Parse identifier and analyze context +3. Function/Variable Disambiguation + 1. Parse identifier + 2. Analyze token patterns: + * Detect parameter capture via parenthesis + * Check for constructor initialization pattern + * Handle variadic argument cases + 3. Macro Expression Analysis: + * Validate functional macros + * Track parenthesis balance + * Detect comma patterns +4. Declaration Parsing + 1. Function path + * Verify function expectation (`consteval`) + * Delegate to `parse_function_after_name` + 2. Variable path + * Validate against function expectation + * Forward to `parse_variable_after_name` + +## `parse_macro_as_definition` + +1. Validation + 1. Check token type (Tok_Preprocess_Macro_Stmt) + 2. Retrieve macro from lookup + 3. Verify `MF_Allow_As_Definition` flag +2. Macro Processing + 1. Parse via `parse_simple_preprocess` + 2. Maintain original token categorization +3. Definition Construction + 1. Format components: + * Attributes (if present) + * Specifiers (if present) + * Macro content + 2. Build unified string representation + 3. Convert to untyped code node + +Notes: + +* Early exits return NullCode for non-qualifying macros +* TODO: Pending AST_Macro implementation for proper attribute/specifier support ## `parse_pragma` @@ -354,21 +699,38 @@ When this function is called, attribute and specifiers may have been resolved, h ## `parse_params` -1. Consume either a `(` or `<` based on `use_template_capture` arg -2. If the we immdiately find a closing token, consume it and finish. -3. If we encounter a varadic argument, consume it and return a `param_varadic` ast constant -4. `parse_type` -5. If we have a macro, parse it (Unreal has macros as tags to parameters and or as entire arguments). -6. So long as next token isn't a comma - a. If we have an identifier - 1. Consume it - 2. Check for assignment: - a. Consume assign operator - b. Parse the expression -7. While we continue to encounter commas - a. Consume them - b. Repeat steps 3 to 6.2.b -8. Consume the closing token +1. Parameter List Initialization + 1. Delimiter handling based on context + * Parentheses: `(...)` for standard parameters + * Angle brackets: `<...>` for template parameters + 2. Early return for empty parameter lists + 3. Initial parameter component initialization + * Macro reference + * Type information + * Parameter value + * Identifier token +2. Primary Parameter Processing + 1. Handle varadic arguments + 2. Process preprocessor macros (`UPARAM` style) + 3. Parse parameter sequence + * Type information + * Optional identifier + * Post-name macro expressions + * Default value expressions + 4. Value expression capture with nested structure tracking + * Template depth counting + * Parentheses balance + * Text span calculation +3. Multi-Parameter Handling + 1. Parse comma-separated entries + 2. Maintain parameter structure + * Macro context + * Type information + * Identifier caching + * Post-name macro persistence + * Value assignments + 3. Parameter list construction via `params_append` +4. Consume params capture termination token & return result. ## `parse_preprocess_cond` @@ -377,18 +739,40 @@ When this function is called, attribute and specifiers may have been resolved, h ## `parse_simple_preprocess` -There is still decent room for improvement in this setup. Right now the entire macro's relevant tokens are shoved into an untyped AST. It would be better to store it instead in an `AST_Macro` node instead down the line. +1. Basic Setup + 1. Push scope + 2. Capture initial macro token + 3. Validate macro registration + * Lookup in macro registry + * Skip validation for unsupported macros +2. Functional Macro Processing + 1. Handle macro invocation + * Parse opening parenthesis + * Track nested parenthesis level + * Capture parameter content + * Update macro span length +3. Macro Body Handling + 1. Process associated block if macro expects body + * Parse curly brace delimited content + * Track nesting level + * Capture body content + 2. Handle statement termination + * Context-specific semicolon handling + * Process inline comments + * Update macro span +4. Context-Specific Termination + 1. Special case handling + * Enum context bypass + * Typedef context validation + * Global/class scope handling + 2. Statement termination rules + * Process semicolons based on context + * Update token span accordingly -1. Consume the macro token -2. Check for an opening curly brace - 1. Consume opening curly brace - 2. Until the closing curly is encountered consume all tokens. - 3. If the parent context is a typedef - 1. Check for end stement - 1. Consume it - 2. Consume potential inline comment -3. Otherwise do steps 3 to 3.1.2 -4. Shove it all in an untyped string +Notes: + +* Pending AST_Macro implementation for improved structure +* Current implementation uses simple token span capture ## `parse_static_assert` @@ -408,127 +792,244 @@ This will get changed heavily once we have better support for typename expressio ## `parse_variable_after_name` -This is needed as a variable defintion is not easily resolvable early on, it takes a long evaluation period before its known that the declaration or definition is a variable. As such this function handles resolving a variable. - +This is needed as a variable defintion is not easily resolvable early on, it takes a long evaluation period before its known that the declaration or definition is a variable. As such this function handles resolving a variable. By the point this function is called the following are known : export module flag, attributes, specifiers, value type, name -1. If its an assignment, parse the assignment expression (currently to an untyped string) -2. If its an opening curly brace, parse the expression within (currnelty to an untyped stirng). - 1. Consume the closing curly brace -3. If its a `:`, we're dealing with bitfield definition: - 1. Consume the assign classifier - 2. Consume the expression (currently to an untyped string) -4. If a comma is encountered : `parse_variable declaration_list` -5. Consume statement end -6. Check for inline comment +1. Initialization Processing + 1. Array dimension parsing + 2. Expression capture + * Assignment expressions + * Constructor initializations + * Bitfield specifications +2. Expression Pattern Handling + 1. Direct assignment (`=`) + * Parse assignment expression + 2. Brace initialization (`{}`) + * Track nested braces + * Capture initialization list + 3. Constructor initialization (`()`) + * Track parenthesis nesting + * Update initialization flag + 4. Bitfield specification (`:`) + * Validate non-empty expression + * Capture bitfield size +3. Multi-Variable Processing + 1. Handle comma-separated declarations + 2. Statement termination + * Process semicolon + * Capture inline comments + 3. Link variable chain via NextVar +4. AST Node Construction + 1. Core properties + * Type (`CT_Variable`) + * Name caching + * Module flags + * Value type + 2. Optional components + * Array expression + * Bitfield size + * Attributes/Specifiers + * Initialization value + * Constructor flag + * Parent/Next linkage ## `parse_variable_declaration_list` -1. Consume the comma -2. Parse specifiers -3. `parse_variable_after_name` +1. Chain Initialization + 1. Initialize null variable chain head and tail + 2. Process while comma token present +2. Per-Variable Processing + 1. Specifier Collection + * Validate specifier ordering (const after pointer) + * Handle core specifiers: `ptr, ref, rvalue` + * Maintain specifier chain integrity + * Log invalid specifier usage but continue parsing + 2. Variable Declaration + * Extract identifier name + * Parse remainder via `parse_variable_after_name` + * Note: Function pointers unsupported +3. Chain Management + 1. First Variable + * Set as chain head and tail + 2. Subsequent Variables + * Link to previous via NextVar + * Establish parent reference + * Update tail pointer -## `parse_class` +Limitations: + +* No function pointer support + +## `parser_parse_class` 1. `parse_class_struct` -## `parse_constructor` +## `parser_parse_constructor` -This currently doesn't support postfix specifiers (planning to in the future) +1. Core Parse Sequence + 1. Identifier extraction and parameter list capture + 2. Handle construction variants: + * Colon-prefixed member initializer lists + * Direct body implementation + * Default/delete assignment forms + * Forward declarations +2. Initializer List Processing + 1. Track nested parentheses balance + 2. Capture full initializer span + 3. Convert to untyped string representation +3. Implementation Variants + 1. Body implementation + * Parse full function body + * Set `CT_Constructor` type + 2. Forward declaration + * Process terminator and comments + * Set `CT_Constructor_Fwd` type + 3. Special forms + * Handle assignment operator cases + * Capture inline comments for declarations +4. AST Construction + 1. Core node attributes + * Cached identifier name + * Parameter list linkage + * Specifier chain + 2. Optional components + * Initializer list + * Implementation body + * Inline comments -1. `parse_identifier` -2. `parse_parameters` -3. If currtok is a `:` - 1. Consume `:` - 2. Parse the initializer list - 3. `parse_function_body` -4. If currtok is an opening curly brace - 1. `parse_function_body` -5. Otherwise: - 1. Consume statement end - 2. Check for inline comment +## `parser_parse_define` -## `parse_destructor` +1. Token Stream Preparation + 1. Handle optional preprocessor hash + 2. Consume define directive + 3. Validate identifier presence +2. Define Node Initialization + 1. Construct CodeDefine with `CT_Preprocess_Define` type + 2. Cache identifier name + 3. Update scope context +3. Parameter Processing (Functional Macros) + 1. Initial parameter detection + * Verify macro functionality + * Initialize parameter list node (`CT_Parameters_Define`) + 2. Parameter chain construction +4. Content Handling + 1. Content validation + * Verify presence + * Handle empty content case with newline + 2. Content processing + * Strip formatting + * Preserve line termination + * Create untyped node -1. Check for and consume virtual specifier -2. Check for the `~` operator -3. `parse_identifier` -4. Consume opening and closing parenthesis -5. Check for assignment operator: - 1. Consume assignment op - 2. Consume pure specifier `0` -6. If not pure virtual & currtok is opening curly brace: - 1. `parse_function_body` -7. Otherwise: - 1. Consume end statement - 2. If currtok is comment : `parse_comment` +## `parser_parse_destructor` -## `parse_enum` +1. Context Validation + 1. Verify parser scope hierarchy + 2. Check global namespace context + 3. Process `virtual` specifier if present +2. Identifier Resolution + 1. Parse prefix identifier in global scope + 2. Validate destructor operator (`~`) + 3. Capture destructor name + 4. Enforce empty parameter list +3. Specifier Processing + 1. Handle pure virtual case (`= 0`) + * Append `Spec_Pure` to specifiers + * Set `pure_virtual` flag + 2. Process default specifier (= default) + * Parse as assignment expression + 3. Validate specifier syntax +4. Implementation Processing + 1. Function body (non-pure case) + * Parse complete body + * Set `CT_Destructor` type + 2. Forward declaration + * Handle statement termination + * Process inline comments + * Set `CT_Destructor_Fwd` type +5. AST Construction + 1. Build destructor node + 2. Handle qualified names + * Concatenate prefix and identifier + 3. Attach components + * Specifiers + * Implementation body + * Inline comments -1. Consume enum token -2. Check for and consume class token -3. `parse_attributes` -4. If there is an identifier consume it -5. Check for a `:` - 1. Consume `:` - 2. `parse_type` -6. If there is a body parse it (Consume `{`): - 1. Newline : ast constant - 2. Comment : `parse_comment` - 3. Preprocess_Define : `parse_define` - 4. Preprocess_Conditional (if, ifdef, ifndef, elif ) : `parse_preprocess_cond` - 5. Preprocess_Else : ast constant - 6. Preprocess_Endif : ast constant - 7. Preprocess_Macro : `parse_simple_preprocess` - 8. Preprocess_Pragma : `parse_pragma` - 9. Preprocess_Unsupported : `parse_smple_preprocess` - 10. An actual enum entry - 1. Consume identifier - 2. If there is an assignment operator: - 1. Consume operator - 2. Consume the expression (assigned to untyped string for now) - 3. If a macro is encountered consume it (Unreal UMETA macro support) - 3. If there is a comma, consume it +## `parser_parse_enum` -## `parse_export_body` +1. Declaration Components + 1. Basic structure processing + * Enum type detection (`enum/enum class`) + * Attributes parsing + * Identifier capture + 2. Underlying type resolution + * Standard type parsing + * Macro-based underlying type handling + * Classifier token validation +2. Body Processing + 1. Entry parsing loop + * Preprocessor directives (`#define, #if, #pragma`) + * Enum member declarations + * Comment preservation + * Formatting tokens + 2. Entry value handling + * Assignment expressions + * `UMETA` macro support + * Entry termination (commas) + 3. Token span calculation for entries +3. AST Construction + 1. Node type determination + * `CT_Enum/CT_Enum_Class` for definitions + * `CT_Enum_Fwd/CT_Enum_Class_Fwd` for declarations + 2. Component attachment + * Name caching + * Body linkage + * Underlying type/macro + * Attributes + * Inline comments + +## `parser_parse_export_body` 1. `parse_global_nspace` -## `parse_extern_link_body` +## `parser_parse_extern_link_body` 1. `parse_global_nspace` -## `parse_extern_link` +## `parser_parse_extern_link` -1. Consume Decl_Extern_Linkage +1. Consume `Tok_Decl_Extern_Linkage` 2. Consume the linkage identifier 3. `parse_extern_link_body` -## `parse_friend` +## `parser_parse_friend` 1. Consume `friend` -2. `parse_type` -3. If the currok is an identifier its a function declaration or definition +2. Parse specifiers +3. `parse_type` +4. If the currok is an identifier its a function declaration or definition 1. `parse_function_after_name` -4. Consume end statement so long as its not a function definion -5. Check for inline comment, `parse_comment` if exists +5. Otherwise its a operator: `parse_operator_after_ret_type` +6. Consume end statement so long as its not a function definion +7. Check for inline comment, `parse_comment` if exists -## `parse_function` +## `parser_parse_function` 1. Check and parse for `export` 2. `parse_attributes` 3. Parse specifiers -4. `parse_type` +4. `parse_type` for return type 5. `parse_identifier` 6. `parse_function_after_name` -## `parse_namespace` +## `parser_parse_namespace` 1. Consume namespace declaration 2. Parse identifier 3. `parse_global_namespace` -## `parse_operator` +## `parser_parse_operator` 1. Check for and parse export declaration 2. `parse_attributes` @@ -536,7 +1037,7 @@ This currently doesn't support postfix specifiers (planning to in the future) 4. `parse_type` 5. `parse_operator_after_ret_type` -## `parse_operator_cast` +## `parser_parse_operator_cast` 1. Look for and parse a qualifier namespace for the cast (in-case this is defined outside the class's scope) 2. Consume operator declaration @@ -551,33 +1052,43 @@ This currently doesn't support postfix specifiers (planning to in the future) 1. Consume end statement 2. Check for and consume comment : `parse_comment` - -## `parse_struct` +## `parser_parse_struct` 1. `parse_class_struct` -## `parse_template` +## `parser_parse_template` -Note: This currently doesn't support templated operator casts (going to need to add support for it) +1. Initial State Configuration + 1. Module flag handling (`export` keyword) + 2. Template parameter parsing via `parse_params` + * Uses specialized template capture mode + * Validates parameter list integrity +2. Declaration Type Resolution + 1. Primary type dispatch + * `Class/Struct/Union` declarations + * Using declarations + 2. Function/Variable handling + * Attribute collection + * Specifier validation (16 max) + * Function expectation detection +3. Special Case Processing + 1. Global namespace constructors/destructors + * Context validation + * Delegation to `parse_global_nspace_constructor_destructor` + 2. Operator cast implementations + * Token lookahead for operator detection + * Static symbol access validation + * Cast parsing delegation +4. AST Construction + 1. Template node composition + * `CT_Template` type assignment + * Parameter linkage + * Declaration binding + * Module flag preservation -1. Check for and parse export declaration -2. Consume template declaration -3. `parse_params` -4. Parse for any of the following: - 1. Decl_Class : `parse_class` - 2. Decl_Struct : `parse_struct` - 3. Decl_Union : `parse_union` - 4. Decl_Using : `parse_using` - 5. The following compound into a resolved definition or declaration: - 1. `parse_attributes` - 2. Parse specifiers - 3. Attempt to parse as constructor or destructor: `parse_global_nspace_constructor_destructor` - 4. Otherwise: `parse_operator_function_or_variable` +## `parser_parse_type` -## `parse_type` - -This function's implementation is awful and not done correctly. It will most likely be overhauled in the future as I plan to segement the AST_Type into several AST varaints along with sub-types to help produce robust type expressions. -Hopefully I won't need to make authentic type expressions as I was hopeing to avoid that... +This implementatin will be updated in the future to properly handle functional typename signatures. ### Current Algorithim @@ -590,7 +1101,8 @@ Anything that is in the qualifier capture of the function typename is treated as 1. If its an in-place definition of a class, enum, struct, or union: 2. If its a decltype (Not supported yet but draft impl there) 3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc ) - 4. Ends up being a regular type alias of an identifier + 4. If its a typename amcro + 5. A regular type alias of an identifier 5. Parse specifiers (postfix) 6. We need to now look ahead to see If we're dealing with a function typename 7. If wer're dealing with a function typename: @@ -618,7 +1130,8 @@ Anything that is in the qualifier capture of the function typename is treated as 1. If its an in-place definition of a class, enum, struct, or union: 2. If its a decltype (Not supported yet but draft impl there) 3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc ) - 4. Ends up being a regular type alias of an identifier + 4. If its a typename amcro + 5. A regular type alias of an identifier 4. Parse specifiers (postfix) 1. If any specifiers are found populate specifiers code with them. 5. We need to now look ahead to see If we're dealing with a function typename @@ -679,7 +1192,7 @@ Anything that is in the qualifier capture of the function typename is treated as 6. Decl_Union 7. Preprocess_Define 8. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif) - 9. Preprocess_Macro + 9. Preprocess_Macro (`MT_Statement` or `MT_Typename`) 10. Preprocess_Pragma 11. Unsupported preprocess directive 12. Variable diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/Parsing.md b/Project/Source/GasaEditor/GasaGen/gencpp/Parsing.md index c29fc17..e562897 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/Parsing.md +++ b/Project/Source/GasaEditor/GasaGen/gencpp/Parsing.md @@ -6,9 +6,9 @@ # Parsing -The library features a naive single-pass parser tailored for only what the library needs to construct the supported syntax of C++ into its AST for *"front-end"* meta-programming purposes. +The library features a naive single-pass parser, tailored for only what the library needs; for construction of C++ code into gencpp's AST for *"front-end"* meta-programming purposes. -This parser does not, and should not do the compiler's job. By only supporting this minimal set of features, the parser is kept (so far) around ~7000 loc. I hope to keep it under 10k loc worst case. +This parser does not, and should not do the compiler's job. By only supporting this minimal set of features, the parser is kept (so far) around ~7000 loc. I hope to keep it under 10-15k loc worst case. You can think of this parser as *frontend parser* vs a *semantic parser*. Its intuitively similar to WYSIWYG. What you ***precerive*** as the syntax from the user-side before the compiler gets a hold of it, is what you get. @@ -17,6 +17,7 @@ User exposed interface: ```cpp CodeClass parse_class ( Str class_def ); CodeConstructor parse_constructor ( Str constructor_def ); +CodeDefine parse_define ( Str define_def ); CodeDestructor parse_destructor ( Str destructor_def ); CodeEnum parse_enum ( Str enum_def ); CodeBody parse_export_body ( Str export_def ); @@ -53,38 +54,98 @@ The keywords supported for the preprocessor are: * endif * pragma -Each directive `#` line is considered one preproecessor unit, and will be treated as one Preprocessor AST. +Each directive `#` line is considered one preproecessor unit, and will be treated as one Preprocessor AST node. If a directive is used with an unsupported keyword its will be processed as an untyped AST. -The preprocessor lines are stored as members of their associated scope they are parsed within. ( Global, Namespace, Class/Struct ) -***Again (Its not standard): These ASTs will be considered members or entries of braced scope they reside within*** +The preprocessor lines are stored as members of their associated scope they are parsed within ( Global, Namespace, Class/Struct ). +***Again: These ASTs will be considered members or entries of braced scope they reside within*** Any preprocessor definition abuse that changes the syntax of the core language is unsupported and will fail to parse if not kept within an execution scope (function body, or expression assignment). Exceptions: -* function signatures are allowed for a preprocessed macro: `neverinline MACRO() { ... }` +* varaible definitions are allowed for a preprocessed macro `extern MACRO();` +* function definitions are allowed for a preprocessed macro: `neverinline MACRO() { ... }` * Disable with: `#define GEN_PARSER_DISABLE_MACRO_FUNCTION_SIGNATURES` * typedefs allow for a preprocessed macro: `typedef MACRO();` * Disable with: `#define GEN_PARSER_DISABLE_MACRO_TYPEDEF` * Macros can behave as typenames -* There is some macro support in paramters for functions or templates *(Specifically added to support parsing Unreal Engine source)*. +* There is some macro support in parameters for functions or templates *(Specifically added to support parsing Unreal Engine source)*. *(Exceptions are added on an on-demand basis)* *(See functions `parse_operator_function_or_variable` and `parse_typedef` )* Adding your own exceptions is possible by simply modifying the parser to allow for the syntax you need. -*Note: You could interpret this strictness as a feature. This would allow the user to see if their codebase or a third-party's codebase some some egregious preprocessor abuse.* +*Note: You could interpret this strictness as a feature. This would allow the user to see if their codebase or a third-party's codebase contains some egregious preprocessor abuse.* -If a macro is not defined withint e scope of parsing a set of files, it can be defined beforehand by: +Macros used within a file should be registered by the user before parsing. This can be done two ways: -* Appending the [`PreprocessorDefines`](https://github.com/Ed94/gencpp/blob/a18b5b97aa5cfd20242065cbf53462a623cd18fa/base/components/header_end.hpp#L137) array. - * For functional macros a "(" just needs to be added after the name like: `(` so that it will tokenize its arguments as part of the token during lexing. -* Defining a CodeDefine using `def_define`. The definition will be processed by the interface for user into `PreprocessorDefines`. - * This can be prevented by setting the optional prameter `dont_append_preprocess_defines`. +1. The register macro interface within [interface.hpp](../base/components/interface.hpp). +2. Using `def_define` to create a CodeDefine and making sure to not set `opts.dont_register_to_preprocess_macros` to `true`. -The lexing and parsing takes shortcuts from whats expected in the standard. +## Registering macros +While the registeration of macros in the meta-program's side for parsing can be considered tedius, its necessary for the parser to accurately resolve the macros intent in one pass (and it provides some hygenics by verifying that they are used as intended). + +The following can be used to register a macro: + +```c +GEN_API void register_macro( Macro macro ); +GEN_API void register_macros( s32 num, ... ); +GEN_API void register_macros_arr( s32 num, Macro* macros ); +``` + +The Macro typename is defined with the following in [parser_types.hpp](../base/components/parser_types.hpp): + +```c +struct Macro +{ + StrCached Name; + MacroType Type; + MacroFlags Flags; +}; +``` + +The macro can be designated one of the following types: + +* `MT_Expression`: Intended to resolve to an expression expansion. +* `MT_Statement`: Intended to resolve an statement expansion. +* `MT_Typename`: Intended to resolve to a typename. + +Additioonally tthe following flags may be set: + +* `MF_Functional`: The macro intended to be passed arguments are at least have the calling `()` as part of its usage. +* `MF_Expects_Body`: The parser should expect a braced-body `{ ... }` after the macro signature ` ` +* `MF_Allow_As_Identifier`: Will allow the macro to be an acceptable token/s when an `Tok_Identifier` is expected. +* `MF_Allow_As_Attribute`: Will allow the macro to be an acceptable token/s when an attribute token/s is expected. +* `MF_Allow_As_Definition`: Will allow the macro be an acceptable token/s when the parser expects a declartion or definition to resolve after attributes or specifiers have been identified beforehand. + * This flag requires that the macro is of type `MT_Statement` to make any sense of usage. + +If a macro is not defined the following warning will be issued if `GEN_BUILD_DEBUG=1` during lexing within [lexer.cpp](../base/components/lexer.cpp) - `lex_preprocessor_define`: + +```c +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 +); +``` + +Further within the same scope, the lexer will issue a warning if it detects a macro was not flagged as function but has an open parenthesis `(` token right after is name with no whitespace: + +```c +log_fmt("Warning: %S registered macro is not flagged as functional yet the definition detects opening parenthesis '(' for arguments\n" + , name.Text +); +``` + +Macros are tracked using a `MacroTable Macros;` defined as a member of the library's `Context`. + +```c +typedef HashTable(Macro) MacroTable; +``` + +## Notes + +* Empty lines used throughout the file are preserved for formatting purposes during ast serialization (they have a dedicated Token: `Tok_NewLine`). * Numeric literals are not checked for validity. * The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. (There is a [todo](https://github.com/Ed94/gencpp/issues/49) to add support) * *This includes the assignment of variables.* @@ -95,4 +156,4 @@ The lexing and parsing takes shortcuts from whats expected in the standard. * Parsing attributes can be extended to support user defined macros by defining `GEN_DEFINE_ATTRIBUTE_TOKENS` (see `gen.hpp` for the formatting) * This is useful for example: parsing Unreal `Module_API` macros. -Empty lines used throughout the file are preserved for formatting purposes during ast serialization. +**The lexer & parser do not gracefully attempt to continue when it comes across incorrect code, and doesn't properly track errors into a listing (yet).** diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/Readme.md b/Project/Source/GasaEditor/GasaGen/gencpp/Readme.md index 7be3fd6..342f4d0 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/Readme.md +++ b/Project/Source/GasaEditor/GasaGen/gencpp/Readme.md @@ -15,3 +15,20 @@ If using the library's provided build scripts: ```ps1 .\build.ps1 unreal ``` + +## Notables + +For the most part this follows the same conventions as `gen_segmented`. + +This generator uses a separate enumeration definitions for the following: + +* [AttributeTokens.csv](./enums/AttributeTokens.csv) : Add your own _API attributes, etc here that are encountered within the Engine. +* [ESpecifier.csv](./enums/ESpecifier.csv) : Adds the `FORCEINLINE` & `FORCEINLINE_DEBUGGABLE` specfiers (additions are made as they are encountered) +* [ETokType.csv](./enums/ETokType.csv) : Same modifications as ESpecifier.csv. + +A separate [parser_case_macros.cpp](./components/parser_case_macros.cpp) is used to accomodate for the new forceinline specifiers. + +The `global` macro the library uses is redefined as an empty substiution. + + +The expected usage of this library is to put into into a third-party plugin module to then use either in editor modules or in shell script done in some stage of hot-reloading or building the Unreal Engine or Project. diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/Readme_Docs.md b/Project/Source/GasaEditor/GasaGen/gencpp/Readme_Docs.md index 4655f0a..fd20b8c 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/Readme_Docs.md +++ b/Project/Source/GasaEditor/GasaGen/gencpp/Readme_Docs.md @@ -26,7 +26,7 @@ This means that the typename entry for the parameter AST would be either: ***Concepts and Constraints are not supported*** Its a [todo](https://github.com/Ed94/gencpp/issues/21) -### Feature Macros: +### Feature Macros * `GEN_DEFINE_ATTRIBUTE_TOKENS` : Allows user to define their own attribute macros for use in parsing. * This can be generated using base.cpp. @@ -36,10 +36,41 @@ Its a [todo](https://github.com/Ed94/gencpp/issues/21) * `GEN_EXPOSE_BACKEND` : Will expose symbols meant for internal use only. * `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves. * `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized. -* `GEN_C_LIKE_PP` : Setting to `` Will prevent usage of function defnitions using references and structs with member functions. Structs will still have user-defined operator conversions, for-range support, and other operator overloads +* `GEN_C_LIKE_CPP` : Setting to `` Will prevent usage of function defnitions using references and structs with member functions. Structs will still have user-defined operator conversions, for-range support, and other operator overloads ### The Data & Interface +The library's persistent state is managed tracked by a context struct: `global Context* _ctx;` defined within [static_data.cpp](../base/components/static_data.cpp) + +https://github.com/Ed94/gencpp/blob/967a044637f1615c709cb723dc61118fcc08dcdb/base/components/interface.hpp#L39-L97 + +The interface for the context: + +* `init`: Initializtion +* `deinit`: De-initialization. +* `reset`: Clears the allocations, but doesn't free the memoery, then calls `init()` on `_ctx` again. +* `get_context`: Retreive the currently tracked context. +* `set_context`: Swap out the current tracked context. + + +#### Allocato usage + +* `Allocator_DyanmicContainers`: Growing arrays, hash tables. (Unbounded sized containers) +* `Allocator_Pool`: Fixed-sized object allocations (ASTs, etc) +* `Allocator_StrCache`: StrCached allocations +* `Allocator_Temp`: Temporary alloations mostly intended for StrBuilder usage. Manually cleared by the user by their own discretion. + +The allocator definitions used are exposed to the user incase they want to dictate memory usage + +* Allocators are defined with the `AllocatorInfo` structure found in [`memory.hpp`](../base/dependencies/memory.hpp) +* Most of the work is just defining the allocation procedure: + +```cpp + void* ( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); +``` + +For any allocator above that the user does not define before `init`, a fallback allocator will be assigned that utiizes the `fallback_allocator_proc` wtihin [interface.cpp](../base/components/interface.cpp). + As mentioned in root readme, the user is provided Code objects by calling the constructor's functions to generate them or find existing matches. The AST is managed by the library and provided to the user via its interface. @@ -47,14 +78,14 @@ However, the user may specifiy memory configuration. [Data layout of AST struct (Subject to heavily change with upcoming todos)](../base/components/ast.hpp#L396-461) -https://github.com/Ed94/gencpp/blob/eea4ebf5c40d5d87baa465abfb1be30845b2377e/base/components/ast.hpp#L396-L461 +https://github.com/Ed94/gencpp/blob/967a044637f1615c709cb723dc61118fcc08dcdb/base/components/ast.hpp#L369-L435 *`StringCahced` is a typedef for `Str` (a string slice), to denote it is an interned string* *`CodeType` is enum taggin the type of code. Has an underlying type of `u32`* *`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`* -*`StrBuilder` is the dynamically allocated string type for the library* +*`StrBuilder` is the dynamically allocating string builder type for the library* -AST widths are setup to be AST_POD_Size. +AST widths are setup to be AST_POD_Size (128 bytes by default). The width dictates how much the static array can hold before it must give way to using an allocated array: ```cpp @@ -73,41 +104,16 @@ int AST_ArrSpecs_Cap = ) / sizeof(Specifier) - 1; ``` - -*Ex: If the AST_POD_Size is 128 the capacity of the static array is 20.* - Data Notes: -* The allocator definitions used are exposed to the user incase they want to dictate memory usage - * You'll find the memory handling in `init`, `deinit`, `reset`, `gen_strbuilder_allocator`, `cache_str`, `make_code`. - * Allocators are defined with the `AllocatorInfo` structure found in [`memory.hpp`](../base/dependencies/memory.hpp) - * Most of the work is just defining the allocation procedure: - -```cpp - void* ( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); -``` - * ASTs are wrapped for the user in a Code struct which is a wrapper for a AST* type. * Code types have member symbols but their data layout is enforced to be POD types. * This library treats memory failures as fatal. * Cached Strings are stored in their own set of arenas. AST constructors use cached strings for names, and content. - * `StringArenas`, `StringCache`, `Allocator_StringArena`, and `Allocator_StringTable` are the associated containers or allocators. * Strings used for serialization and file buffers are not contained by those used for cached strings. - * They are currently using `FallbackAllocator`, which are tracked array of arenas that grows as needed (adds buckets when one runs out). - * Memory within the buckets is not reused, so its inherently wasteful. - * I will be augmenting the default allocator with virtual memory & a slab allocator in the [future](https://github.com/Ed94/gencpp/issues/12) -* Intrusive linked lists used children nodes on bodies, and parameters. + * `_ctx->Allocator_Temp` is used. * Its intended to generate the AST in one go and serialize after. The constructors and serializer are designed to be a "one pass, front to back" setup. -* Allocations can be tuned by defining the folloiwng macros (will be moved to runtime configuration in the future): - * `GEN_GLOBAL_BUCKET_SIZE` : Size of each bucket area for the global allocator - * `GEN_CODEPOOL_NUM_BLOCKS` : Number of blocks per code pool in the code allocator - * `GEN_SIZE_PER_STRING_ARENA` : Size per arena used with string caching. - * `GEN_MAX_COMMENT_LINE_LENGTH` : Longest length a comment can have per line. - * `GEN_MAX_NAME_LENGTH` : Max length of any identifier. - * `GEN_MAX_UNTYPED_STR_LENGTH` : Max content length for any untyped code. - * `TokenMap_FixedArena` : token_fmt_va uses local_persit memory of this arena type for the hashtable. - * `GEN_LEX_ALLOCATOR_SIZE` - * `GEN_BUILDER_STR_BUFFER_RESERVE` + * Any modifcations to an existing AST should be to just construct another with the modifications done on-demand while traversing the AST (non-destructive). The following CodeTypes are used which the user may optionally use strong typing with if they enable: `GEN_ENFORCE_STRONG_CODE_TYPES` @@ -117,6 +123,7 @@ The following CodeTypes are used which the user may optionally use strong typing * CodeClass * CodeConstructor * CodeDefine +* CodeDefineParams * CodeDestructor * CodeEnum * CodeExec @@ -127,7 +134,7 @@ The following CodeTypes are used which the user may optionally use strong typing * CodeModule * CodeNS * CodeOperator -* CodeOpCast +* CodeOpCast : User defined member operator conversion * CodeParams : Has support for `for : range` iterating across parameters. * CodePreprocessCond * CodePragma @@ -140,11 +147,15 @@ The following CodeTypes are used which the user may optionally use strong typing * CodeUsing * CodeVar -Each Code boy has an associated "filtered AST" with the naming convention: `AST_` +Each `struct Code` has an associated "filtered AST" with the naming convention: `AST_` Unrelated fields of the AST for that node type are omitted and only necessary padding members are defined otherwise. -Retrieving a raw version of the ast can be done using the `raw()` function defined in each AST. -## There are three sets of interfaces for Code AST generation the library provides +For the interface related to these code types see: + +* [ast.hpp](../base/components/ast.hpp): Under the region pragma `Code C-Interface` +* [code_types.hpp](../base/components/code_types.hpp): Under the region pragma `Code C-Interface`. Additional functionlity for c++ will be within the struct definitions or at the end of the file. + +## There are three categories of interfaces for Code AST generation & reflection * Upfront * Parsing @@ -164,6 +175,7 @@ Interface :`` * def_class * def_constructor * def_define +* def_define_params * def_destructor * def_enum * def_execution @@ -218,6 +230,27 @@ Code ``` +All optional parmeters are defined within `struct Opts_def_`. This was done to setup a [macro trick](https://x.com/vkrajacic/status/1749816169736073295) for default optional parameers in the C library: + +```cpp +struct gen_Opts_def_struct +{ + gen_CodeBody body; + gen_CodeTypename parent; + gen_AccessSpec parent_access; + gen_CodeAttributes attributes; + gen_CodeTypename* interfaces; + gen_s32 num_interfaces; + gen_ModuleFlag mflags; +}; +typedef struct gen_Opts_def_struct gen_Opts_def_struct; + +GEN_API gen_CodeClass gen_def__struct( gen_Str name, gen_Opts_def_struct opts GEN_PARAM_DEFAULT ); +#define gen_def_struct( name, ... ) gen_def__struct( name, ( gen_Opts_def_struct ) { __VA_ARGS__ } ) +``` + +In the C++ library, the `def_` is not wrapped in a macro. + When using the body functions, its recommended to use the args macro to auto determine the number of arguments for the varadic: ```cpp @@ -228,7 +261,7 @@ def_global_body( 3, ht_entry, array_ht_entry, hashtable ); ``` If a more incremental approach is desired for the body ASTs, `Code def_body( CodeT type )` can be used to create an empty body. -When the members have been populated use: `AST::validate_body` to verify that the members are valid entires for that type. +When the members have been populated use: `code_validate_body` to verify that the members are valid entires for that type. ### Parse construction @@ -238,12 +271,12 @@ Interface : * parse_class * parse_constructor +* parse_define * parse_destructor * parse_enum * parse_export_body * parse_extern_link * parse_friend - * Purposefully are only support forward declares with this constructor. * parse_function * parse_global_body * parse_namespace @@ -322,6 +355,7 @@ Code = parse_( gen_code_str ); The following are provided predefined by the library as they are commonly used: +* `enum_underlying_macro` * `access_public` * `access_protected` * `access_private` diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp b/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp index 86f3191..c736e5f 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp +++ b/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp @@ -32,10 +32,9 @@ GEN_NS_BEGIN #pragma region StaticData global Context* _ctx; +global u32 context_counter; #pragma region Constants -global u32 context_counter; - global Macro enum_underlying_macro; global Code Code_Global; @@ -2534,12 +2533,24 @@ void specifiers_to_strbuilder_ref( CodeSpecifiers self, StrBuilder* result ) GEN_ASSERT(result); s32 idx = 0; s32 left = self->NumEntries; - while ( left-- ) + while ( left -- ) { - Str spec = spec_to_str( self->ArrSpecs[idx] ); - strbuilder_append_fmt( result, "%.*s ", spec.Len, spec.Ptr ); + Specifier spec = self->ArrSpecs[idx]; + Str spec_str = spec_to_str( spec ); + if ( idx > 0 ) switch (spec) { + case Spec_Ptr: + case Spec_Ref: + case Spec_RValue: + break; + + default: + strbuilder_append_str(result, txt(" ")); + break; + } + strbuilder_append_fmt( result, "%S", spec_str ); idx++; } + strbuilder_append_str(result, txt(" ")); } StrBuilder struct_to_strbuilder(CodeStruct self) @@ -2943,7 +2954,7 @@ void var_to_strbuilder_ref(CodeVar self, StrBuilder* result ) strbuilder_append_fmt( result, "%SB ", attributes_to_strbuilder(self->Attributes) ); if ( self->Specs ) - strbuilder_append_fmt( result, "%SB\n", specifiers_to_strbuilder(self->Specs) ); + strbuilder_append_fmt( result, "%SB", specifiers_to_strbuilder(self->Specs) ); strbuilder_append_fmt( result, "%SB %S", typename_to_strbuilder(self->ValueType), self->Name ); @@ -3528,7 +3539,7 @@ void register_macros( s32 num, ... ) va_end(va); } -void register_macros( s32 num, Macro* macros ) +void register_macros_arr( s32 num, Macro* macros ) { GEN_ASSERT(num > 0); do @@ -4911,7 +4922,7 @@ CodeBody def_class_body( s32 num, ... ) return result; } -CodeBody def_class_body( s32 num, Code* codes ) +CodeBody def_class_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_class_body ); @@ -4974,7 +4985,7 @@ CodeDefineParams def_define_params( s32 num, ... ) return result; } -CodeDefineParams def_define_params( s32 num, CodeDefineParams* codes ) +CodeDefineParams def_define_params_arr( s32 num, CodeDefineParams* codes ) { def_body_code_array_start( def_define_params ); @@ -5033,7 +5044,7 @@ CodeBody def_enum_body( s32 num, ... ) return (CodeBody) result; } -CodeBody def_enum_body( s32 num, Code* codes ) +CodeBody def_enum_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_enum_body ); @@ -5094,7 +5105,7 @@ CodeBody def_export_body( s32 num, ... ) return result; } -CodeBody def_export_body( s32 num, Code* codes ) +CodeBody def_export_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_export_body ); @@ -5160,7 +5171,7 @@ CodeBody def_extern_link_body( s32 num, ... ) return result; } -CodeBody def_extern_link_body( s32 num, Code* codes ) +CodeBody def_extern_link_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_extern_linkage_body ); @@ -5227,7 +5238,7 @@ CodeBody def_function_body( s32 num, ... ) return result; } -CodeBody def_function_body( s32 num, Code* codes ) +CodeBody def_function_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_function_body ); @@ -5298,7 +5309,7 @@ CodeBody def_global_body( s32 num, ... ) return result; } -CodeBody def_global_body( s32 num, Code* codes ) +CodeBody def_global_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_global_body ); @@ -5369,7 +5380,7 @@ CodeBody def_namespace_body( s32 num, ... ) return result; } -CodeBody def_namespace_body( s32 num, Code* codes ) +CodeBody def_namespace_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_namespace_body ); @@ -5431,7 +5442,7 @@ CodeParams def_params( s32 num, ... ) return result; } -CodeParams def_params( s32 num, CodeParams* codes ) +CodeParams def_params_arr( s32 num, CodeParams* codes ) { def_body_code_array_start( def_params ); @@ -5487,7 +5498,7 @@ CodeSpecifiers def_specifiers( s32 num, ... ) return result; } -CodeSpecifiers def_specifiers( s32 num, Specifier* specs ) +CodeSpecifiers def_specifiers_arr( s32 num, Specifier* specs ) { if ( num <= 0 ) { log_failure("gen::def_specifiers: num cannot be zero or less"); @@ -5546,7 +5557,7 @@ CodeBody def_struct_body( s32 num, ... ) return result; } -CodeBody def_struct_body( s32 num, Code* codes ) +CodeBody def_struct_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_struct_body ); @@ -5607,7 +5618,7 @@ CodeBody def_union_body( s32 num, ... ) return result; } -CodeBody def_union_body( s32 num, Code* codes ) +CodeBody def_union_body_arr( s32 num, Code* codes ) { def_body_code_array_start( def_union_body ); @@ -5789,7 +5800,7 @@ s32 lex_preprocessor_define( LexContext* ctx ) macro.Flags |= MF_Functional; } - Token opening_paren = { { ctx->scanner, 1 }, Tok_Capture_Start, ctx->line, ctx->column, TF_Preprocess }; + Token opening_paren = { { ctx->scanner, 1 }, Tok_Paren_Open, ctx->line, ctx->column, TF_Preprocess }; array_append( _ctx->Lexer_Tokens, opening_paren ); move_forward(); @@ -5880,7 +5891,7 @@ s32 lex_preprocessor_define( LexContext* ctx ) ); return Lex_ReturnNull; } - Token closing_paren = { { ctx->scanner, 1 }, Tok_Capture_End, ctx->line, ctx->column, TF_Preprocess }; + Token closing_paren = { { ctx->scanner, 1 }, Tok_Paren_Close, ctx->line, ctx->column, TF_Preprocess }; array_append(_ctx->Lexer_Tokens, closing_paren); move_forward(); } @@ -5919,7 +5930,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) ctx->token.Text.Len++; } - ctx->token.Type = str_to_toktype( tok_to_str(ctx->token) ); + ctx->token.Type = str_to_toktype( ctx->token.Text ); bool is_preprocessor = ctx->token.Type >= Tok_Preprocess_Define && ctx->token.Type <= Tok_Preprocess_Pragma; if ( ! is_preprocessor ) @@ -6126,7 +6137,7 @@ void lex_found_token( LexContext* ctx ) return; } - TokType type = str_to_toktype( tok_to_str(ctx->token) ); + TokType type = str_to_toktype( ctx->token.Text ); if (type <= Tok_Access_Public && type >= Tok_Access_Private ) { ctx->token.Flags |= TF_AccessSpecifier; @@ -6170,7 +6181,7 @@ void lex_found_token( LexContext* ctx ) 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 ) { + if ( ! resolved_to_macro && GEN_BUILD_DEBUG ) { log_fmt("Info(%d, %d): %S identified as a macro but usage here does not resolve to one (interpreting as identifier)\n" , ctx->token.Line , ctx->token.Line @@ -6435,7 +6446,7 @@ TokArray lex( Str content ) { Str text = { c.scanner, 1 }; c.token.Text = text; - c.token.Type = Tok_Capture_Start; + c.token.Type = Tok_Paren_Open; if (c.left) move_forward(); @@ -6445,7 +6456,7 @@ TokArray lex( Str content ) { Str text = { c.scanner, 1 }; c.token.Text = text; - c.token.Type = Tok_Capture_End; + c.token.Type = Tok_Paren_Close; if (c.left) move_forward(); @@ -6936,7 +6947,7 @@ TokArray lex( Str content ) #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 \ +#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \ case Tok_Spec_Consteval: \ case Tok_Spec_Constexpr: \ case Tok_Spec_Constinit: \ @@ -6950,7 +6961,7 @@ case Tok_Spec_Static: \ case Tok_Spec_Volatile: \ case Tok_Spec_Virtual -#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES \ +#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES \ case Spec_Constexpr: \ case Spec_Constinit: \ case Spec_Explicit: \ @@ -6990,12 +7001,12 @@ case Spec_NeverInline: \ case Spec_Static: \ case Spec_Volatile -#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES \ +#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIER_CASES \ case Spec_Const: \ case Spec_Inline: \ case Spec_ForceInline -#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES \ +#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES \ case Spec_Const: \ case Spec_Consteval: \ case Spec_Constexpr: \ @@ -7007,7 +7018,7 @@ case Spec_Inline: \ case Spec_NeverInline: \ case Spec_Static -#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES \ +#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIER_CASES \ case Spec_Const: \ case Spec_Constexpr: \ case Spec_ForceInline: \ @@ -7015,7 +7026,7 @@ case Spec_Inline: \ case Spec_NeverInline: \ case Spec_Static -#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES \ +#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIER_CASES \ case Spec_Const: \ case Spec_Constexpr: \ case Spec_Constinit: \ @@ -7043,6 +7054,12 @@ case Spec_Static: \ case Spec_Thread_Local: \ case Spec_Volatile +#define GEN_PARSER_TYPENAME_ALLOWED_SUFFIX_SPECIFIER_CASES \ +case Spec_Const: \ +case Spec_Ptr: \ +case Spec_Ref: \ +case Spec_RValue + // TODO(Ed) : Rename ETok_Capture_Start, ETok_Capture_End to Open_Parenthesis adn Close_Parenthesis constexpr bool lex_dont_skip_formatting = false; @@ -7570,7 +7587,7 @@ Code parse_array_decl() untyped_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)untyped_tok.Text.Ptr; - Code array_expr = untyped_str( tok_to_str(untyped_tok) ); + Code array_expr = untyped_str( untyped_tok.Text ); // [ if ( left == 0 ) @@ -7638,18 +7655,18 @@ CodeAttributes parse_attributes() else if ( check( Tok_Decl_GNU_Attribute ) ) { eat( Tok_Decl_GNU_Attribute ); - eat( Tok_Capture_Start ); - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); + eat( Tok_Paren_Open ); // __attribute__(( - while ( left && currtok.Type != Tok_Capture_End ) + while ( left && currtok.Type != Tok_Paren_Close ) { eat( currtok.Type ); } // __attribute__(( - eat( Tok_Capture_End ); - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); + eat( Tok_Paren_Close ); // __attribute__(( )) len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr; @@ -7657,16 +7674,16 @@ CodeAttributes parse_attributes() else if ( check( Tok_Decl_MSVC_Attribute ) ) { eat( Tok_Decl_MSVC_Attribute ); - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); // __declspec( - while ( left && currtok.Type != Tok_Capture_End ) + while ( left && currtok.Type != Tok_Paren_Close ) { eat( currtok.Type ); } // __declspec( - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // __declspec( ) len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr; @@ -7677,20 +7694,20 @@ CodeAttributes parse_attributes() // // If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...) - if ( check( Tok_Capture_Start)) + if ( check( Tok_Paren_Open)) { - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); s32 level = 0; - while (left && currtok.Type != Tok_Capture_End && level == 0) + while (left && currtok.Type != Tok_Paren_Close && level == 0) { - if (currtok.Type == Tok_Capture_Start) + if (currtok.Type == Tok_Paren_Open) ++ level; - if (currtok.Type == Tok_Capture_End) + if (currtok.Type == Tok_Paren_Close) --level; eat(currtok.Type); } - eat(Tok_Capture_End); + eat(Tok_Paren_Close); } len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr; @@ -7774,7 +7791,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) } Token parent_tok = parse_identifier(nullptr); - parent = def_type( tok_to_str(parent_tok) ); + parent = def_type( parent_tok.Text ); // : while ( check(Tok_Comma) ) @@ -7787,7 +7804,7 @@ Code parse_class_struct( TokType which, bool inplace_def ) } Token interface_tok = parse_identifier(nullptr); - array_append( interfaces, def_type( tok_to_str(interface_tok) ) ); + array_append( interfaces, def_type( interface_tok.Text ) ); // : , ... } } @@ -7810,10 +7827,10 @@ Code parse_class_struct( TokType which, bool inplace_def ) } if ( which == Tok_Decl_Class ) - result = cast(Code, def_class( tok_to_str(name), def_assign( body, parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) )); + result = cast(Code, def_class( name.Text, def_assign( body, parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) )); else - result = cast(Code, def_struct( tok_to_str(name), def_assign( body, (CodeTypename)parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) )); + result = cast(Code, def_struct( name.Text, def_assign( body, (CodeTypename)parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) )); if ( inline_cmt ) result->InlineCmt = cast(Code, inline_cmt); @@ -8024,20 +8041,20 @@ CodeBody parse_class_struct_body( TokType which, Token name ) // } //! Fallthrough intended - GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES: + GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES: { Specifier specs_found[16] = { Spec_NumSpecifiers }; s32 NumSpecifiers = 0; while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); b32 ignore_spec = false; switch ( spec ) { - GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES: + GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES: break; case Spec_Consteval: @@ -8065,7 +8082,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // @@ -8115,7 +8132,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) case Tok_Type_int: case Tok_Type_double: { - if ( nexttok.Type == Tok_Capture_Start && name.Text.Len && currtok.Type == Tok_Identifier ) + if ( nexttok.Type == Tok_Paren_Open && name.Text.Len && currtok.Type == Tok_Identifier ) { if ( c_str_compare_len( name.Text.Ptr, currtok.Text.Ptr, name.Text.Len ) == 0 ) { @@ -8139,7 +8156,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) 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) ); + member = untyped_str( untyped_tok.Text ); // Something unknown break; } @@ -8167,7 +8184,7 @@ CodeComment parse_comment() CodeComment result = (CodeComment) make_code(); result->Type = CT_Comment; - result->Content = cache_str( tok_to_str(currtok_noskip) ); + result->Content = cache_str( currtok_noskip.Text ); // result->Token = currtok_noskip; eat( Tok_Comment ); @@ -8208,19 +8225,19 @@ Code parse_complicated_definition( TokType which ) } Token tok = tokens.Arr[ idx - 1 ]; - if ( tok_is_specifier(tok) && spec_is_trailing( str_to_specifier( tok_to_str(tok))) ) + if ( tok_is_specifier(tok) && spec_is_trailing( str_to_specifier( tok.Text)) ) { // (...) ...; s32 spec_idx = idx - 1; Token spec = tokens.Arr[spec_idx]; - while ( tok_is_specifier(spec) && spec_is_trailing( str_to_specifier( tok_to_str(spec))) ) + while ( tok_is_specifier(spec) && spec_is_trailing( str_to_specifier( spec.Text)) ) { -- spec_idx; spec = tokens.Arr[spec_idx]; } - if ( tokens.Arr[spec_idx].Type == Tok_Capture_End ) + if ( tokens.Arr[spec_idx].Type == Tok_Paren_Close ) { // Forward declaration with trailing specifiers for a procedure tok = tokens.Arr[spec_idx]; @@ -8244,9 +8261,19 @@ Code parse_complicated_definition( TokType which ) if ( tok.Type == Tok_BraceCurly_Close ) { // Its an inplace definition - // { ... } ; + // { ... } ; ok_to_parse = true; is_inplace = true; + + CodeTypename type = cast(CodeTypename, parse_forward_or_definition(which, is_inplace)); + + // Should be a name right after the type. + Token name = parse_identifier(nullptr); + _ctx->parser.Scope->Name = name.Text; + + CodeVar result = parse_variable_after_name(ModuleFlag_None, NullCode, NullCode, type, name.Text); + parser_pop(& _ctx->parser); + return (Code) result; } else if ( tok.Type == Tok_Identifier && tokens.Arr[ idx - 3 ].Type == which ) { @@ -8355,16 +8382,16 @@ Code parse_assignment_expression() level++; if (currtok.Type == Tok_BraceCurly_Close ) level--; - if (currtok.Type == Tok_Capture_Start) + if (currtok.Type == Tok_Paren_Open) level++; - else if (currtok.Type == Tok_Capture_End) + else if (currtok.Type == Tok_Paren_Close) level--; eat( currtok.Type ); } expr_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )expr_tok.Text.Ptr - 1; - expr = untyped_str( tok_to_str(expr_tok) ); + expr = untyped_str( expr_tok.Text ); // = return expr; } @@ -8420,12 +8447,12 @@ CodeFn parse_function_after_name( { if ( specifiers == nullptr ) { - specifiers = def_specifier( str_to_specifier( tok_to_str(currtok)) ); + specifiers = def_specifier( str_to_specifier( currtok.Text) ); eat( currtok.Type ); continue; } - specifiers_append(specifiers, str_to_specifier( tok_to_str(currtok)) ); + specifiers_append(specifiers, str_to_specifier( currtok.Text) ); eat( currtok.Type ); } // ( ) @@ -8468,7 +8495,7 @@ CodeFn parse_function_after_name( } StrBuilder - name_stripped = strbuilder_make_str( _ctx->Allocator_Temp, tok_to_str(name) ); + name_stripped = strbuilder_make_str( _ctx->Allocator_Temp, name.Text ); strbuilder_strip_space(name_stripped); CodeFn @@ -8755,7 +8782,7 @@ CodeBody parse_global_nspace( CodeType which ) while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); bool ignore_spec = false; @@ -8790,7 +8817,7 @@ CodeBody parse_global_nspace( CodeType which ) if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // } @@ -8910,7 +8937,7 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) if (nav.Type == Tok_Operator && nav.Text.Ptr[1] == '>') -- template_level; - if ( nav.Type == Tok_Capture_Start) + if ( nav.Type == Tok_Paren_Open) { if (template_level != 0 ) ++ capture_level; @@ -8918,12 +8945,12 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) break; } - if ( template_level != 0 && nav.Type == Tok_Capture_End) + if ( template_level != 0 && nav.Type == Tok_Paren_Close) -- capture_level; } } - if ( nav.Type == Tok_Capture_Start ) + if ( nav.Type == Tok_Paren_Open ) break; } @@ -8969,10 +8996,10 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) if (tok_left.Type == Tok_Operator && tok_left.Text.Ptr[1] == '>') -- template_level; - if ( template_level != 0 && tok_left.Type == Tok_Capture_Start) + if ( template_level != 0 && tok_left.Type == Tok_Paren_Open) ++ capture_level; - if ( template_level != 0 && tok_left.Type == Tok_Capture_End) + if ( template_level != 0 && tok_left.Type == Tok_Paren_Close) -- capture_level; if ( capture_level == 0 && template_level == 0 && tok_left.Type == Tok_Identifier ) @@ -9096,7 +9123,7 @@ CodeInclude parse_include() } _ctx->parser.Scope->Name = currtok.Text; - include->Content = cache_str( tok_to_str(currtok) ); + include->Content = cache_str( currtok.Text ); eat( Tok_String ); // #include or "Path" @@ -9421,12 +9448,12 @@ CodeOperator parse_operator_after_ret_type( { if ( specifiers == nullptr ) { - specifiers = def_specifier( str_to_specifier( tok_to_str(currtok)) ); + specifiers = def_specifier( str_to_specifier( currtok.Text) ); eat( currtok.Type ); continue; } - specifiers_append(specifiers, str_to_specifier( tok_to_str(currtok)) ); + specifiers_append(specifiers, str_to_specifier( currtok.Text) ); eat( currtok.Type ); } // operator ( ) @@ -9456,7 +9483,7 @@ CodeOperator parse_operator_after_ret_type( } // OpValidateResult check_result = operator__validate( op, params, ret_type, specifiers ); - CodeOperator result = def_operator( op, tok_to_str(nspace), def_assign( params, ret_type, body, specifiers, attributes, mflags ) ); + CodeOperator result = def_operator( op, nspace.Text, def_assign( params, ret_type, body, specifiers, attributes, mflags ) ); if ( inline_cmt ) result->InlineCmt = inline_cmt; @@ -9520,7 +9547,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes Token name = parse_identifier(nullptr); _ctx->parser.Scope->Name = name.Text; - bool detected_capture = check( Tok_Capture_Start ); + bool detected_capture = check( Tok_Paren_Open ); // Check three tokens ahead to make sure that were not dealing with a constructor initialization... // ( 350.0f , <--- Could be the scenario @@ -9545,11 +9572,11 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes { Token tok = _ctx->parser.Tokens.Arr[ idx ]; - if ( tok.Type == Tok_Capture_Start ) + if ( tok.Type == Tok_Paren_Open ) level++; - else if ( tok.Type == Tok_Capture_End && level > 0 ) + else if ( tok.Type == Tok_Paren_Close && level > 0 ) level--; - if (level == 0 && tok.Type == Tok_Capture_End) + if (level == 0 && tok.Type == Tok_Paren_Close) break; } ++ idx; // Will incremnt to possible comma position @@ -9574,7 +9601,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes return InvalidCode; } // Dealing with a variable - result = cast(Code, parse_variable_after_name( ModuleFlag_None, attributes, specifiers, type, tok_to_str(name) )); + result = cast(Code, parse_variable_after_name( ModuleFlag_None, attributes, specifiers, type, name.Text )); // ... } } @@ -9632,7 +9659,7 @@ CodePragma parse_pragma() _ctx->parser.Scope->Name = currtok.Text; - pragma->Content = cache_str( tok_to_str(currtok) ); + pragma->Content = cache_str( currtok.Text ); eat( Tok_Preprocess_Content ); // #pragma @@ -9646,7 +9673,7 @@ CodeParams parse_params( bool use_template_capture ) push_scope(); if ( ! use_template_capture ) { - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); // ( } else { @@ -9655,9 +9682,9 @@ CodeParams parse_params( bool use_template_capture ) // < } - if ( ! use_template_capture && check( Tok_Capture_End ) ) + if ( ! use_template_capture && check( Tok_Paren_Close ) ) { - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // ) parser_pop(& _ctx->parser); return NullCode; @@ -9688,7 +9715,7 @@ CodeParams parse_params( bool use_template_capture ) } #define CheckEndParams() \ - (use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Capture_End)) + (use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Paren_Close)) // TODO(Ed): Use expression macros or this? macro as attribute? // Ex: Unreal has this type of macro: vvvvvvvvv @@ -9756,17 +9783,17 @@ CodeParams parse_params( bool use_template_capture ) if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>') -- template_level; - if ( currtok.Type == Tok_Capture_Start) + if ( currtok.Type == Tok_Paren_Open) ++ capture_level; - if ( currtok.Type == Tok_Capture_End) + if ( currtok.Type == Tok_Paren_Close) -- capture_level; value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr; eat( currtok.Type ); } - value = untyped_str( strbuilder_to_str(parser_strip_formatting( tok_to_str(value_tok), parser_strip_formatting_dont_preserve_newlines )) ); + value = untyped_str( strbuilder_to_str(parser_strip_formatting( value_tok.Text, parser_strip_formatting_dont_preserve_newlines )) ); // ( = } } @@ -9777,7 +9804,7 @@ CodeParams parse_params( bool use_template_capture ) result->Macro = macro; if ( name.Text.Len > 0 ) - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); result->ValueType = type; @@ -9870,17 +9897,17 @@ CodeParams parse_params( bool use_template_capture ) if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>') -- template_level; - if ( currtok.Type == Tok_Capture_Start) + if ( currtok.Type == Tok_Paren_Open) ++ capture_level; - if ( currtok.Type == Tok_Capture_End) + if ( currtok.Type == Tok_Paren_Close) -- capture_level; value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr; eat( currtok.Type ); } - value = untyped_str( strbuilder_to_str(parser_strip_formatting( tok_to_str(value_tok), parser_strip_formatting_dont_preserve_newlines )) ); + value = untyped_str( strbuilder_to_str(parser_strip_formatting( value_tok.Text, parser_strip_formatting_dont_preserve_newlines )) ); // ( = , = } // ( = , = , .. @@ -9892,7 +9919,7 @@ CodeParams parse_params( bool use_template_capture ) param->Macro = macro; if ( name.Text.Len > 0 ) - param->Name = cache_str( tok_to_str(name) ); + param->Name = cache_str( name.Text ); param->PostNameMacro = post_name_macro; param->ValueType = cast(CodeTypename, type); @@ -9905,7 +9932,7 @@ CodeParams parse_params( bool use_template_capture ) if ( ! use_template_capture ) { - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // ( = , = , .. ) } else @@ -9949,7 +9976,7 @@ CodePreprocessCond parse_preprocess_cond() } _ctx->parser.Scope->Name = currtok.Text; - cond->Content = cache_str( tok_to_str(currtok) ); + cond->Content = cache_str( currtok.Text ); eat( Tok_Preprocess_Content ); // # @@ -9978,20 +10005,20 @@ Code parse_simple_preprocess( TokType which ) // TODO(Ed) : Parse this properly later (expression and statement support) if ( macro && macro_is_functional(* macro) ) { - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); s32 level = 0; - while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) ) + while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) ) { - if ( currtok.Type == Tok_Capture_Start ) + if ( currtok.Type == Tok_Paren_Open ) level++; - else if ( currtok.Type == Tok_Capture_End && level > 0 ) + else if ( currtok.Type == Tok_Paren_Close && level > 0 ) level--; eat( currtok.Type ); } - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // ( ) full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr; @@ -10104,21 +10131,21 @@ Code parse_static_assert() _ctx->parser.Scope->Name = content.Text; eat( Tok_StaticAssert ); - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); // static_assert( // TODO(Ed) : Parse this properly. s32 level = 0; - while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) ) + while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) ) { - if ( currtok.Type == Tok_Capture_Start ) + if ( currtok.Type == Tok_Paren_Open ) level++; - else if ( currtok.Type == Tok_Capture_End ) + else if ( currtok.Type == Tok_Paren_Close ) level--; eat( currtok.Type ); } - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); eat( Tok_Statement_End ); // static_assert( ); @@ -10216,13 +10243,13 @@ CodeVar parse_variable_after_name( eat( Tok_BraceCurly_Close ); expr_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_tok.Text.Ptr; - expr = untyped_str( tok_to_str(expr_tok) ); + expr = untyped_str( expr_tok.Text ); // = { } } - if ( currtok.Type == Tok_Capture_Start ) + if ( currtok.Type == Tok_Paren_Open ) { - eat( Tok_Capture_Start); + eat( Tok_Paren_Open); // ( Token expr_token = currtok; @@ -10230,20 +10257,20 @@ CodeVar parse_variable_after_name( using_constructor_initializer = true; s32 level = 0; - while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) ) + while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) ) { - if ( currtok.Type == Tok_Capture_Start ) + if ( currtok.Type == Tok_Paren_Open ) level++; - else if ( currtok.Type == Tok_Capture_End && level > 0 ) + else if ( currtok.Type == Tok_Paren_Close && level > 0 ) level--; eat( currtok.Type ); } expr_token.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_token.Text.Ptr; - expr = untyped_str( tok_to_str(expr_token) ); - eat( Tok_Capture_End ); + expr = untyped_str( expr_token.Text ); + eat( Tok_Paren_Close ); // ( ) } @@ -10265,7 +10292,7 @@ CodeVar parse_variable_after_name( } expr_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_tok.Text.Ptr; - bitfield_expr = untyped_str( tok_to_str(expr_tok) ); + bitfield_expr = untyped_str( expr_tok.Text ); // : } @@ -10346,7 +10373,7 @@ CodeVar parse_variable_declaration_list() while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); switch ( spec ) { @@ -10370,7 +10397,7 @@ CodeVar parse_variable_declaration_list() { log_failure( "Error, invalid specifier '%S' proceeding comma\n" "(Parser will add and continue to specifiers, but will most likely fail to compile)\n%S" - , tok_to_str(currtok), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); + , currtok.Text, strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); continue; } break; @@ -10385,7 +10412,7 @@ CodeVar parse_variable_declaration_list() } // , - Str name = tok_to_str(currtok); + Str name = currtok.Text; eat( Tok_Identifier ); // , @@ -10443,9 +10470,9 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers ) s32 level = 0; while ( left && ( currtok.Type != Tok_BraceCurly_Open || level > 0 ) ) { - if (currtok.Type == Tok_Capture_Start) + if (currtok.Type == Tok_Paren_Open) level++; - else if ( currtok.Type == Tok_Capture_End ) + else if ( currtok.Type == Tok_Paren_Close ) level--; eat( currtok.Type ); @@ -10454,7 +10481,7 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers ) initializer_list_tok.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )initializer_list_tok.Text.Ptr; // ( ) : - initializer_list = untyped_str( tok_to_str(initializer_list_tok) ); + initializer_list = untyped_str( initializer_list_tok.Text ); // TODO(Ed): Constructors can have post-fix specifiers @@ -10483,7 +10510,7 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers ) CodeConstructor result = ( CodeConstructor )make_code(); - result->Name = cache_str( tok_to_str(identifier)); + result->Name = cache_str( identifier.Text ); result->Specs = specifiers; @@ -10529,13 +10556,13 @@ CodeDefine parser_parse_define() return InvalidCode; } _ctx->parser.Scope->Name = currtok.Text; - define->Name = cache_str( tok_to_str(currtok) ); + define->Name = cache_str( currtok.Text ); eat( Tok_Identifier ); // #define Macro* macro = lookup_macro(define->Name); if (macro_is_functional(* macro)) { - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); // #define ( // We provide the define params even if empty to make sure '()' are serialized. @@ -10543,7 +10570,7 @@ CodeDefine parser_parse_define() params = (CodeDefineParams) make_code(); params->Type = CT_Parameters_Define; - if ( left && currtok.Type != Tok_Capture_End ) { + if ( left && currtok.Type != Tok_Paren_Close ) { params->Name = currtok.Text; params->NumEntries ++; @@ -10551,7 +10578,7 @@ CodeDefine parser_parse_define() // #define ( } - while( left && currtok.Type != Tok_Capture_End ) { + while( left && currtok.Type != Tok_Paren_Close ) { eat( Tok_Comma ); // #define ( , @@ -10564,7 +10591,7 @@ CodeDefine parser_parse_define() eat( Tok_Preprocess_Define_Param ); } - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // #define ( ) define->Params = params; @@ -10587,7 +10614,7 @@ CodeDefine parser_parse_define() return define; } - define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( tok_to_str(currtok), parser_strip_formatting_dont_preserve_newlines )) ); + define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( currtok.Text, parser_strip_formatting_dont_preserve_newlines )) ); eat( Tok_Preprocess_Content ); // #define ( ) @@ -10632,8 +10659,8 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) CodeComment inline_cmt = NullCode; // ~ - eat( Tok_Capture_Start ); - eat( Tok_Capture_End ); + eat( Tok_Paren_Open ); + eat( Tok_Paren_Close ); // ~() bool pure_virtual = false; @@ -10687,7 +10714,7 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers ) if ( tok_is_valid(prefix_identifier) ) { prefix_identifier.Text.Len += 1 + identifier.Text.Len; - result->Name = cache_str( tok_to_str(prefix_identifier) ); + result->Name = cache_str( prefix_identifier.Text ); } if ( specifiers ) @@ -10721,9 +10748,6 @@ CodeEnum parser_parse_enum( bool inplace_def ) Code array_expr = { nullptr }; CodeTypename type = { nullptr }; - char entries_code[ kilobytes(128) ] = { 0 }; - s32 entries_length = 0; - bool is_enum_class = false; eat( Tok_Decl_Enum ); @@ -10766,7 +10790,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) else if ( currtok.Type == Tok_Preprocess_Macro_Expr ) { // We'll support the enum_underlying macro - if ( str_contains( tok_to_str(currtok), enum_underlying_macro.Name) ) + if ( str_contains( currtok.Text, enum_underlying_macro.Name) ) { use_macro_underlying = true; underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr ); @@ -10801,7 +10825,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) switch ( currtok_noskip.Type ) { case Tok_NewLine: - member = untyped_str( tok_to_str(currtok_noskip) ); + member = untyped_str( currtok_noskip.Text ); eat( Tok_NewLine ); break; @@ -10894,7 +10918,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) Token prev = * lex_previous(_ctx->parser.Tokens, lex_dont_skip_formatting); entry.Text.Len = ( (sptr)prev.Text.Ptr + prev.Text.Len ) - (sptr)entry.Text.Ptr; - member = untyped_str( tok_to_str(entry) ); + member = untyped_str( entry.Text ); } break; } @@ -10938,7 +10962,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) result->Type = is_enum_class ? CT_Enum_Class_Fwd : CT_Enum_Fwd; } - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); if ( attributes ) result->Attributes = attributes; @@ -10990,7 +11014,7 @@ CodeExtern parser_parse_extern_link() CodeExtern result = (CodeExtern) make_code(); result->Type = CT_Extern_Linkage; - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); CodeBody entry = parser_parse_extern_link_body(); if ( cast(Code, entry) == Code_Invalid ) @@ -11026,11 +11050,11 @@ CodeFriend parser_parse_friend() while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); switch ( spec ) { - GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES: + GEN_PARSER_FRIEND_ALLOWED_SPECIFIER_CASES: break; default : @@ -11049,7 +11073,7 @@ CodeFriend parser_parse_friend() } if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // } @@ -11144,11 +11168,11 @@ CodeFn parser_parse_function() while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); switch ( spec ) { - GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES: + GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES: break; default: @@ -11166,17 +11190,10 @@ CodeFn parser_parse_function() } if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // - // Note(Ed): We're enforcing that using this codepath requires non-macro jank. - // Code macro_stmt = parse_macro_as_definiton(attributes, specifiers); - // if (macro_stmt) { - // parser_pop(& _ctx->parser); - // return macro_stmt; - // } - CodeTypename ret_type = parser_parse_type(parser_not_from_template, nullptr); if ( cast(Code, ret_type) == Code_Invalid ) { parser_pop(& _ctx->parser); @@ -11221,7 +11238,7 @@ CodeNS parser_parse_namespace() CodeNS result = (CodeNS) make_code(); result->Type = CT_Namespace; - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); result->Body = body; @@ -11252,11 +11269,11 @@ CodeOperator parser_parse_operator() while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); switch ( spec ) { - GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES: + GEN_PARSER_OPERATOR_ALLOWED_SPECIFIER_CASES: break; default: @@ -11274,7 +11291,7 @@ CodeOperator parser_parse_operator() } if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // @@ -11323,8 +11340,8 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers ) Token scope_name_tok = { scope_name, Tok_Identifier, 0, 0, TF_Null }; _ctx->parser.Scope->Name = scope_name_tok.Text; - eat( Tok_Capture_Start ); - eat( Tok_Capture_End ); + eat( Tok_Paren_Open ); + eat( Tok_Paren_Close ); // :: ... operator () // TODO(Ed) : operator cast can have const, volatile, l-value, r-value noexecept qualifying specifiers. @@ -11366,7 +11383,7 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers ) eat( Tok_BraceCurly_Close ); // :: ... operator () { } - body = untyped_str( tok_to_str(body_str) ); + body = untyped_str( body_str.Text ); } else { @@ -11382,7 +11399,7 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers ) CodeOpCast result = (CodeOpCast) make_code(); if ( tok_is_valid(name) ) - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); if (body) { result->Type = CT_Operator_Cast; @@ -11485,11 +11502,11 @@ CodeTemplate parser_parse_template() { while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); switch ( spec ) { - GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES: + GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIER_CASES: break; case Spec_Consteval : @@ -11512,7 +11529,7 @@ CodeTemplate parser_parse_template() } if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // template< > } @@ -11615,10 +11632,10 @@ CodeTypename parser_parse_type( bool from_template, bool* typedef_is_function ) // Prefix specifiers while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); 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) ); + log_failure( "Error, invalid specifier used in type definition: %S\n%SB", currtok.Text, parser_to_strbuilder(_ctx->parser) ); parser_pop(& _ctx->parser); return InvalidCode; } @@ -11675,18 +11692,18 @@ else if ( currtok.Type == Tok_DeclType ) eat( Tok_DeclType ); // decltype - eat( Tok_Capture_Start ); - while ( left && currtok.Type != Tok_Capture_End ) + eat( Tok_Paren_Open ); + while ( left && currtok.Type != Tok_Paren_Close ) { - if ( currtok.Type == Tok_Capture_Start ) + if ( currtok.Type == Tok_Paren_Open ) level++; - if ( currtok.Type == Tok_Capture_End ) + if ( currtok.Type == Tok_Paren_Close ) level--; eat( currtok.Type ); } - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text; _ctx->parser.Scope->Name = name; @@ -11728,11 +11745,12 @@ else if ( currtok.Type == Tok_DeclType ) } } } - // TODO(Ed): This needs updating else if ( currtok.Type == Tok_Preprocess_Macro_Typename ) { // Typename is a macro - name = currtok; - eat(Tok_Preprocess_Macro_Typename); + // name = currtok; + // eat(Tok_Preprocess_Macro_Typename); + Code macro = parse_simple_preprocess(Tok_Preprocess_Macro_Typename); + name.Text = macro->Content; } // The usual Identifier type signature that may have namespace qualifiers @@ -11753,15 +11771,18 @@ else if ( currtok.Type == Tok_DeclType ) // Suffix specifiers for typename. while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); - if ( spec != Spec_Const && spec != Spec_Ptr && spec != Spec_Ref && spec != Spec_RValue ) - { - 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; + switch (spec ) { + GEN_PARSER_TYPENAME_ALLOWED_SUFFIX_SPECIFIER_CASES: + break; + + default: { + log_failure( "Error, invalid specifier used in type definition: %S\n%SB", currtok.Text, parser_to_strbuilder(_ctx->parser) ); + parser_pop(& _ctx->parser); + return InvalidCode; + } } - specs_found[ NumSpecifiers ] = spec; NumSpecifiers++; eat( currtok.Type ); @@ -11770,7 +11791,7 @@ else if ( currtok.Type == Tok_DeclType ) #ifdef GEN_USE_NEW_TYPENAME_PARSING if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); NumSpecifiers = 0; } #endif @@ -11778,7 +11799,7 @@ else if ( currtok.Type == Tok_DeclType ) // For function type signatures CodeTypename return_type = NullCode; - CodeParams params = NullCode; + CodeParams params = NullCode; #ifdef GEN_USE_NEW_TYPENAME_PARSING CodeParams params_nested = NullCode; @@ -11795,7 +11816,7 @@ else if ( currtok.Type == Tok_DeclType ) is_function_typename = true; ++scanner; } - is_function_typename = scanner->Type == Tok_Capture_Start; + is_function_typename = scanner->Type == Tok_Paren_Open; Token* first_capture = scanner; if ( is_function_typename ) @@ -11805,7 +11826,7 @@ else if ( currtok.Type == Tok_DeclType ) ++scanner; // Go back to the first capture start found - while ( scanner->Type != Tok_Capture_Start ) + while ( scanner->Type != Tok_Paren_Open ) --scanner; last_capture = scanner; @@ -11839,7 +11860,7 @@ else if ( currtok.Type == Tok_DeclType ) // StrBuilder // name_stripped = StrBuilder::make( FallbackAllocator, name ); // name_stripped.strip_space(); - return_type->Name = cache_str( tok_to_str(name) ); + return_type->Name = cache_str( name.Text ); #ifdef GEN_USE_NEW_TYPENAME_PARSING if ( specifiers ) @@ -11850,7 +11871,7 @@ else if ( currtok.Type == Tok_DeclType ) #else if ( NumSpecifiers ) - return_type->Specs = def_specifiers( NumSpecifiers, ( Specifier* )specs_found ); + return_type->Specs = def_specifiers_arr( NumSpecifiers, ( Specifier* )specs_found ); // Reset specifiers, the function itself will have its own suffix specifiers possibly. NumSpecifiers = 0; @@ -11859,7 +11880,7 @@ else if ( currtok.Type == Tok_DeclType ) name = NullToken; // The next token can either be a capture for the identifier or it could be the identifier exposed. - if ( ! check( Tok_Capture_Start ) ) + if ( ! check( Tok_Paren_Open ) ) { // Started with an identifier immeidately, which means its of the format: ; name = parse_identifier(nullptr); @@ -11879,7 +11900,7 @@ else if ( currtok.Type == Tok_DeclType ) // Parse immeidate capture which would be with parse_params() // Eat Capture End #ifdef GEN_USE_NEW_TYPENAME_PARSING - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); // ( // Binding specifiers @@ -11901,7 +11922,7 @@ else if ( currtok.Type == Tok_DeclType ) if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } NumSpecifiers = 0; // ( @@ -11912,11 +11933,11 @@ else if ( currtok.Type == Tok_DeclType ) // Immeidate parameters - if ( check( Tok_Capture_Start ) ) + if ( check( Tok_Paren_Open ) ) params_nested = parse_params(); // ( ( ) - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // ( ( ) ) #else @@ -11924,21 +11945,21 @@ else if ( currtok.Type == Tok_DeclType ) // Everything within this capture will just be shoved into the name field including the capture tokens themselves. name = currtok; - eat( Tok_Capture_Start ); + eat( Tok_Paren_Open ); // ( s32 level = 0; - while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) ) + while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) ) { - if ( currtok.Type == Tok_Capture_Start ) + if ( currtok.Type == Tok_Paren_Open ) level++; - if ( currtok.Type == Tok_Capture_End ) + if ( currtok.Type == Tok_Paren_Close ) level--; eat( currtok.Type ); } - eat( Tok_Capture_End ); + eat( Tok_Paren_Close ); // ( ) name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr; @@ -11952,14 +11973,14 @@ else if ( currtok.Type == Tok_DeclType ) // Look for suffix specifiers for the function while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); if ( spec != Spec_Const // TODO : Add support for NoExcept, l-value, volatile, l-value, etc // && spec != Spec_NoExcept && spec != Spec_RValue ) { - log_failure( "Error, invalid specifier used in type definition: %S\n%S", tok_to_str(currtok), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); + log_failure( "Error, invalid specifier used in type definition: %S\n%S", currtok.Text, strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) ); parser_pop(& _ctx->parser); return InvalidCode; } @@ -11972,7 +11993,7 @@ else if ( currtok.Type == Tok_DeclType ) #ifdef GEN_USE_NEW_TYPENAME_PARSING if ( NumSpecifiers ) { - func_suffix_specs = def_specifiers( NumSpecifiers, specs_found ); + func_suffix_specs = def_specifiers_arr( NumSpecifiers, specs_found ); NumSpecifiers = 0; } #endif @@ -11993,7 +12014,7 @@ else if ( currtok.Type == Tok_DeclType ) // result->Token = _ctx->parser.Scope->Start; // Need to wait until were using the new parsing method to do this. - StrBuilder name_stripped = parser_strip_formatting( tok_to_str(name), parser_strip_formatting_dont_preserve_newlines ); + StrBuilder name_stripped = parser_strip_formatting( name.Text, parser_strip_formatting_dont_preserve_newlines ); // name_stripped.strip_space(); @@ -12022,7 +12043,7 @@ else if ( currtok.Type == Tok_DeclType ) #else if ( NumSpecifiers ) { - CodeSpecifiers specifiers = def_specifiers( NumSpecifiers, ( Specifier* )specs_found ); + CodeSpecifiers specifiers = def_specifiers_arr( NumSpecifiers, ( Specifier* )specs_found ); result->Specs = specifiers; } #endif @@ -12252,7 +12273,7 @@ CodeTypedef parser_parse_typedef() } else { - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); result->IsFunction = false; } @@ -12296,7 +12317,7 @@ CodeUnion parser_parse_union( bool inplace_def ) Str name = { nullptr, 0 }; if ( check( Tok_Identifier ) ) { - name = tok_to_str(currtok); + name = currtok.Text; _ctx->parser.Scope->Name = currtok.Text; eat( Tok_Identifier ); } @@ -12487,7 +12508,7 @@ CodeUsing parser_parse_using() CodeUsing result = (CodeUsing) make_code(); - result->Name = cache_str( tok_to_str(name) ); + result->Name = cache_str( name.Text ); result->ModuleFlags = mflags; if ( is_namespace) @@ -12538,7 +12559,7 @@ CodeVar parser_parse_variable() while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); switch ( spec ) { GEN_PARSER_VARIABLE_ALLOWED_SPECIFIER_CASES: @@ -12560,17 +12581,10 @@ CodeVar parser_parse_variable() } if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); } // - // Note(Ed): We're enforcing that using this codepath requires non-macro jank. - // Code macro_stmt = parse_macro_as_definiton(attributes, specifiers); - // if (macro_stmt) { - // parser_pop(& _ctx->parser); - // return macro_stmt; - // } - CodeTypename type = parser_parse_type(parser_not_from_template, nullptr); // @@ -12631,7 +12645,7 @@ CodeConstructor parse_constructor( Str def ) while ( left && tok_is_specifier(currtok) ) { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); + Specifier spec = str_to_specifier( currtok.Text ); b32 ignore_spec = false; @@ -12665,7 +12679,7 @@ CodeConstructor parse_constructor( Str def ) if ( NumSpecifiers ) { - specifiers = def_specifiers( NumSpecifiers, specs_found ); + specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); // ... } diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/gen.dep.hpp b/Project/Source/GasaEditor/GasaGen/gencpp/gen.dep.hpp index 37177fc..4876085 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/gen.dep.hpp +++ b/Project/Source/GasaEditor/GasaGen/gencpp/gen.dep.hpp @@ -270,11 +270,11 @@ GEN_NS_BEGIN #define src_line_str stringize( __LINE__ ) #ifndef do_once -#define do_once() \ - static int __do_once_counter_##src_line_str = 0; \ +#define do_once() \ + local_persist int __do_once_counter_##src_line_str = 0; \ for ( ; __do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1 ) -#define do_once_defer( expression ) \ - static int __do_once_counter_##src_line_str = 0; \ +#define do_once_defer( expression ) \ + local_persist int __do_once_counter_##src_line_str = 0; \ for ( ; __do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1, ( expression ) ) #define do_once_start \ do \ @@ -852,10 +852,10 @@ template mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem #if GEN_BUILD_DEBUG # if defined( GEN_COMPILER_MSVC ) # if _MSC_VER < 1300 -#pragma message("GEN_BUILD_DEBUG: __asm int 3") +// #pragma message("GEN_BUILD_DEBUG: __asm int 3") # define GEN_DEBUG_TRAP() __asm int 3 /* Trap to debugger! */ # else -#pragma message("GEN_BUILD_DEBUG: __debugbreak()") +// #pragma message("GEN_BUILD_DEBUG: __debugbreak()") # define GEN_DEBUG_TRAP() __debugbreak() # endif # elif defined( GEN_COMPILER_TINYC ) @@ -864,7 +864,7 @@ template mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem # define GEN_DEBUG_TRAP() __builtin_trap() # endif #else -#pragma message("GEN_BUILD_DEBUG: omitted") +// #pragma message("GEN_BUILD_DEBUG: omitted") # define GEN_DEBUG_TRAP() #endif @@ -2182,10 +2182,9 @@ bool array_fill(Array array, usize begin, usize end, Type value) ArrayHeader* header = array_get_header(array); if (begin < 0 || end > header->Num) - return false; + return false; - for (ssize idx = ssize(begin); idx < ssize(end); idx++) - { + for (ssize idx = ssize(begin); idx < ssize(end); idx++) { array[idx] = value; } @@ -2654,7 +2653,7 @@ HashTableFindResult hashtable__find(HashTable table, u64 key) if (table.Entries[result.EntryIndex].Key == key) break; - result.PrevIndex = result.EntryIndex; + result.PrevIndex = result.EntryIndex; result.EntryIndex = table.Entries[result.EntryIndex].Next; } } diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/gen.hpp b/Project/Source/GasaEditor/GasaGen/gencpp/gen.hpp index 2e5a9f6..d2fa92f 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/gen.hpp +++ b/Project/Source/GasaEditor/GasaGen/gencpp/gen.hpp @@ -42,7 +42,7 @@ | \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l | | Unreal Engine | | | | __} | | | l_l l_l {___/ | - ! ----------------------------------------------------------------------- VERSION: v0.20-Alpha | + ! ----------------------------------------------------------------------- VERSION: v0.23-Alpha | ! ============================================================================================ | ! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION | ! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL | @@ -605,7 +605,18 @@ inline Str spec_to_str( Specifier type ) inline bool spec_is_trailing( Specifier specifier ) { - return specifier > Spec_Virtual; + switch ( specifier ) + { + case Spec_Const : + case Spec_Final : + case Spec_NoExceptions : + case Spec_Override : + case Spec_Pure : + case Spec_Volatile : + return true; + default : + return false; + } } inline Specifier str_to_specifier( Str str ) @@ -663,8 +674,8 @@ enum TokType : u32 Tok_BraceCurly_Close, Tok_BraceSquare_Open, Tok_BraceSquare_Close, - Tok_Capture_Start, - Tok_Capture_End, + Tok_Paren_Open, + Tok_Paren_Close, Tok_Comment, Tok_Comment_End, Tok_Comment_Start, @@ -923,11 +934,6 @@ AccessSpec tok_to_access_specifier(Token tok) { return scast(AccessSpec, tok.Type); } -FORCEINLINE -Str tok_to_str(Token tok) { - return tok.Text; -} - FORCEINLINE bool tok_is_valid( Token tok ) { return tok.Text.Ptr && tok.Text.Len && tok.Type != Tok_Invalid; @@ -1012,8 +1018,6 @@ 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 @@ -1040,8 +1044,6 @@ Str macrotype_to_str( MacroType type ) { "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 }, @@ -1144,7 +1146,7 @@ struct AST_Pragma; struct AST_PreprocessCond; struct AST_Specifiers; -#if GEN_EXECUTION_EXPRESSION_SUPPORT +#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT struct AST_Expr; struct AST_Expr_Assign; struct AST_Expr_Alignof; @@ -1241,7 +1243,7 @@ struct CodePragma; struct CodeSpecifiers; #endif -#if GEN_EXECUTION_EXPRESSION_SUPPORT +#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT #if GEN_COMPILER_C typedef AST_Expr* CodeExpr; @@ -1916,7 +1918,7 @@ struct CodeExec AST_Exec *ast; }; -#if GEN_EXECUTION_EXPRESSION_SUPPORT +#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT struct CodeExpr { #if ! GEN_C_LIKE_CPP @@ -2243,7 +2245,7 @@ struct CodePreprocessCond AST_PreprocessCond* ast; }; -#if GEN_EXECUTION_EXPRESSION_SUPPORT +#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT struct CodeStmt { #if ! GEN_C_LIKE_CPP @@ -2750,16 +2752,16 @@ GEN_OPITMIZE_MAPPINGS_END struct AST_Body { union { - char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; + char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; - Code Front; - Code Back; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; - s32 NumEntries; + StrCached Name; + Code Front; + Code Back; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + s32 NumEntries; }; static_assert( sizeof(AST_Body) == sizeof(AST), "ERROR: AST_Body is not the same size as AST"); @@ -2768,7 +2770,7 @@ struct AST_Attributes { union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; - StrCached Content; + StrCached Content; }; StrCached Name; Code Prev; @@ -2786,7 +2788,7 @@ struct AST_BaseClass union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2803,7 +2805,7 @@ struct AST_Comment char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; StrCached Content; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2821,14 +2823,14 @@ struct AST_Class { CodeComment InlineCmt; // Only supported by forward declarations CodeAttributes Attributes; - char _PAD_SPECS_ [ sizeof(AST*) ]; + char _PAD_SPECS_ [ sizeof(AST*) ]; CodeTypename ParentType; - char _PAD_PARAMS_[ sizeof(AST*) ]; + char _PAD_PARAMS_[ sizeof(AST*) ]; CodeBody Body; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; + StrCached Name; CodeTypename Prev; CodeTypename Next; Token* Tok; @@ -2851,10 +2853,10 @@ struct AST_Constructor Code InitializerList; CodeParams Params; Code Body; - char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ]; + char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ]; }; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2876,13 +2878,13 @@ struct AST_Define char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 1 ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the same size as AST"); @@ -2897,7 +2899,7 @@ struct AST_DefineParams Token* Tok; Code Parent; CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; s32 NumEntries; }; static_assert( sizeof(AST_DefineParams) == sizeof(AST), "ERROR: AST_DefineParams is not the same size as AST"); @@ -2913,10 +2915,10 @@ struct AST_Destructor CodeSpecifiers Specs; char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ]; Code Body; - char _PAD_PROPERTIES_3_ [ sizeof(AST*) ]; + char _PAD_PROPERTIES_3_ [ sizeof(AST*) ]; }; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2938,10 +2940,10 @@ struct AST_Enum CodeTypename UnderlyingType; Code UnderlyingTypeMacro; CodeBody Body; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2958,7 +2960,7 @@ struct AST_Exec char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; StrCached Content; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; @@ -2968,7 +2970,7 @@ struct AST_Exec }; static_assert( sizeof(AST_Exec) == sizeof(AST), "ERROR: AST_Exec is not the same size as AST"); -#if GEN_EXECUTION_EXPRESSION_SUPPORT +#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT struct AST_Expr { union { @@ -3236,13 +3238,13 @@ struct AST_Extern char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_Extern) == sizeof(AST), "ERROR: AST_Extern is not the same size as AST"); @@ -3252,13 +3254,13 @@ struct AST_Include char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; StrCached Content; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_Include) == sizeof(AST), "ERROR: AST_Include is not the same size as AST"); @@ -3271,16 +3273,16 @@ struct AST_Friend CodeComment InlineCmt; char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ]; Code Declaration; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_Friend) == sizeof(AST), "ERROR: AST_Friend is not the same size as AST"); @@ -3294,19 +3296,19 @@ struct AST_Fn CodeAttributes Attributes; CodeSpecifiers Specs; CodeTypename ReturnType; - CodeParams Params; + CodeParams Params; CodeBody Body; - char _PAD_PROPERTIES_ [ sizeof(AST*) ]; + char _PAD_PROPERTIES_ [ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - char _PAD_UNUSED_[ sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + char _PAD_UNUSED_[ sizeof(u32) ]; }; static_assert( sizeof(AST_Fn) == sizeof(AST), "ERROR: AST_Fn is not the same size as AST"); @@ -3315,14 +3317,14 @@ struct AST_Module union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; Token* Tok; Code Parent; CodeType Type; ModuleFlag ModuleFlags; - char _PAD_UNUSED_[ sizeof(u32) ]; + char _PAD_UNUSED_[ sizeof(u32) ]; }; static_assert( sizeof(AST_Module) == sizeof(AST), "ERROR: AST_Module is not the same size as AST"); @@ -3331,45 +3333,45 @@ struct AST_NS union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; struct { - char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ]; + char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ]; CodeBody Body; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - char _PAD_UNUSED_[ sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + char _PAD_UNUSED_[ sizeof(u32) ]; }; static_assert( sizeof(AST_NS) == sizeof(AST), "ERROR: AST_NS is not the same size as AST"); struct AST_Operator { union { - char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; + char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; struct { - CodeComment InlineCmt; - CodeAttributes Attributes; - CodeSpecifiers Specs; - CodeTypename ReturnType; - CodeParams Params; - CodeBody Body; - char _PAD_PROPERTIES_ [ sizeof(AST*) ]; + CodeComment InlineCmt; + CodeAttributes Attributes; + CodeSpecifiers Specs; + CodeTypename ReturnType; + CodeParams Params; + CodeBody Body; + char _PAD_PROPERTIES_ [ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - Operator Op; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + Operator Op; }; static_assert( sizeof(AST_Operator) == sizeof(AST), "ERROR: AST_Operator is not the same size as AST"); @@ -3379,22 +3381,22 @@ struct AST_OpCast char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; struct { - CodeComment InlineCmt; - char _PAD_PROPERTIES_[ sizeof(AST*) ]; - CodeSpecifiers Specs; - CodeTypename ValueType; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; - CodeBody Body; - char _PAD_PROPERTIES_3_[ sizeof(AST*) ]; + CodeComment InlineCmt; + char _PAD_PROPERTIES_[ sizeof(AST*) ]; + CodeSpecifiers Specs; + CodeTypename ValueType; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + CodeBody Body; + char _PAD_PROPERTIES_3_[ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_OpCast) == sizeof(AST), "ERROR: AST_OpCast is not the same size as AST"); @@ -3405,7 +3407,7 @@ struct AST_Params struct { // TODO(Ed): Support attributes for parameters (Some prefix macros can be converted to that...) - char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ]; CodeTypename ValueType; Code Macro; Code Value; @@ -3413,14 +3415,14 @@ struct AST_Params // char _PAD_PROPERTIES_3_[sizeof( AST* )]; }; }; - StrCached Name; - CodeParams Last; - CodeParams Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; - s32 NumEntries; + StrCached Name; + CodeParams Last; + CodeParams Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + s32 NumEntries; }; static_assert( sizeof(AST_Params) == sizeof(AST), "ERROR: AST_Params is not the same size as AST"); @@ -3430,13 +3432,13 @@ struct AST_Pragma char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; StrCached Content; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_Pragma) == sizeof(AST), "ERROR: AST_Pragma is not the same size as AST"); @@ -3444,40 +3446,40 @@ struct AST_PreprocessCond { union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; - StrCached Content; + StrCached Content; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; }; static_assert( sizeof(AST_PreprocessCond) == sizeof(AST), "ERROR: AST_PreprocessCond is not the same size as AST"); struct AST_Specifiers { - Specifier ArrSpecs[ AST_ArrSpecs_Cap ]; + Specifier ArrSpecs[ AST_ArrSpecs_Cap ]; StrCached Name; - CodeSpecifiers NextSpecs; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; - s32 NumEntries; + CodeSpecifiers NextSpecs; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + s32 NumEntries; }; static_assert( sizeof(AST_Specifiers) == sizeof(AST), "ERROR: AST_Specifier is not the same size as AST"); -#if GEN_EXECUTION_EXPRESSION_SUPPORT +#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT struct AST_Stmt { union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3492,7 +3494,7 @@ struct AST_Stmt_Break union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3507,7 +3509,7 @@ struct AST_Stmt_Case union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3522,7 +3524,7 @@ struct AST_Stmt_Continue union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3537,7 +3539,7 @@ struct AST_Stmt_Decl union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3552,7 +3554,7 @@ struct AST_Stmt_Do union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3567,7 +3569,7 @@ struct AST_Stmt_Expr union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3582,7 +3584,7 @@ struct AST_Stmt_Else union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3597,7 +3599,7 @@ struct AST_Stmt_If union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3612,7 +3614,7 @@ struct AST_Stmt_For union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3627,7 +3629,7 @@ struct AST_Stmt_Goto union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3642,7 +3644,7 @@ struct AST_Stmt_Label union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3657,7 +3659,7 @@ struct AST_Stmt_Switch union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3672,7 +3674,7 @@ struct AST_Stmt_While union { char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; }; - StrCached Name; + StrCached Name; CodeExpr Prev; CodeExpr Next; Token* Tok; @@ -3691,14 +3693,14 @@ struct AST_Struct { CodeComment InlineCmt; CodeAttributes Attributes; - char _PAD_SPECS_ [ sizeof(AST*) ]; + char _PAD_SPECS_ [ sizeof(AST*) ]; CodeTypename ParentType; - char _PAD_PARAMS_[ sizeof(AST*) ]; + char _PAD_PARAMS_[ sizeof(AST*) ]; CodeBody Body; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; + StrCached Name; CodeTypename Prev; CodeTypename Next; Token* Tok; @@ -3715,20 +3717,20 @@ struct AST_Template char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ]; struct { - char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ]; + char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ]; CodeParams Params; Code Declaration; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - char _PAD_UNUSED_[ sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + char _PAD_UNUSED_[ sizeof(u32) ]; }; static_assert( sizeof(AST_Template) == sizeof(AST), "ERROR: AST_Template is not the same size as AST"); @@ -3750,13 +3752,13 @@ struct AST_Type // CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures }; }; - StrCached Name; + StrCached Name; Code Prev; Code Next; - Token* Tok; + Token* Tok; Code Parent; CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; b32 IsParamPack; }; static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same size as AST"); @@ -3783,7 +3785,7 @@ struct AST_Typename Token* Tok; Code Parent; CodeType Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; struct { b16 IsParamPack; // Used by typename to know if type should be considered a parameter pack. ETypenameTag TypeTag; // Used by typename to keep track of explicitly declared tags for the identifier (enum, struct, union) @@ -3798,9 +3800,9 @@ struct AST_Typedef struct { CodeComment InlineCmt; - char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ]; + char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ]; Code UnderlyingType; - char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ]; }; }; StrCached Name; @@ -3822,19 +3824,19 @@ struct AST_Union { char _PAD_INLINE_CMT_[ sizeof(AST*) ]; CodeAttributes Attributes; - char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ]; + char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ]; CodeBody Body; - char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; + char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - char _PAD_UNUSED_[ sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + char _PAD_UNUSED_[ sizeof(u32) ]; }; static_assert( sizeof(AST_Union) == sizeof(AST), "ERROR: AST_Union is not the same size as AST"); @@ -3846,19 +3848,19 @@ struct AST_Using { CodeComment InlineCmt; CodeAttributes Attributes; - char _PAD_SPECS_ [ sizeof(AST*) ]; + char _PAD_SPECS_ [ sizeof(AST*) ]; CodeTypename UnderlyingType; - char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ]; + char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ]; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - char _PAD_UNUSED_[ sizeof(u32) ]; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + char _PAD_UNUSED_[ sizeof(u32) ]; }; static_assert( sizeof(AST_Using) == sizeof(AST), "ERROR: AST_Using is not the same size as AST"); @@ -3874,17 +3876,17 @@ struct AST_Var CodeTypename ValueType; Code BitfieldSize; Code Value; - CodeVar NextVar; + CodeVar NextVar; }; }; - StrCached Name; - Code Prev; - Code Next; - Token* Tok; - Code Parent; - CodeType Type; - ModuleFlag ModuleFlags; - s32 VarParenthesizedInit; + StrCached Name; + Code Prev; + Code Next; + Token* Tok; + Code Parent; + CodeType Type; + ModuleFlag ModuleFlags; + s32 VarParenthesizedInit; }; static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST"); @@ -3982,6 +3984,9 @@ struct Context // TODO(Ed): Active parse context vs a parse result need to be separated conceptually ParseContext parser; + + // TODO(Ed): Formatting - This will eventually be in a separate struct when in the process of serialization of the builder. + s32 temp_serialize_indent; }; // Initialize the library. There first ctx initialized must exist for lifetime of other contextes that come after as its the one that @@ -4010,7 +4015,11 @@ 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 ); +GEN_API void register_macros_arr( s32 num, Macro* macros ); + +#if GEN_COMPILER_CPP +FORCEINLINE void register_macros( s32 num, Macro* macros ) { return register_macros_arr(num, macros); } +#endif // Used internally to retrive or make string allocations. // Strings are stored in a series of string arenas of fixed size (SizePer_StringArena) @@ -4165,37 +4174,50 @@ 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 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 ); +GEN_API CodeBody def_class_body ( s32 num, ... ); +GEN_API CodeBody def_class_body_arr ( s32 num, Code* codes ); +GEN_API CodeDefineParams def_define_params ( s32 num, ... ); +GEN_API CodeDefineParams def_define_params_arr ( s32 num, CodeDefineParams* codes ); +GEN_API CodeBody def_enum_body ( s32 num, ... ); +GEN_API CodeBody def_enum_body_arr ( s32 num, Code* codes ); +GEN_API CodeBody def_export_body ( s32 num, ... ); +GEN_API CodeBody def_export_body_arr ( s32 num, Code* codes); +GEN_API CodeBody def_extern_link_body ( s32 num, ... ); +GEN_API CodeBody def_extern_link_body_arr ( s32 num, Code* codes ); +GEN_API CodeBody def_function_body ( s32 num, ... ); +GEN_API CodeBody def_function_body_arr ( s32 num, Code* codes ); +GEN_API CodeBody def_global_body ( s32 num, ... ); +GEN_API CodeBody def_global_body_arr ( s32 num, Code* codes ); +GEN_API CodeBody def_namespace_body ( s32 num, ... ); +GEN_API CodeBody def_namespace_body_arr ( s32 num, Code* codes ); +GEN_API CodeParams def_params ( s32 num, ... ); +GEN_API CodeParams def_params_arr ( s32 num, CodeParams* params ); +GEN_API CodeSpecifiers def_specifiers ( s32 num, ... ); +GEN_API CodeSpecifiers def_specifiers_arr ( s32 num, Specifier* specs ); +GEN_API CodeBody def_struct_body ( s32 num, ... ); +GEN_API CodeBody def_struct_body_arr ( s32 num, Code* codes ); +GEN_API CodeBody def_union_body ( s32 num, ... ); +GEN_API CodeBody def_union_body_arr ( s32 num, Code* codes ); + +#if GEN_COMPILER_CPP +FORCEINLINE CodeBody def_class_body ( s32 num, Code* codes ) { return def_class_body_arr(num, codes); } +FORCEINLINE CodeDefineParams def_define_params ( s32 num, CodeDefineParams* codes ) { return def_define_params_arr(num, codes); } +FORCEINLINE CodeBody def_enum_body ( s32 num, Code* codes ) { return def_enum_body_arr(num, codes); } +FORCEINLINE CodeBody def_export_body ( s32 num, Code* codes) { return def_export_body_arr(num, codes); } +FORCEINLINE CodeBody def_extern_link_body( s32 num, Code* codes ) { return def_extern_link_body_arr(num, codes); } +FORCEINLINE CodeBody def_function_body ( s32 num, Code* codes ) { return def_function_body_arr(num, codes); } +FORCEINLINE CodeBody def_global_body ( s32 num, Code* codes ) { return def_global_body_arr(num, codes); } +FORCEINLINE CodeBody def_namespace_body ( s32 num, Code* codes ) { return def_namespace_body_arr(num, codes); } +FORCEINLINE CodeParams def_params ( s32 num, CodeParams* params ) { return def_params_arr(num, params); } +FORCEINLINE CodeSpecifiers def_specifiers ( s32 num, Specifier* specs ) { return def_specifiers_arr(num, specs); } +FORCEINLINE CodeBody def_struct_body ( s32 num, Code* codes ) { return def_struct_body_arr(num, codes); } +FORCEINLINE CodeBody def_union_body ( s32 num, Code* codes ) { return def_union_body_arr(num, codes); } +#endif #pragma endregion Upfront #pragma region Parsing -// TODO(Ed) : Implmeent the new parser API design. - #if 0 struct StackNode {