diff --git a/Readme.md b/Readme.md index 61c2a78..3cb7968 100644 --- a/Readme.md +++ b/Readme.md @@ -5,26 +5,26 @@ An attempt at simple staged metaprogramming for C/C++. The library API is a composition of code element constructors, and a non-standards-compliant single-pass C/C++ parser. These build up a code AST to then serialize with a file builder, or can be traversed for staged-reflection of C/C++ code. -This code base attempts follow the [handmade philosophy](https://handmade.network/manifesto). -Its not meant to be a black box metaprogramming utility, it should be easy to intergrate into a user's project domain. +This code base attempts follow the [handmade philosophy](https://handmade.network/manifesto). +Its not meant to be a black box metaprogramming utility, it should be easy to intergrate into a user's project domain. + +# Documentation + +[] ## Notes -**On Partial Hiatus: Life has got me tackling other issues..** -I will be passively updating the library with bug fixes and minor improvements as I use it for my personal projects. +**On Partial Hiatus: Life has got me tackling other issues..** +I will be passively updating the library with bug fixes and minor improvements as I use it for my personal projects. There won't be any major reworks or features to this thing for a while. -This project is still in development (very much an alpha state), so expect bugs and missing features. +This project is still in development (very much an alpha state), so expect bugs and missing features. See [issues](https://github.com/Ed94/gencpp/issues) for a list of known bugs or todos. The library can already be used to generate code just fine, but the parser is where the most work is needed. If your C++ isn't "down to earth" expect issues. A `natvis` and `natstepfilter` are provided in the scripts directory (its outdated, I'll update this readme when its not). -***The editor and scanner have not been implemented yet. The scanner will come first, then the editor.*** - -A C variant is hosted [here](https://github.com/Ed94/genc); I will complete it when this library is feature complete, it should be easier to make than this... - ## Usage A metaprogram is built to generate files before the main program is built. We'll term runtime for this program as `GEN_TIME`. The metaprogram's core implementation are within `gen.hpp` and `gen.cpp` in the project directory. @@ -56,7 +56,7 @@ u32 gen_main() #endif ``` -The design uses a constructive builder API for the code to generate. +The design uses a constructive builder API for the code to generate. The user is provided `Code` objects that are used to build up the AST. Example using each construction interface: @@ -112,8 +112,8 @@ Code header = code_str( ); ``` -`name` is a helper macro for providing a string literal with its size, intended for the name parameter of functions. -`code` is a helper macro for providing a string literal with its size, but intended for code string parameters. +`name` is a helper macro for providing a string literal with its size, intended for the name parameter of functions. +`code` is a helper macro for providing a string literal with its size, but intended for code string parameters. `args` is a helper macro for providing the number of arguments to varadic constructors. `code_str` is a helper macro for writting `untyped_str( code( ))` diff --git a/base/Readme.md b/base/Readme.md index efd2160..b121aa7 100644 --- a/base/Readme.md +++ b/base/Readme.md @@ -25,19 +25,6 @@ Standard formats: Code not making up the core library is located in `auxiliary/.`. These are optional extensions or tools for the library. -Feature Macros: - -* `GEN_DEFINE_ATTRIBUTE_TOKENS` : Allows user to define their own attribute macros for use in parsing. - * This is auto-generated if using the bootstrap or single-header generation - * *Note: The user will use the `AttributeTokens.csv` when the library is fully self-hosting.* -* `GEN_DEFINE_LIBRARY_CORE_CONSTANTS` : Optional typename codes as they are non-standard to C/C++ and not necessary to library usage -* `GEN_DONT_ENFORCE_GEN_TIME_GUARD` : By default, the library ( gen.hpp/ gen.cpp ) expects the macro `GEN_TIME` to be defined, this disables that. -* `GEN_ENFORCE_STRONG_CODE_TYPES` : Enforces casts to filtered code types. -* `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` : 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 *Note: A variant of the C++ library could be generated where those additonal support features are removed (see gen_c_library implementation for an idea of how)* diff --git a/docs/Readme.md b/docs/Readme.md index 2ba612f..ad0b0c7 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -14,7 +14,7 @@ The project has no external dependencies beyond: * `io.h` (Windows with gcc) * `windows.h` (Windows) -Dependencies for the project are wrapped within `GENCPP_ROLL_OWN_DEPENDENCIES` (Defining it will disable them). +Dependencies for the project are wrapped within `GENCPP_ROLL_OWN_DEPENDENCIES` (Defining it will disable them). The majority of the dependency's implementation was derived from the [c-zpl library](https://github.com/zpl-c/zpl). This library was written in a subset of C++ where the following are not used at all: @@ -24,10 +24,10 @@ This library was written in a subset of C++ where the following are not used at * Object-Oriented Inheritance * Exceptions -Polymorphic & Member-functions are used as an ergonomic choice, along with a conserative use of operator overloads. +Polymorphic & Member-functions are used as an ergonomic choice, along with a conserative use of operator overloads. The base library itself does not use anything but C-like features to allow for generating a derviative compatiable with C (WIP). -There are only 4 template definitions in the entire library. (`Array`, `Hashtable`, `swap`, and `AST/Code::cast`) +There are only 4 template definitions in the entire library (C++ versions). (`Array`, `Hashtable`, `swap`, and `AST/Code::cast`) Two generic templated containers are used throughout the library: @@ -43,94 +43,46 @@ Otherwise the library is free of any templates. ### *WHAT IS NOT PROVIDED* **There is no support for validating expressions.** -Its difficult to parse without enough benefits (At the metaprogramming level). -I plan to add this only at the tail of the project parsing milestone. +Its a [todo](https://github.com/Ed94/gencpp/issues/49) -**Only trivial template support is provided.** -The intention is for only simple, non-recursive substitution. -The parameters of the template are treated like regular parameter AST entries. +**Only trivial template support is provided.** +The intention is for only simple, non-recursive substitution. +The parameters of the template are treated like regular parameter AST entries. This means that the typename entry for the parameter AST would be either: * `class` * `typename` * A fundamental type, function, or pointer type. -Anything beyond this usage is not supported by parse_template for arguments (at least not intentionally). -Use at your own mental peril. +***Concepts and Constraints are not supported*** +Its a [todo](https://github.com/Ed94/gencpp/issues/21) -*Concepts and Constraints are not supported, its usage is non-trivial substitution.* +### Feature Macros: + +* `GEN_DEFINE_ATTRIBUTE_TOKENS` : Allows user to define their own attribute macros for use in parsing. + * This is auto-generated if using the bootstrap or single-header generation + * *Note: The user will use the `AttributeTokens.csv` when the library is fully self-hosting.* +* `GEN_DEFINE_LIBRARY_CORE_CONSTANTS` : Optional typename codes as they are non-standard to C/C++ and not necessary to library usage +* `GEN_DONT_ENFORCE_GEN_TIME_GUARD` : By default, the library ( gen.hpp/ gen.cpp ) expects the macro `GEN_TIME` to be defined, this disables that. +* `GEN_ENFORCE_STRONG_CODE_TYPES` : Enforces casts to filtered code types. +* `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` : 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 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. +The AST is managed by the library and provided to the user via its interface. However, the user may specifiy memory configuration. -Data layout of AST struct (Subject to heavily change with upcoming redesign): +[Data layout of AST struct (Subject to heavily change with upcoming todos)](C:\projects\gencpp\base\components\ast.hpp#L396-462) -```cpp -union { - struct - { - AST* InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable - AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable - AST* Specs; // Destructor, Function, Operator, Typename, Variable - union { - AST* InitializerList; // Constructor - AST* ParentType; // Class, Struct, ParentType->Next has a possible list of interfaces. - AST* ReturnType; // Function, Operator, Typename - AST* UnderlyingType; // Enum, Typedef - AST* ValueType; // Parameter, Variable - }; - union { - AST* Macro; // Parameters - AST* BitfieldSize; // Variable (Class/Struct Data Member) - AST* Params; // Constructor, Function, Operator, Template, Typename - }; - union { - AST* ArrExpr; // Typename - AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union - AST* Declaration; // Friend, Template - AST* Value; // Parameter, Variable - }; - union { - AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) - AST* SpecsFuncSuffix; // Only used with typenames, to store the function suffix if typename is function signature. - }; - }; - StringCached Content; // Attributes, Comment, Execution, Include - struct { - SpecifierT ArrSpecs[AST_ArrSpecs_Cap]; // Specifiers - AST* NextSpecs; // Specifiers - }; -}; -union { - AST* Prev; - AST* Front; - AST* Last; -}; -union { - AST* Next; - AST* Back; -}; -AST* Parent; -StringCached Name; -CodeT Type; -ModuleFlag ModuleFlags; -union { - b32 IsFunction; // Used by typedef to not serialize the name field. - b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack. - OperatorT Op; - AccessSpec ParentAccess; - s32 NumEntries; -}; -s32 Token; // Handle to the token, stored in the CodeFile (Otherwise unretrivable) -``` - -*`CodeT` is a typedef for `ECode::Type` which has an underlying type of `u32`* -*`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`* -*`StringCahced` is a typedef for `String const`, to denote it is an interned string* +*`CodeT` is a typedef for `ECode::Type` which has an underlying type of `u32`* +*`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`* +*`StringCahced` is a typedef for `String const`, to denote it is an interned string* *`String` is the dynamically allocated string type for the library* AST widths are setup to be AST_POD_Size. @@ -302,7 +254,7 @@ def_global_body( args( ht_entry, array_ht_entry, hashtable )); 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. +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. ### Parse construction @@ -354,7 +306,7 @@ Interface : * untyped_fmt * untyped_token_fmt -During serialization any untyped Code AST has its string value directly injected inline of whatever context the content existed as an entry within. +During serialization any untyped Code AST has its string value directly injected inline of whatever context the content existed as an entry within. Even though these are not validated from somewhat correct c/c++ syntax or components, it doesn't mean that Untyped code can be added as any component of a Code AST: * Untyped code cannot have children, thus there cannot be recursive injection this way. @@ -474,11 +426,8 @@ and have the desired specifiers assigned to them beforehand. There are three provided auxillary interfaces: * Builder -* Editor * Scanner -Editor and Scanner are disabled by default, use `GEN_FEATURE_EDITOR` and `GEN_FEATURE_SCANNER` to enable them. - ### Builder is a similar object to the jai language's string_builder * The purpose of it is to generate a file. diff --git a/scripts/build.ci.ps1 b/scripts/build.ci.ps1 index dcf10ed..f31d68c 100644 --- a/scripts/build.ci.ps1 +++ b/scripts/build.ci.ps1 @@ -3,36 +3,15 @@ # That or just rewrite it in an sh script and call it a day. $devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1' -$format_cpp = Join-Path $PSScriptRoot 'helpers/format_cpp.psm1' +$misc = Join-Path $PSScriptRoot 'helpers/misc.psm1' $refactor_c_library = Join-Path $PSScriptRoot 'refactor_c_library.ps1' $refactor_unreal = Join-Path $PSScriptRoot 'refactor_unreal.ps1' $incremental_checks = Join-Path $PSScriptRoot 'helpers/incremental_checks.ps1' $vendor_toolchain = Join-Path $PSScriptRoot 'helpers/vendor_toolchain.ps1' -function Get-ScriptRepoRoot { - $currentPath = $PSScriptRoot - while ($currentPath -ne $null -and $currentPath -ne "") - { - if (Test-Path (Join-Path $currentPath ".git")) { - return $currentPath - } - # Also check for .git file which indicates a submodule - $gitFile = Join-Path $currentPath ".git" - if (Test-Path $gitFile -PathType Leaf) - { - $gitContent = Get-Content $gitFile - if ($gitContent -match "gitdir: (.+)") { - return $currentPath - } - } - $currentPath = Split-Path $currentPath -Parent - } - throw "Unable to find repository root" -} -$path_root = Get-ScriptRepoRoot +Import-Module $misc -# Import-Module $target_arch -Import-Module $format_cpp +$path_root = Get-ScriptRepoRoot Push-Location $path_root diff --git a/scripts/clean.ps1 b/scripts/clean.ps1 index 6c2a78f..1b7642b 100644 --- a/scripts/clean.ps1 +++ b/scripts/clean.ps1 @@ -1,62 +1,42 @@ $path_root = git rev-parse --show-toplevel -$path_project = Join-Path $path_root project -$path_project_build = Join-Path $path_project build -$path_project_gen = Join-Path $path_project gen -$path_singleheader = Join-Path $path_root singleheader +$path_base = Join-Path $path_root base +$path_base_build = Join-Path $path_base build +$path_singleheader = Join-Path $path_root singleheader $path_singleheader_build = Join-Path $path_singleheader build $path_singleheader_gen = Join-Path $path_singleheader gen -$path_test = Join-Path $path_root test -$path_test_build = Join-Path $path_test build -$path_test_gen = Join-Path $path_test gen -$path_x64 = Join-Path $path_root x64 -$path_release = Join-Path $path_root release +$path_unreal = Join-Path $paht_root unreal +$path_unreal_build = Join-Path $path_unreal build +$path_unreal_gen = Join-Path $path_unreal gen +$path_test = Join-Path $path_root test +$path_test_build = Join-Path $path_test build +$path_test_gen = Join-Path $path_test gen +$path_x64 = Join-Path $path_root x64 +$path_release = Join-Path $path_root release -if ( Test-Path $path_project_build) -{ +if ( Test-Path $path_project_build) { Remove-Item $path_project_build -Recurse } - -if ( Test-Path $path_project_gen ) -{ +if ( Test-Path $path_project_gen ) { Remove-Item $path_project_gen -Recurse } - -if ( Test-Path $path_singleheader_build) -{ +if ( Test-Path $path_singleheader_build) { Remove-Item $path_singleheader_build -Recurse } - -if ( Test-Path $path_singleheader_gen ) -{ +if ( Test-Path $path_singleheader_gen ) { Remove-Item $path_singleheader_gen -Recurse } - -if ( Test-Path $path_test_build ) -{ +if ( Test-Path $path_unreal ) { + Remove-Item $path_unreal_build -Recurse +} +if ( Test-Path $path_test_build ) { Remove-Item $path_test_build -Recurse } - -if ( Test-Path $path_test_gen ) -{ +if ( Test-Path $path_test_gen ) { Remove-Item $path_test_gen -Recurse } - -if ( Test-Path $path_x64) -{ +if ( Test-Path $path_x64) { Remove-Item $path_x64 -Recurse } - -if ( Test-Path $path_release ) -{ +if ( Test-Path $path_release ) { Remove-Item $path_release -Recurse } - -$include = '*.h', '*.hpp', '*.cpp' -$exclude = - -$files = Get-ChildItem -Recurse -Path $path_gen -Include $include -Exclude $exclude - -if ( $files ) -{ - Remove-Item $files -} diff --git a/scripts/helpers/misc.psm1 b/scripts/helpers/misc.psm1 new file mode 100644 index 0000000..b547ae1 --- /dev/null +++ b/scripts/helpers/misc.psm1 @@ -0,0 +1,20 @@ +function Get-ScriptRepoRoot { + $currentPath = $PSScriptRoot + while ($currentPath -ne $null -and $currentPath -ne "") + { + if (Test-Path (Join-Path $currentPath ".git")) { + return $currentPath + } + # Also check for .git file which indicates a submodule + $gitFile = Join-Path $currentPath ".git" + if (Test-Path $gitFile -PathType Leaf) + { + $gitContent = Get-Content $gitFile + if ($gitContent -match "gitdir: (.+)") { + return $currentPath + } + } + $currentPath = Split-Path $currentPath -Parent + } + throw "Unable to find repository root" +}