Staged metaprogramming in C++ for C/C++
Go to file
2024-12-11 14:57:38 -05:00
.vscode Large updates to docs 2024-12-10 19:31:50 -05:00
base minor fixees 2024-12-11 14:57:38 -05:00
docs Updates to docs and various changes to project from working on them. 2024-12-11 13:33:35 -05:00
gen_c_library minor fixees 2024-12-11 14:57:38 -05:00
gen_segmented corrections to c_library.cpp, package_release.ps1 working for all zips 2024-12-11 02:04:22 -05:00
gen_singleheader Update undef.macros.h 2024-12-11 14:08:34 -05:00
gen_unreal_engine Updates to docs and various changes to project from working on them. 2024-12-11 13:33:35 -05:00
scripts Updates to docs and various changes to project from working on them. 2024-12-11 13:33:35 -05:00
test Updates to docs and various changes to project from working on them. 2024-12-11 13:33:35 -05:00
.editorconfig WIP Change to code types [ Broken ] 2023-07-13 23:01:20 -04:00
.gitignore Finished first pass reviewing memory.hpp for C lib generation 2024-11-30 23:38:27 -05:00
gencpp.10x c_library refacotring works, and compiles with all content from the base project. 2024-12-10 13:56:56 -05:00
gencpp.sln WIP : better AST::debug_str() 2023-09-12 02:32:44 -04:00
gencpp.sln.DotSettings.user Parsing constructors passed the sanity test! 2023-07-10 22:14:51 -04:00
gencpp.vcxproj WIP: code_types.hpp c_library.cpp conversion (issue with C struct padding on asts) 2024-12-07 19:46:19 -05:00
gencpp.vcxproj.filters Fixed some compilation errors 2023-11-22 15:41:41 -05:00
gencpp.vcxproj.user WIP : better AST::debug_str() 2023-09-12 02:32:44 -04:00
LICENSE Create LICENSE 2023-07-11 01:18:58 -04:00
Readme.md Updates to docs and various changes to project from working on them. 2024-12-11 13:33:35 -05:00

gencpp

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. 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.
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.
See 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).

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.

gen.cpp `s main() is defined as gen_main() which the user will have to define once for their program. There they will dictate everything that should be generated.

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):

Within program.cpp :

#ifdef GEN_TIME
#include "gen.hpp"

...

u32 gen_main()
{
    ...
}
#endif

// "Stage" agnostic code.

#ifndef GEN_TIME
#include "program.gen.cpp"

    // Regular runtime dependent on the generated code here.
#endif

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:

Upfront

Validation and construction through a functional interface.

Code t_uw           = def_type( name(usize) );
Code t_allocator    = def_type( name(allocator) );
Code t_string_const = def_type( name(char), def_specifiers( args( ESpecifier::Const, ESpecifier::Ptr ) ));

Code header;
{
    Code num       = def_variable( t_uw,        name(Num) );
    Code cap       = def_variable( t_uw,        name(Capacity) );
    Code mem_alloc = def_variable( t_allocator, name(Allocator) );
    Code body      = def_struct_body( args( num, cap, mem_alloc ) );

    header = def_struct( name(ArrayHeader), __, __, body );
}

Parse

Validation through ast construction.

Code header = parse_struct( code(
    struct ArrayHeader
    {
        usize        Num;
        usize        Capacity;
        allocator Allocator;
    };
));

Untyped

No validation, just glorified text injection.

Code header = code_str(
    struct ArrayHeader
    {
        usize        Num;
        usize        Capacity;
        allocator Allocator;
    };
);

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( <content> ))

All three constrcuton interfaces will generate the following C code:

struct ArrayHeader
{
    usize        Num;
    usize        Capacity;
    allocator Allocator;
};

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.
(The library currently uses clang-format for formatting, beware its pretty slow...)

Building

See the scripts directory.