2023-04-02 01:07:44 -04:00
# gencpp
2024-12-15 22:53:32 -05:00
An attempt at simple staged metaprogramming for C/C++. Reflect and generate code for your codebase at runtime!
2024-12-15 23:05:33 -05:00

2024-12-15 23:02:32 -05:00

2023-04-02 01:07:44 -04:00
2024-12-10 19:31:50 -05:00
The library API is a composition of code element constructors, and a non-standards-compliant single-pass C/C++ parser.
2024-12-07 00:21:09 -05:00
These build up a code AST to then serialize with a file builder, or can be traversed for staged-reflection of C/C++ code.
2023-04-22 22:24:55 -04:00
2024-12-12 10:27:55 -05:00
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 integrate into a user's project domain.
2024-12-10 16:38:01 -05:00
2024-12-10 19:31:50 -05:00
## Documentation
2024-12-10 16:38:01 -05:00
2024-12-10 19:31:50 -05:00
* [docs - General ](./docs/Readme.md ): Overview and additional docs
2024-12-12 10:27:55 -05:00
* [AST_Design ](./docs/AST_Design.md ): Overview of ASTs
2024-12-10 19:31:50 -05:00
* [AST Types ](./docs/AST_Types.md ): Listing of all AST types along with their Code type interface.
* [Parsing ](./docs/Parsing.md ): Overview of the parsing interface.
* [Parser Algo ](./docs/Parser_Algo.md ): In-depth breakdown of the parser's implementation.
* [base ](./base/Readme.md ): Essential (base) library.
2024-12-12 10:42:01 -05:00
* [gen_c_library ](./gen_c_library/ ): C11 library variant generation (single header and segmented).
* [gen_segmented ](./gen_segmented/ ): Segmented C++ (`gen.<hpp/cpp>` , `gen.dep.<hpp/cpp>` ) generation
2024-12-11 13:33:35 -05:00
* [gen_singleheader ](./gen_singleheader/ ): Singlehader C++ generation `gen.hpp`
* [gen_unreal_engine ](./gen_unreal_engine/ ): Unreal Engine thirdparty code generation.
2023-07-24 14:30:35 -04:00
2023-04-03 03:55:28 -04:00
## Notes
2024-12-10 19:31:50 -05:00
This project is still in development (very much an alpha state), so expect bugs and missing features.
2023-09-11 18:34:37 -04:00
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.
2023-07-24 11:20:13 -04:00
2024-12-12 10:42:01 -05:00
A `natvis` and `natstepfilter` are provided in the scripts directory (its outdated, I'll update this readme when its not).
*Minor update: I've been using [RAD Debugger ](https://github.com/EpicGamesExt/raddebugger ) with this and the code structures should be easy to debug even without natvis.*
2023-07-15 23:38:53 -04:00
2023-04-04 02:04:19 -04:00
## Usage
2023-04-02 01:07:44 -04:00
2023-07-19 00:14:15 -04:00
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.
2023-04-02 01:07:44 -04:00
2024-12-12 10:42:01 -05:00
`gen.cpp` \`s `main()` is defined as `gen_main()` which the user will have to define once for their program. There they may reflect and/or generate code.
2023-04-02 01:07:44 -04:00
2024-12-07 00:21:09 -05:00
In order to keep the locality of this code within the same files the following pattern may be used (although this pattern isn't the best to use):
2023-04-02 01:07:44 -04:00
Within `program.cpp` :
2023-04-08 02:16:25 -04:00
2023-04-02 01:07:44 -04:00
```cpp
2023-07-19 00:14:15 -04:00
#ifdef GEN_TIME
2023-04-02 01:07:44 -04:00
#include "gen.hpp"
...
u32 gen_main()
{
2024-12-15 22:53:32 -05:00
gen::Context ctx;
gen::init(& ctx);
2023-04-08 02:16:25 -04:00
...
2024-12-15 22:53:32 -05:00
gen::deinit(& ctx);
return 0;
2023-04-02 01:07:44 -04:00
}
#endif
2023-08-08 11:56:42 -04:00
// "Stage" agnostic code.
2023-07-19 00:14:15 -04:00
#ifndef GEN_TIME
2023-04-02 01:07:44 -04:00
#include "program.gen.cpp"
2023-04-08 02:16:25 -04:00
// Regular runtime dependent on the generated code here.
2023-04-02 01:07:44 -04:00
#endif
```
2024-12-10 19:31:50 -05:00
The design uses a constructive builder API for the code to generate.
2023-07-29 05:52:06 -04:00
The user is provided `Code` objects that are used to build up the AST.
2023-04-04 02:04:19 -04:00
2023-04-08 02:16:25 -04:00
Example using each construction interface:
2023-04-22 22:24:55 -04:00
### Upfront
2023-08-08 11:56:42 -04:00
Validation and construction through a functional interface.
2023-04-08 02:16:25 -04:00
```cpp
2024-12-16 21:19:19 -05:00
CodeTypename t_uw = def_type( name(usize) );
CodeTypename t_allocator = def_type( name(allocator) );
CodeTypename t_string_const = def_type( name(char), def_specifiers( args( ESpecifier::Const, ESpecifier::Ptr ) ));
2023-04-08 02:16:25 -04:00
2024-12-16 21:19:19 -05:00
CodeStruct header;
2023-04-08 02:16:25 -04:00
{
2024-12-16 21:19:19 -05:00
CodeVar num = def_variable( t_uw, name(Num) );
CodeVar cap = def_variable( t_uw, name(Capacity) );
CodeVar mem_alloc = def_variable( t_allocator, name(Allocator) );
CodeBody body = def_struct_body( args( num, cap, mem_alloc ) );
2023-04-08 02:16:25 -04:00
2024-12-16 21:19:19 -05:00
header = def_struct( name(ArrayHeader), { body });
2023-04-08 02:16:25 -04:00
}
```
2023-04-22 22:24:55 -04:00
### Parse
2023-04-08 02:16:25 -04:00
2023-08-08 11:56:42 -04:00
Validation through ast construction.
2023-04-08 02:16:25 -04:00
```cpp
2024-12-16 21:19:19 -05:00
CodeStruct header = parse_struct( code(
2023-04-08 02:16:25 -04:00
struct ArrayHeader
{
2024-12-12 10:27:55 -05:00
usize Num;
usize Capacity;
2023-04-08 02:16:25 -04:00
allocator Allocator;
};
));
```
2023-06-29 01:37:42 -04:00
### Untyped
2023-04-08 02:16:25 -04:00
2023-08-08 11:56:42 -04:00
No validation, just glorified text injection.
2023-04-08 02:16:25 -04:00
```cpp
2023-07-24 23:10:10 -04:00
Code header = code_str(
2023-04-22 22:24:55 -04:00
struct ArrayHeader
2023-04-08 02:16:25 -04:00
{
2024-12-12 10:27:55 -05:00
usize Num;
usize Capacity;
2023-04-08 02:16:25 -04:00
allocator Allocator;
2023-04-22 22:24:55 -04:00
};
2023-07-24 23:10:10 -04:00
);
2023-04-08 02:16:25 -04:00
```
2024-12-10 19:31:50 -05:00
`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.
2024-12-12 10:42:01 -05:00
`code_str` is a helper macro for writing `untyped_str( code( <content> ))`
2023-04-08 02:16:25 -04:00
2024-12-12 10:42:01 -05:00
All three construction interfaces will generate the following C code:
2023-04-08 02:16:25 -04:00
2023-04-04 02:04:19 -04:00
```cpp
struct ArrayHeader
{
2024-12-12 10:27:55 -05:00
usize Num;
usize Capacity;
2023-04-04 16:13:48 -04:00
allocator Allocator;
2023-04-04 02:04:19 -04:00
};
```
2023-04-08 02:16:25 -04:00
2024-12-10 19:31:50 -05:00
**Note: The formatting shown here is not how it will look. For your desired formatting its recommended to run a pass through the files with an auto-formatter.**
2023-09-11 18:34:37 -04:00
*(The library currently uses clang-format for formatting, beware its pretty slow...)*
2023-04-04 02:04:19 -04:00
2023-04-02 01:07:44 -04:00
## Building
2024-12-16 17:34:17 -05:00
2024-12-16 17:38:16 -05:00
See the [scripts directory ](scripts/ ).
2024-12-16 17:34:17 -05:00
## Gallery
2024-12-16 17:38:16 -05:00
### Listing definitions in the Cuik Compiler
2024-12-16 20:52:15 -05:00
https://github.com/user-attachments/assets/2302240c-01f1-4e1b-a4b5-292eb3186648
2024-12-16 17:34:17 -05:00
2024-12-16 17:38:16 -05:00
### Unreal: Generating a UAttributeSet from a UDataTable
2024-12-16 17:49:09 -05:00
https://github.com/user-attachments/assets/2a07b743-825d-4f9f-beaf-3559e8748a4d