Compare commits

..

12 Commits

Author SHA1 Message Date
Ed_
ef78772278 work on gettings things compiling again after restructuring 2024-12-10 20:45:00 -05:00
Ed_
8891657eb1 Large updates to docs 2024-12-10 19:31:50 -05:00
Ed_
a18b5b97aa typo 2024-12-10 16:58:04 -05:00
Ed_
0ea88a263d third test 2024-12-10 16:56:42 -05:00
Ed_
eea4ebf5c4 another test 2024-12-10 16:55:04 -05:00
Ed_
7351ba6175 testing link embedding 2024-12-10 16:53:07 -05:00
Ed_
8e3e66b3c1 Updates to docs and scripts 2024-12-10 16:38:01 -05:00
Ed_
2c51a2f9c8 WIP: Restructuring project 2024-12-10 16:13:14 -05:00
Ed_
e3b3882443 correctionns to gen_unreal_engine 2024-12-10 13:57:12 -05:00
Ed_
0046c4a223 c_library refacotring works, and compiles with all content from the base project.
I need to make the refactor step happen before formatting with clang-format in the metaprogram instead of calling it from powershell
2024-12-10 13:56:56 -05:00
Ed_
5aaef0f1a2 get rid of Test.josnc
not sure how that got there...
2024-12-10 10:29:34 -05:00
Ed_
abdad1a436 demacro AST and Code forwards/typedefs 2024-12-10 10:24:48 -05:00
132 changed files with 1780 additions and 5927 deletions

View File

@ -1,14 +0,0 @@
{
"files": [
{
"path": "project/auxillary/vis_ast/dependencies/temp/raylib-master/src/rcamera.h",
"bookmarks": [
{
"line": 140,
"column": 14,
"label": ""
}
]
}
]
}

View File

@ -3,7 +3,7 @@
{
"name": "Bootstrap",
"includePath": [
"${workspaceFolder}/project/**"
"${workspaceFolder}/base/**"
],
"defines": [
"_DEBUG",
@ -20,7 +20,7 @@
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.29.30133/bin/HostX64/x64/cl.exe",
"intelliSenseMode": "msvc-x64",
"compileCommands": "C:\\projects\\gencpp\\.vscode\\tasks.json",
"compileCommands": "${workspaceFolder}/.vscode/tasks.json",
"compilerArgs": [
"/EHsc-",
"/GR-",
@ -47,12 +47,12 @@
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.29.30133/bin/HostX64/x64/cl.exe",
"intelliSenseMode": "msvc-x64",
"compileCommands": "C:\\projects\\gencpp\\.vscode\\tasks.json"
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
},
{
"name": "Win32 clang",
"includePath": [
"${workspaceFolder}/**"
"${workspaceFolder}/base/**"
],
"defines": [
"_DEBUG",
@ -65,9 +65,9 @@
"INTELLISENSE_DIRECTIVES"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Users/Ed/scoop/apps/llvm/current/bin/clang++.exe",
"compilerPath": "clang++.exe",
"intelliSenseMode": "windows-clang-x64",
"compileCommands": ".vscode/tasks.json"
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
}
],
"version": 4

45
.vscode/launch.json vendored
View File

@ -4,39 +4,20 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug gentime lldb",
"program": "${workspaceFolder}/test/test.exe",
"args": [],
"cwd": "${workspaceFolder}/test/",
"postRunCommands": [
]
},
{
"type": "cppvsdbg",
"request": "launch",
"name": "Debug gentime vsdbg",
"program": "${workspaceFolder}/test/build/test.exe",
"name": "Debug base vsdbg",
"program": "${workspaceFolder}/base/build/base.exe",
"args": [],
"cwd": "${workspaceFolder}/test/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
},
{
"type": "cppvsdbg",
"request": "launch",
"name": "Debug bootstrap vsdbg",
"program": "${workspaceFolder}/project/build/bootstrap.exe",
"args": [],
"cwd": "${workspaceFolder}/project/",
"cwd": "${workspaceFolder}/base/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
},
{
"type": "cppvsdbg",
"request": "launch",
"name": "Debug singleheader vsdbg",
"program": "${workspaceFolder}/singleheader/build/gencpp_singleheader.exe",
"program": "${workspaceFolder}/singleheader/build/singleheader.exe",
"args": [],
"cwd": "${workspaceFolder}/singleheader/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
@ -49,24 +30,6 @@
"args": [],
"cwd": "${workspaceFolder}/unreal_engine/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
},
{
"type": "cppvsdbg",
"request": "launch",
"name": "Debug raylib refactor vsdbg",
"program": "${workspaceFolder}/project/auxillary/vis_ast/dependencies/raylib/build/raylib_refactor.exe",
"args": [],
"cwd": "${workspaceFolder}/project/auxillary/vis_ast/dependencies/temp/raylib-master/src/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
},
{
"type": "cppvsdbg",
"request": "launch",
"name": "Debug VIS AST",
"program": "${workspaceFolder}/project/auxillary/vis_ast/binaries/vis_ast.exe",
"args": [],
"cwd": "${workspaceFolder}/project/auxillary/vis_ast/binaries/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
}
]
}

View File

@ -2,15 +2,30 @@
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.
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
If your going to metaprogram, you can never have enough docs on your tooling...
* [docs - General](./docs/Readme.md): Overview and additional docs
* [AST_Design](./docs/AST_Design.md): Overvie of ASTs
* [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.
* [gen_c_library](./gen_c_library/Readme.md): C11 library variant generation (single header and segmeented).
* [gen_segmented](./gen_segmented/Readme.md): Segemented C++ (`gen.<hpp/cpp>`, `gen.dep.<hpp/cpp>`) generation
* [gen_singleheader](./gen_singleheader/Readme.md): Singlehader C++ generation `gen.hpp`
* [gen_unreal_engine](./gen_unreal_engine/Readme.md): Unreal Engine thirdparty code generation.
## Notes
**On Partial Hiatus: Life has got me tackling other issues..**
**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.
@ -21,10 +36,6 @@ The library can already be used to generate code just fine, but the parser is wh
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.
@ -114,7 +125,7 @@ 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.
`args` is a helper macro for providing the number of arguments to varadic constructors.
`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:
@ -128,7 +139,7 @@ struct ArrayHeader
};
```
**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.**
**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

154
base/Readme.md Normal file
View File

@ -0,0 +1,154 @@
## Navigation
# base
[Top](../Readme.md)
* [docs](../docs/Readme.md)
The library is fragmented into a series of headers and source files meant to be scanned in and then generated to a standard target format, or a user's desires.
Standard formats:
* **base**: Files are in granular pieces separated into four directories:
* **dependencies**: Originally from the c-zpl library and modified thereafter.
* **components**: The essential definitions of the library.
* **helpers**: Contains helper functionality used by base and other libraries to regenerate or generate the other library formats.
* `base_codegen.hpp`: Helps with self-hosted code generation of enums, and operator overload inlines of the code types.
* `<push/pop>.<name>.inline.<hpp>`: macros that are meant to be injected at specific locations of the library.
* `misc.hpp`: Misc functionality used by the library generation metaprograms.
* `undef.macros.h`: Undefines all macros from library that original were intended to leak into user code.
* **auxillary**: Non-essential tooling:
* `Builder`: Similar conceptually to Jai programming language's *builder*, just opens a file and prepares a string buffer to serialize code into (`builder_print`, `builder_print_fmt`). Then write & close the file when completed (`builder_write`).
* **`Scanner`**: Interface to load up `Code` from files two basic funcctions are currently provided.
* `scan_file`: Used mainly by the library format generators to directly scan files into untyped `Code` (raw string content, pre-formatted no AST parsed).
* `parse_file`: Used to read file and then parsed to populate a `CodeBody` AST.
* CSV parsing via one or two columns simplified.
* **gen_segemetned**: Dependencies go into gen.dep.{hpp/cpp} and components into gen.{hpp/cpp}
* **gen_singleheader**: Everything into a single file: gen.hpp
* **gen_unreal_engine**: Like gen_segemented but the library is modified slightly to compile as a thirdparty library within an Unreal Engine plugin or module.
* **gen_c_library**: The library is heavily modifed into C11 compliant code. A segemented and single-header set of variants are generatd.
Code not making up the core library is located in `auxiliary/<auxiliary_name>.<hpp/cpp>`. These are optional extensions or tools for the library.
*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)*
## Dependencies
The project has no external dependencies beyond:
* `errno.h`
* `stat.h`
* `stdarg.h`
* `stddef.h`
* `stdio.h`
* `copyfile.h` (Mac)
* `types.h` (Linux)
* `sys/man.h` (Linux)
* `fcntl.h` (POSXIX Filesystem)
* `unistd.h` (Linux/Mac)
* `intrin.h` (Windows)
* `io.h` (Windows with gcc)
* `windows.h` (Windows)
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).
See the following files for any updates:
* [`platform.hpp`](./dependencies/platform.hpp)
* [`src_start.cpp`](./dependencies/src_start.cpp)
* [`filesystem.cpp`](./dependencies/filesystem.cpp)
* [`memory.cpp`](./dependencies/memory.cpp)
## Conventions
This library was written in a subset of C++ where the following are not used at all:
* RAII (Constructors/Destructors), lifetimes are managed using named static or regular functions.
* Language provide dynamic dispatch, RTTI
* Object-Oriented Inheritance
* Exceptions
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).
## C++ template usage
There are only 4 template definitions in the entire library (C++ versions). (`Array<Type>`, `Hashtable<Type>`, `swap<Type>`, and `tmpl_cast<CodeT>(CodeT code)`)
Two generic templated containers are used throughout the library:
* `template< class Type> struct Array`
* `template< class Type> struct HashTable`
`tmpl_cast<CodeT>(CodeT code)` is just an alternative way to explicitly cast to code. Its usage is wrapped in a macro called `cast` for the base library (needed for interoperability with C).
`template< class Type> swap( Type& a, Type& b)` is used over a macro.
Otherwise the library is free of any templates.
## Macro usage
Since this is a meta-programming library, it was desired to keep both templates and macros (especially macros) usage very limited.
Most macros are defined within [macros.hpp](./dependencies/macros.hpp).
The most advanced macro usage is `num_args` which is a helper for counting the number of arguments of another macro.
Any large macros used implementing the gen interface or parser are going to be phased out in favor of just forcinlined functions.
*(Unless there is a hot-path that requires them)*
The vast majority of macros should be single-line subsitutions that either add:
* Improvements to searching
* Inteniality of keyword usage
* A feature that only the preprocessor has (ex: function name reflection or stringifying)
* Compatibility of statements or expressions bewteen C & C++ that cannot be parsed by gencpp itself.
* Masking highly verbose syntax (the latter is getting phased out).
[gen_c_library](../gen_c_library/) has the most advanced set of macros for c11's generic selection.
* A significant amount of explicit code geneeration is utilized to keep abuse of the preprocessor to the absolute minimum.
* There is a heavy set of documentation inlined wth them; their naming is also highly verbose and explicit.
* See its documentation for more information.
## On base code generation
There are ***five*** header files which are automatically generated by [base_codegen.hpp](./helpers/base_codegen.hpp). They are all located in [components/gen](./components/gen/).
* [`ecode.hpp`](./components/gen/ecode.hpp): `CodeType` enum definition and related implementaiton. Generation is based off of [`ECodeType.csv](./enums/ECodeTypes.csv).
* [`especifier.hpp`](./components/gen/especifier.hpp): `Specifier` enum definition, etc. Generated using [`ESpecifier.csv`](./enums/ESpecifier.csv).
* [`eoperator.hpp`](./components/gen/eoperator.hpp): `Operator` enum definition, etc. Generated using [`EOperator.hpp`](./enums/EOperator.csv).
* [`etoktype.cpp`](./components/gen/etoktype.cpp): `TokType` enum defininition, etc. Used by the lexer and parser backend. Uses two csvs:
* [`ETokType.csv`](./enums/ETokType.csv): Provides the enum entries and their strinng ids.
* [`AttributeTokens.csv`](./enums/AttributeTokens.csv): Provides tokens entries that should be considered as attributes by the lexer and parser. Sspecfiically macro attributes such as those use for exporting symbols.
* [`ast_inlines.hpp`](./components/gen/ast_inlines.hpp): Member trivial `operator` definitions for C++ code types. Does not use a csv.
[`misc.hpp`](./helpers/misc.hpp): Has shared functions used by the library generation meta-programs throughout this codebase.
## On multi-threading
Currently unsupported. I want the library to be *stable* and *correct*, with the addition of exhausting all basic single-threaded optimizations before I consider multi-threading.
## Extending the library
This library is relatively very small (for parsing C++), and can be extended without much hassle.
The convention you'll see used throughout the interface of the library is as follows:
1. Check name or parameters to make sure they are valid for the construction requested
2. Create a code object using `make_code`.
3. Populate immediate fields (Name, Type, ModuleFlags, etc)
4. Populate sub-entires using `add_entry`. If using the default serialization function `to_string`, follow the order at which entires are expected to appear (there is a strong ordering expected).
Names or Content fields are interned strings and thus showed be cached using `get_cached_string` if its desired to preserve that behavior.
`def_operator` is the most sophisticated upfront constructor as it has multiple permutations of definitions that could be created that are not trivial to determine if valid.
The parser is documented under `docs/Parsing.md` and `docs/Parser_Algo.md`. Extending it is more serious, but resolution of a parse for a given internal parse procedure is well documented.
## A note on compilation and runtime generation speed
The library is designed to be fast to compile and generate code at runtime as fast as resonable possible on a debug build.
Its recommended that your metaprogam be compiled using a single translation unit (unity build).

View File

@ -2,6 +2,8 @@
# include "builder.hpp"
#endif
#pragma region Builder
Builder builder_open( char const* path )
{
Builder result;
@ -39,7 +41,7 @@ void builder_print_fmt_va( Builder* builder, char const* fmt, va_list va )
res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1;
string_append_c_str_len( (String*) & builder->Buffer, (char const*)buf, res);
string_append_c_str_len( (String*) & (builder->Buffer), (char const*)buf, res);
}
void builder_write(Builder* builder)
@ -54,3 +56,4 @@ void builder_write(Builder* builder)
string_free(& builder->Buffer);
}
#pragma endregion Builder

View File

@ -1,8 +1,23 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "gen.hpp"
# include "helpers/push_ignores.inline.hpp"
# include "components/header_start.hpp"
# include "components/types.hpp"
# include "components/gen/ecode.hpp"
# include "components/gen/eoperator.hpp"
# include "components/gen/especifier.hpp"
# include "components/ast.hpp"
# include "components/code_types.hpp"
# include "components/ast_types.hpp"
# include "components/interface.hpp"
# include "components/inlines.hpp"
# include "components/gen/ast_inlines.hpp"
# include "components/header_end.hpp"
using namespace gen;
#endif
#pragma region Builder
struct Builder;
typedef struct Builder Builder;
@ -30,7 +45,10 @@ struct Builder
forceinline void print( Code code ) { return builder_print(this, code); }
forceinline void print_fmt( char const* fmt, ... ) {
va_list va;
va_start( va, fmt );
builder_print_fmt_va( this, fmt, va );
va_end( va );
}
forceinline void write() { return builder_write(this); }
@ -48,3 +66,5 @@ void builder_print_fmt( Builder& builder, char const* fmt, ...) {
va_end( va );
}
#endif
#pragma endregion Builder

View File

@ -1,6 +1,18 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "../gen.hpp"
# include "helpers/push_ignores.inline.hpp"
# include "components/header_start.hpp"
# include "components/types.hpp"
# include "components/gen/ecode.hpp"
# include "components/gen/eoperator.hpp"
# include "components/gen/especifier.hpp"
# include "components/ast.hpp"
# include "components/code_types.hpp"
# include "components/ast_types.hpp"
# include "components/interface.hpp"
# include "components/inlines.hpp"
# include "components/gen/ast_inlines.hpp"
# include "components/header_end.hpp"
#endif
/*

View File

@ -1,12 +1,9 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "gen.hpp"
# include "scanner.hpp"
#endif
// This is a simple file reader that reads the entire file into memory.
// It has an extra option to skip the first few lines for undesired includes.
// This is done so that includes can be kept in dependency and component files so that intellisense works.
inline
#pragma region Scanner
Code scan_file( char const* path )
{
FileInfo file;
@ -119,41 +116,4 @@ Code scan_file( char const* path )
return untyped_str( string_to_strc(str) );
}
#if 0
struct CodeFile
{
using namespace Parser;
String FilePath;
TokArray Tokens;
Array<ParseFailure> ParseFailures;
Code CodeRoot;
};
namespace Parser
{
struct ParseFailure
{
String Reason;
Code Node;
};
}
CodeFile scan_file( char const* path )
{
using namespace Parser;
CodeFile
result = {};
result.FilePath = String::make( GlobalAllocator, path );
Code code = scan_file( path );
result.CodeRoot = code;
ParseContext context = parser_get_last_context();
result.Tokens = context.Tokens;
result.ParseFailures = context.Failures;
return result;
}
#endif
#pragma endregion Scanner

View File

@ -0,0 +1,77 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "helpers/push_ignores.inline.hpp"
# include "components/header_start.hpp"
# include "components/types.hpp"
# include "components/gen/ecode.hpp"
# include "components/gen/eoperator.hpp"
# include "components/gen/especifier.hpp"
# include "components/ast.hpp"
# include "components/code_types.hpp"
# include "components/ast_types.hpp"
# include "components/interface.hpp"
# include "components/inlines.hpp"
# include "components/gen/ast_inlines.hpp"
# include "components/header_end.hpp"
#endif
#pragma region Scanner
// This is a simple file reader that reads the entire file into memory.
// It has an extra option to skip the first few lines for undesired includes.
// This is done so that includes can be kept in dependency and component files so that intellisense works.
Code scan_file( char const* path );
inline
CodeBody parse_file( const char* path )
{
FileContents file = file_read_contents( GlobalAllocator, true, path );
CodeBody code = parse_global_body( { file.size, (char const*)file.data } );
log_fmt("\nParsed: %s\n", path);
return code;
}
// The follow is basic support for light csv parsing (use it as an example)
// Make something robust if its more serious.
typedef struct CSV_Column CSV_Column;
struct CSV_Column {
CSV_Object ADT;
Array<ADT_Node> Content;
};
typedef struct CSV_Columns2 CSV_Columns2;
struct CSV_Columns2 {
CSV_Object ADT;
Array<ADT_Node> Col_1;
Array<ADT_Node> Col_2;
};
inline
CSV_Column parse_csv_one_column(AllocatorInfo allocator, char const* path) {
char scratch_mem[kilobytes(32)];
Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( arena_allocator_info( & scratch), file_zero_terminate, path );
CSV_Column result;
csv_parse( & result.ADT, scratch_mem, allocator, false );
result.Content = result.ADT.nodes[0].nodes;
return result;
}
inline
CSV_Columns2 parse_csv_two_columns(AllocatorInfo allocator, char const* path) {
char scratch_mem[kilobytes(32)];
Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( arena_allocator_info( & scratch), file_zero_terminate, path );
CSV_Columns2 result;
csv_parse( & result.ADT, scratch_mem, allocator, false );
result.Col_1 = result.ADT.nodes[0].nodes;
result.Col_2 = result.ADT.nodes[1].nodes;
return result;
}
#pragma endregion Scanner

71
base/base.cpp Normal file
View File

@ -0,0 +1,71 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_C_LIKE_CPP 1
#include "gen.cpp"
#include "helpers/push_ignores.inline.hpp"
#include <stdlib.h>
GEN_NS_BEGIN
#include "helpers/base_codegen.hpp"
#include "helpers/misc.hpp"
GEN_NS_END
using namespace gen;
constexpr char const* path_format_style = "../scripts/.clang-format";
constexpr char const* scratch_file = "gen/scratch.hpp";
Code format( Code code ) {
return code_refactor_and_format(code, scratch_file, nullptr, path_format_style );
}
constexpr char const* generation_notice =
"// This file was generated automatially by gencpp's bootstrap.cpp "
"(See: https://github.com/Ed94/gencpp)\n\n";
CodeBody gen_component_header = def_global_body( args(
def_preprocess_cond( PreprocessCond_IfDef, txt("GEN_INTELLISENSE_DIRECTIVES") ),
pragma_once,
def_include(txt("components/types.hpp")),
preprocess_endif,
fmt_newline,
untyped_str( to_strc_from_c_str(generation_notice) )
));
int gen_main()
{
gen::init();
__debugbreak();
CodeBody ecode = gen_ecode ( "enums/ECodeTypes.csv" );
CodeBody eoperator = gen_eoperator ( "enums/EOperator.csv" );
CodeBody especifier = gen_especifier( "enums/ESpecifier.csv" );
CodeBody ast_inlines = gen_ast_inlines();
Builder header_ecode = builder_open( "components/gen/ecode.hpp" );
builder_print( & header_ecode, gen_component_header );
builder_print( & header_ecode, format(ecode) );
builder_write( & header_ecode);
Builder header_eoperator = builder_open( "components/gen/eoperator.hpp" );
builder_print( & header_eoperator, gen_component_header );
builder_print( & header_eoperator, format(eoperator) );
builder_write( & header_eoperator );
Builder header_especifier = builder_open( "components/gen/especifier.hpp" );
builder_print( & header_especifier, gen_component_header );
builder_print( & header_especifier, format(especifier) );
builder_write( & header_especifier);
Builder header_ast_inlines = builder_open( "components/gen/ast_inlines.hpp" );
builder_print( & header_ast_inlines, gen_component_header );
builder_print( & header_ast_inlines, format(ast_inlines) );
builder_write( & header_ast_inlines);
gen::deinit();
return 0;
}

View File

@ -85,84 +85,149 @@ struct AST_Union;
struct AST_Using;
struct AST_Var;
#if GEN_COMPILER_C
#define Define_Code(Type) typedef AST_##Type* Code##Type
#else
#define Define_Code(Type) struct Code##Type
#endif
#if GEN_COMPILER_C
typedef AST* Code;
#else
struct Code;
#endif
Define_Code(Body);
// These are to offer ease of use and optionally strong type safety for the AST.
Define_Code(Attributes);
// struct CodeBaseClass;
Define_Code(Comment);
Define_Code(Class);
Define_Code(Constructor);
Define_Code(Define);
Define_Code(Destructor);
Define_Code(Enum);
Define_Code(Exec);
Define_Code(Extern);
Define_Code(Include);
Define_Code(Friend);
Define_Code(Fn);
Define_Code(Module);
Define_Code(NS);
Define_Code(Operator);
Define_Code(OpCast);
Define_Code(Param);
Define_Code(PreprocessCond);
Define_Code(Pragma);
Define_Code(Specifiers);
#if GEN_EXECUTION_EXPRESSION_SUPPORT
Define_Code(Expr);
Define_Code(Expr_Assign);
Define_Code(Expr_Alignof);
Define_Code(Expr_Binary);
Define_Code(Expr_CStyleCast);
Define_Code(Expr_FunctionalCast);
Define_Code(Expr_CppCast);
Define_Code(Expr_Element);
Define_Code(Expr_ProcCall);
Define_Code(Expr_Decltype);
Define_Code(Expr_Comma);
Define_Code(Expr_AMS); // Access Member Symbol
Define_Code(Expr_Sizeof);
Define_Code(Expr_Subscript);
Define_Code(Expr_Ternary);
Define_Code(Expr_UnaryPrefix);
Define_Code(Expr_UnaryPostfix);
Define_Code(Stmt);
Define_Code(Stmt_Break);
Define_Code(Stmt_Case);
Define_Code(Stmt_Continue);
Define_Code(Stmt_Decl);
Define_Code(Stmt_Do);
Define_Code(Stmt_Expr);
Define_Code(Stmt_Else);
Define_Code(Stmt_If);
Define_Code(Stmt_For);
Define_Code(Stmt_Goto);
Define_Code(Stmt_Label);
Define_Code(Stmt_Switch);
Define_Code(Stmt_While);
#if GEN_COMPILER_C
typedef AST_Body* CodeBody;
typedef AST_Attributes* CodeAttributes;
typedef AST_Comment* CodeComment;
typedef AST_Class* CodeClass;
typedef AST_Constructor* CodeConstructor;
typedef AST_Define* CodeDefine;
typedef AST_Destructor* CodeDestructor;
typedef AST_Enum* CodeEnum;
typedef AST_Exec* CodeExec;
typedef AST_Extern* CodeExtern;
typedef AST_Include* CodeInclude;
typedef AST_Friend* CodeFriend;
typedef AST_Fn* CodeFn;
typedef AST_Module* CodeModule;
typedef AST_NS* CodeNS;
typedef AST_Operator* CodeOperator;
typedef AST_OpCast* CodeOpCast;
typedef AST_Param* CodeParam;
typedef AST_PreprocessCond* CodePreprocessCond;
typedef AST_Pragma* CodePragma;
typedef AST_Specifiers* CodeSpecifiers;
#else
struct CodeBody;
struct CodeAttributes;
struct CodeComment;
struct CodeClass;
struct CodeConstructor;
struct CodeDefine;
struct CodeDestructor;
struct CodeEnum;
struct CodeExec;
struct CodeExtern;
struct CodeInclude;
struct CodeFriend;
struct CodeFn;
struct CodeModule;
struct CodeNS;
struct CodeOperator;
struct CodeOpCast;
struct CodeParam;
struct CodePreprocessCond;
struct CodePragma;
struct CodeSpecifiers;
#endif
Define_Code(Struct);
Define_Code(Template);
Define_Code(Typename);
Define_Code(Typedef);
Define_Code(Union);
Define_Code(Using);
Define_Code(Var);
#if GEN_EXECUTION_EXPRESSION_SUPPORT
#if GEN_COMPILER_C
typedef AST_Expr* CodeExpr;
typedef AST_Expr_Assign* CodeExpr_Assign;
typedef AST_Expr_Alignof* CodeExpr_Alignof;
typedef AST_Expr_Binary* CodeExpr_Binary;
typedef AST_Expr_CStyleCast* CodeExpr_CStyleCast;
typedef AST_Expr_FunctionalCast* CodeExpr_FunctionalCast;
typedef AST_Expr_CppCast* CodeExpr_CppCast;
typedef AST_Expr_Element* CodeExpr_Element;
typedef AST_Expr_ProcCall* CodeExpr_ProcCall;
typedef AST_Expr_Decltype* CodeExpr_Decltype;
typedef AST_Expr_Comma* CodeExpr_Comma;
typedef AST_Expr_AMS* CodeExpr_AMS; // Access Member Symbol
typedef AST_Expr_Sizeof* CodeExpr_Sizeof;
typedef AST_Expr_Subscript* CodeExpr_Subscript;
typedef AST_Expr_Ternary* CodeExpr_Ternary;
typedef AST_Expr_UnaryPrefix* CodeExpr_UnaryPrefix;
typedef AST_Expr_UnaryPostfix* CodeExpr_UnaryPostfix;
#else
struct CodeExpr;
struct CodeExpr_Assign;
struct CodeExpr_Alignof;
struct CodeExpr_Binary;
struct CodeExpr_CStyleCast;
struct CodeExpr_FunctionalCast;
struct CodeExpr_CppCast;
struct CodeExpr_Element;
struct CodeExpr_ProcCall;
struct CodeExpr_Decltype;
struct CodeExpr_Comma;
struct CodeExpr_AMS; // Access Member Symbol
struct CodeExpr_Sizeof;
struct CodeExpr_Subscript;
struct CodeExpr_Ternary;
struct CodeExpr_UnaryPrefix;
struct CodeExpr_UnaryPostfix;
#endif
#if GEN_COMPILER_C
typedef AST_Stmt* CodeStmt;
typedef AST_Stmt_Break* CodeStmt_Break;
typedef AST_Stmt_Case* CodeStmt_Case;
typedef AST_Stmt_Continue* CodeStmt_Continue;
typedef AST_Stmt_Decl* CodeStmt_Decl;
typedef AST_Stmt_Do* CodeStmt_Do;
typedef AST_Stmt_Expr* CodeStmt_Expr;
typedef AST_Stmt_Else* CodeStmt_Else;
typedef AST_Stmt_If* CodeStmt_If;
typedef AST_Stmt_For* CodeStmt_For;
typedef AST_Stmt_Goto* CodeStmt_Goto;
typedef AST_Stmt_Label* CodeStmt_Label;
typedef AST_Stmt_Switch* CodeStmt_Switch;
typedef AST_Stmt_While* CodeStmt_While;
#else
struct CodeStmt;
struct CodeStmt_Break;
struct CodeStmt_Case;
struct CodeStmt_Continue;
struct CodeStmt_Decl;
struct CodeStmt_Do;
struct CodeStmt_Expr;
struct CodeStmt_Else;
struct CodeStmt_If;
struct CodeStmt_For;
struct CodeStmt_Goto;
struct CodeStmt_Label;
struct CodeStmt_Switch;
struct CodeStmt_While;
#endif
#endif
#if GEN_COMPILER_C
typedef AST_Struct* CodeStruct;
typedef AST_Template* CodeTemplate;
typedef AST_Typename* CodeTypename;
typedef AST_Typedef* CodeTypedef;
typedef AST_Union* CodeUnion;
typedef AST_Using* CodeUsing;
typedef AST_Var* CodeVar;
#else
struct CodeStruct;
struct CodeTemplate;
struct CodeTypename;
struct CodeTypedef;
struct CodeUnion;
struct CodeUsing;
struct CodeVar;
#endif
#undef Define_Code

View File

@ -184,54 +184,34 @@ void define_constants()
# undef def_constant_code_type
# define def_constant_spec( Type_, ... ) \
spec_##Type_ = def_specifiers( num_args(__VA_ARGS__), __VA_ARGS__); \
code_set_global( cast(Code, spec_##Type_));
# pragma push_macro("forceinline")
# pragma push_macro("global")
# pragma push_macro("internal")
# pragma push_macro("local_persist")
# pragma push_macro("neverinline")
# undef forceinline
# undef global
# undef internal
# undef local_persist
# undef neverinline
def_constant_spec( const, Spec_Const );
def_constant_spec( consteval, Spec_Consteval );
def_constant_spec( constexpr, Spec_Constexpr );
def_constant_spec( constinit, Spec_Constinit );
def_constant_spec( extern_linkage, Spec_External_Linkage );
def_constant_spec( final, Spec_Final );
def_constant_spec( forceinline, Spec_ForceInline );
def_constant_spec( global, Spec_Global );
def_constant_spec( inline, Spec_Inline );
def_constant_spec( internal_linkage, Spec_Internal_Linkage );
def_constant_spec( local_persist, Spec_Local_Persist );
def_constant_spec( mutable, Spec_Mutable );
def_constant_spec( neverinline, Spec_NeverInline );
def_constant_spec( noexcept, Spec_NoExceptions );
def_constant_spec( override, Spec_Override );
def_constant_spec( ptr, Spec_Ptr );
def_constant_spec( pure, Spec_Pure )
def_constant_spec( ref, Spec_Ref );
def_constant_spec( register, Spec_Register );
def_constant_spec( rvalue, Spec_RValue );
def_constant_spec( static_member, Spec_Static );
def_constant_spec( thread_local, Spec_Thread_Local );
def_constant_spec( virtual, Spec_Virtual );
def_constant_spec( volatile, Spec_Volatile)
spec_const = def_specifier( Spec_Const); code_set_global( cast(Code, spec_const ));
spec_consteval = def_specifier( Spec_Consteval); code_set_global( cast(Code, spec_consteval ));;
spec_constexpr = def_specifier( Spec_Constexpr); code_set_global( cast(Code, spec_constexpr ));;
spec_constinit = def_specifier( Spec_Constinit); code_set_global( cast(Code, spec_constinit ));;
spec_extern_linkage = def_specifier( Spec_External_Linkage); code_set_global( cast(Code, spec_extern_linkage ));;
spec_final = def_specifier( Spec_Final); code_set_global( cast(Code, spec_final ));;
spec_forceinline = def_specifier( Spec_ForceInline); code_set_global( cast(Code, spec_forceinline ));;
spec_global = def_specifier( Spec_Global); code_set_global( cast(Code, spec_global ));;
spec_inline = def_specifier( Spec_Inline); code_set_global( cast(Code, spec_inline ));;
spec_internal_linkage = def_specifier( Spec_Internal_Linkage); code_set_global( cast(Code, spec_internal_linkage ));;
spec_local_persist = def_specifier( Spec_Local_Persist); code_set_global( cast(Code, spec_local_persist ));;
spec_mutable = def_specifier( Spec_Mutable); code_set_global( cast(Code, spec_mutable ));;
spec_neverinline = def_specifier( Spec_NeverInline); code_set_global( cast(Code, spec_neverinline ));;
spec_noexcept = def_specifier( Spec_NoExceptions); code_set_global( cast(Code, spec_noexcept ));;
spec_override = def_specifier( Spec_Override); code_set_global( cast(Code, spec_override ));;
spec_ptr = def_specifier( Spec_Ptr); code_set_global( cast(Code, spec_ptr ));;
spec_pure = def_specifier( Spec_Pure); code_set_global( cast(Code, spec_pure ));
spec_ref = def_specifier( Spec_Ref); code_set_global( cast(Code, spec_ref ));;
spec_register = def_specifier( Spec_Register); code_set_global( cast(Code, spec_register ));;
spec_rvalue = def_specifier( Spec_RValue); code_set_global( cast(Code, spec_rvalue ));;
spec_static_member = def_specifier( Spec_Static); code_set_global( cast(Code, spec_static_member ));;
spec_thread_local = def_specifier( Spec_Thread_Local); code_set_global( cast(Code, spec_thread_local ));;
spec_virtual = def_specifier( Spec_Virtual); code_set_global( cast(Code, spec_virtual ));;
spec_volatile = def_specifier( Spec_Volatile); code_set_global( cast(Code, spec_volatile ));
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
code_set_global(cast(Code, spec_local_persist));
# pragma pop_macro("forceinline")
# pragma pop_macro("global")
# pragma pop_macro("internal")
# pragma pop_macro("local_persist")
# pragma pop_macro("neverinline")
# pragma push_macro("enum_underlying")
array_append(PreprocessorDefines, txt("enum_underlying("));
# pragma pop_macro("enum_underlying")
@ -260,22 +240,22 @@ void init()
}
if (Allocator_DataArrays.Proc == nullptr) {
Allocator_DataArrays = heap();
Allocator_DataArrays = GlobalAllocator;
}
if (Allocator_CodePool.Proc == nullptr ) {
Allocator_CodePool = heap();
Allocator_CodePool = GlobalAllocator;
}
if (Allocator_Lexer.Proc == nullptr) {
Allocator_Lexer = heap();
Allocator_Lexer = GlobalAllocator;
}
if (Allocator_StringArena.Proc == nullptr) {
Allocator_StringArena = heap();
Allocator_StringArena = GlobalAllocator;
}
if (Allocator_StringTable.Proc == nullptr) {
Allocator_StringTable = heap();
Allocator_StringTable = GlobalAllocator;
}
if (Allocator_TypeTable.Proc == nullptr) {
Allocator_TypeTable = heap();
Allocator_TypeTable = GlobalAllocator;
}
// Setup the arrays

View File

@ -60,7 +60,7 @@ struct Opts_def_struct {
s32 num_interfaces;
ModuleFlag mflags;
};
CodeClass def_class( StrC name, Opts_def_struct otps GEN_PARAM_DEFAULT );
CodeClass def_class( StrC name, Opts_def_struct opts GEN_PARAM_DEFAULT );
struct Opts_def_constructor {
CodeParam params;
@ -69,7 +69,10 @@ struct Opts_def_constructor {
};
CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEFAULT );
CodeDefine def_define( StrC name, StrC content );
struct Opts_def_define {
b32 dont_append_preprocess_defines;
};
CodeDefine def_define( StrC name, StrC content, Opts_def_define opts GEN_PARAM_DEFAULT );
struct Opts_def_destructor {
Code body;
@ -278,51 +281,64 @@ Code untyped_token_fmt( s32 num_tokens, char const* fmt, ... );
#pragma region Macros
#ifndef gen_main
#define gen_main main
#endif
#ifndef name
// Convienence for defining any name used with the gen api.
// Lets you provide the length and string literal to the functions without the need for the DSL.
#define name( Id_ ) { sizeof(stringize( Id_ )) - 1, stringize(Id_) }
#endif
#ifndef code
// Same as name just used to indicate intention of literal for code instead of names.
#define code( ... ) { sizeof(stringize(__VA_ARGS__)) - 1, stringize( __VA_ARGS__ ) }
#endif
#ifndef args
// Provides the number of arguments while passing args inplace.
#define args( ... ) num_args( __VA_ARGS__ ), __VA_ARGS__
#endif
#ifndef code_str
// Just wrappers over common untyped code definition constructions.
#define code_str( ... ) GEN_NS untyped_str( code( __VA_ARGS__ ) )
#endif
#ifndef code_fmt
#define code_fmt( ... ) GEN_NS untyped_str( token_fmt( __VA_ARGS__ ) )
#endif
#ifndef parse_fmt
#define parse_fmt( type, ... ) GEN_NS parse_##type( token_fmt( __VA_ARGS__ ) )
#endif
#ifndef token_fmt
# define gen_main main
# define __ NullCode
// Convienence for defining any name used with the gen api.
// Lets you provide the length and string literal to the functions without the need for the DSL.
# define name( Id_ ) { sizeof(stringize( Id_ )) - 1, stringize(Id_) }
// Same as name just used to indicate intention of literal for code instead of names.
# define code( ... ) { sizeof(stringize(__VA_ARGS__)) - 1, stringize( __VA_ARGS__ ) }
// Provides the number of arguments while passing args inplace.
# define args( ... ) num_args( __VA_ARGS__ ), __VA_ARGS__
// Just wrappers over common untyped code definition constructions.
# define code_str( ... ) GEN_NS untyped_str( code( __VA_ARGS__ ) )
# define code_fmt( ... ) GEN_NS untyped_str( token_fmt( __VA_ARGS__ ) )
# define parse_fmt( type, ... ) GEN_NS parse_##type( token_fmt( __VA_ARGS__ ) )
/*
Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
Tokens are provided in '<'identifier'>' format where '<' '>' are just angle brackets (you can change it in token_fmt_va)
---------------------------------------------------------
Example - A string with:
typedef <type> <name> <name>;
Will have a token_fmt arguments populated with:
"type", strc_for_type,
"name", strc_for_name,
and:
stringize( typedef <type> <name> <name>; )
-----------------------------------------------------------
So the full call for this example would be:
token_fmt(
"type", strc_for_type
, "name", strc_for_name
, stringize(
typedef <type> <name> <name>
));
!----------------------------------------------------------
! Note: token_fmt_va is whitespace sensitive for the tokens.
! This can be alleviated by skipping whitespace between brackets but it was choosen to not have that implementation by default.
*/
# define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ )
/*
Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
Tokens are provided in '<'identifier'>' format where '<' '>' are just angle brackets (you can change it in token_fmt_va)
---------------------------------------------------------
Example - A string with:
typedef <type> <name> <name>;
Will have a token_fmt arguments populated with:
"type", strc_for_type,
"name", strc_for_name,
and:
stringize( typedef <type> <name> <name>; )
-----------------------------------------------------------
So the full call for this example would be:
token_fmt(
"type", strc_for_type
, "name", strc_for_name
, stringize(
typedef <type> <name> <name>
));
!----------------------------------------------------------
! Note: token_fmt_va is whitespace sensitive for the tokens.
! This can be alleviated by skipping whitespace between brackets but it was choosen to not have that implementation by default.
*/
#define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ )
#endif
#pragma endregion Macros

View File

@ -319,15 +319,27 @@ CodeVar parse_variable( StrC def )
}
// Undef helper macros
# undef check_parse_args
# undef currtok_noskip
# undef currtok
# undef peektok
# undef prevtok
# undef nexttok
# undef nexttok_noskip
# undef eat
# undef left
# undef check
# undef push_scope
# undef def_assign
#undef check_parse_args
#undef currtok_noskip
#undef currtok
#undef peektok
#undef prevtok
#undef nexttok
#undef nexttok_noskip
#undef eat
#undef left
#undef check
#undef push_scope
#undef def_assign
// Here for C Variant
#undef lex_dont_skip_formatting
#undef lex_skip_formatting
#undef parser_inplace_def
#undef parser_not_inplace_def
#undef parser_dont_consume_braces
#undef parser_consume_braces
#undef parser_not_from_template
#undef parser_use_parenthesis
#undef parser_strip_formatting_dont_preserve_newlines

View File

@ -12,6 +12,7 @@ enum OpValidateResult : u32
OpValResult_Member
};
internal neverinline
OpValidateResult operator__validate( Operator op, CodeParam params_code, CodeTypename ret_type, CodeSpecifiers specifier )
{
if ( op == Op_Invalid )
@ -416,7 +417,6 @@ OpValidateResult operator__validate( Operator op, CodeParam params_code, CodeTyp
return InvalidCode;
#pragma endregion Helper Marcos
/*
The implementaiton of the upfront constructors involves doing three things:
* Validate the arguments given to construct the intended type of AST is valid.
@ -615,7 +615,7 @@ CodeClass def_class( StrC name, Opts_def_struct p )
return result;
}
CodeDefine def_define( StrC name, StrC content )
CodeDefine def_define( StrC name, StrC content, Opts_def_define p )
{
name_check( def_define, name );
@ -639,6 +639,17 @@ CodeDefine def_define( StrC name, StrC content )
else
result->Content = get_cached_string( string_to_strc(string_fmt_buf(GlobalAllocator, "%SC\n", content)) );
b32 append_preprocess_defines = ! p.dont_append_preprocess_defines;
if ( append_preprocess_defines ) {
// Add the define to PreprocessorDefines for usage in parsing
s32 lex_id_len = 0;
for (; lex_id_len < result->Name.Len; ++ lex_id_len ) {
if ( result->Name.Ptr[lex_id_len] == '(' )
break;
}
StrC lex_id = { lex_id_len, result->Name.Ptr };
array_append(PreprocessorDefines, lex_id );
}
return result;
}

View File

@ -1,6 +1,6 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "gen.hpp"
#include "../gen.hpp"
#endif
#pragma region StaticData

View File

@ -1,6 +1,5 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "platform.hpp"
# include "macros.hpp"
#endif

View File

@ -1,7 +1,5 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "debug.hpp"
# include "basic_types.hpp"
# include "src_start.cpp"
#endif

View File

@ -1,6 +1,9 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "dependencies/platform.hpp"
# include "dependencies/macros.hpp"
# include "basic_types.hpp"
# include "macros.hpp"
#endif
#pragma region Debug

View File

@ -1,5 +1,6 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "platform.hpp"
#endif
#pragma region Macros
@ -355,7 +356,7 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u
// If using an Editor with support for syntax hightlighting macros: HASH__ARGS_SIG_1 and HASH_ARGS_SIG_2 should show color highlighting indicating the slot is enabled,
// or, "defined" for usage during the compilation pass that handles the _Generic instrinsic.
#define hash( function_arguments ) _Generic( \
#define gen_hash_example( function_arguments ) _Generic( \
(function_arguments), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \

View File

@ -215,7 +215,7 @@ struct Arena
#endif
};
#if GEN_COMPILER_CPP && ! GEN_C_LIKECPP
#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP
forceinline AllocatorInfo allocator_info(Arena& arena ) { return arena_allocator_info(& arena); }
forceinline Arena init_sub (Arena& parent, ssize size) { return arena_init_sub( & parent, size); }
forceinline ssize alignment_of (Arena& arena, ssize alignment) { return arena_alignment_of( & arena, alignment); }

View File

@ -1,5 +1,6 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "timing.hpp"
#endif
#pragma region ADT

View File

@ -1,7 +1,5 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "filesystem.hpp"
# include "strings.hpp"
# include "string_ops.cpp"
#endif

View File

@ -1,4 +1,5 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "header_start.hpp"
#endif

View File

@ -1,6 +1,5 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "string_ops.hpp"
# include "debug.cpp"
#endif

View File

@ -626,7 +626,7 @@ StrC string_to_strc(String str) {
}
inline
void trim(String str, char const* cut_set)
void string_trim(String str, char const* cut_set)
{
ssize len = 0;
@ -650,12 +650,12 @@ void trim(String str, char const* cut_set)
}
forceinline
void trim_space(String str) {
trim(str, " \t\r\n\v\f");
void string_trim_space(String str) {
string_trim(str, " \t\r\n\v\f");
}
inline
String visualize_whitespace(String const str)
String string_visualize_whitespace(String const str)
{
StringHeader* header = (StringHeader*)(scast(char const*, str) - sizeof(StringHeader));
String result = string_make_reserve(header->Allocator, string_length(str) * 2); // Assume worst case for space requirements.

View File

@ -37,6 +37,9 @@ GEN_NS_BEGIN
#include "components/interface.parsing.cpp"
#include "components/interface.untyped.cpp"
#include "auxillary/builder.cpp"
#include "auxillary/scanner.cpp"
GEN_NS_END
#include "helpers/pop_container_defines.inline.hpp"

View File

@ -13,5 +13,6 @@ GEN_NS_BEGIN
#include "dependencies/strings.cpp"
#include "dependencies/filesystem.cpp"
#include "dependencies/timing.cpp"
#include "dependencies/parsing.cpp"
GEN_NS_END

View File

@ -16,5 +16,6 @@ GEN_NS_BEGIN
#include "dependencies/strings.hpp"
#include "dependencies/filesystem.hpp"
#include "dependencies/timing.hpp"
#include "dependencies/parsing.hpp"
GEN_NS_END

View File

@ -31,6 +31,9 @@ GEN_NS_BEGIN
#include "components/gen/ast_inlines.hpp"
#include "components/header_end.hpp"
#include "auxillary/builder.hpp"
#include "auxillary/scanner.hpp"
GEN_NS_END
#include "helpers/pop_container_defines.inline.hpp"

View File

@ -18,6 +18,8 @@
// Precedence (highest to lowest):
// word, namespace, regex
// TODO(ED): THIS IS VERY OUTDATED
// Gen Macro namespace
// namespace GEN_, new_namespace_

View File

@ -1,51 +1,36 @@
#pragma once
#include "gen.hpp"
GEN_NS_BEGIN
#include "dependencies/parsing.hpp"
GEN_NS_END
#if GEN_INTELLISENSE_DIRECTIVES
# include "../gen.hpp"
# include "misc.hpp"
using namespace gen;
#endif
CodeBody gen_ecode( char const* path, bool use_c_definition = false )
{
char scratch_mem[kilobytes(4)];
Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( arena_allocator_info( & scratch), file_zero_terminate, path );
CSV_Object csv_nodes;
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
Array<ADT_Node> keyword_strs = csv_nodes.nodes[1].nodes;
CSV_Columns2 csv_enum = parse_csv_two_columns(GlobalAllocator, path );
String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_keyword_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
for ( ssize idx = 0; idx < array_num(enum_strs); ++ idx )
{
char const* code = enum_strs [idx].string;
char const* keyword = keyword_strs[idx].string;
for ( ssize idx = 0; idx < array_num(csv_enum.Col_1); ++ idx ) {
char const* code = csv_enum.Col_1[idx].string;
char const* keyword = csv_enum.Col_2[idx].string;
// TODO(Ed): to_str_entries and the others in here didn't have proper sizing of the StrC slice.
string_append_fmt( & enum_entries, "CT_%s,\n", code );
string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", code, code );
string_append_fmt( & to_keyword_str_entries, "{ sizeof(\"%s\") - 1, \"%s\" },\n", keyword, keyword );
}
CodeEnum enum_code;
if (use_c_definition)
{
if (use_c_definition) {
enum_code = parse_enum(token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries),
"enum CodeType enum_underlying(u32) { <entries> CT_NumTypes, CT_UnderlyingType = GEN_U32_MAX };"
));
}
else
{
else {
enum_code = parse_enum(token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries),
"enum CodeType : u32 { <entries> CT_NumTypes, CT_UnderlyingType = GEN_U32_MAX };"
));
@ -53,7 +38,7 @@ CodeBody gen_ecode( char const* path, bool use_c_definition = false )
#pragma push_macro("local_persist")
#undef local_persist
StrC lookup_size = string_to_strc(string_fmt_buf(GlobalAllocator, "%d", array_num(enum_strs) ));
StrC lookup_size = string_to_strc(string_fmt_buf(GlobalAllocator, "%d", array_num(csv_enum.Col_1) ));
CodeBody to_str_fns = parse_global_body( token_fmt(
"entries", string_to_strc(to_str_entries)
, "keywords", string_to_strc(to_keyword_str_entries)
@ -84,16 +69,14 @@ CodeBody gen_ecode( char const* path, bool use_c_definition = false )
CodeBody result = def_body(CT_Global_Body);
body_append(result, enum_code);
if (use_c_definition)
{
if (use_c_definition) {
CodeTypedef code_t = parse_typedef(code(typedef enum CodeType CodeType; ));
body_append(result, code_t);
}
body_append(result, to_str_fns);
if (! use_c_definition)
{
if (! use_c_definition) {
#pragma push_macro("forceinline")
#undef forceinline
CodeBody alias_mappings = parse_global_body(code(
@ -108,24 +91,14 @@ CodeBody gen_ecode( char const* path, bool use_c_definition = false )
CodeBody gen_eoperator( char const* path, bool use_c_definition = false )
{
char scratch_mem[kilobytes(4)];
Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( arena_allocator_info(& scratch), file_zero_terminate, path );
CSV_Object csv_nodes;
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes;
CSV_Columns2 csv_enum = parse_csv_two_columns(GlobalAllocator, path);
String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
for (usize idx = 0; idx < array_num(enum_strs); idx++)
{
char const* enum_str = enum_strs[idx].string;
char const* entry_to_str = str_strs [idx].string;
for (usize idx = 0; idx < array_num(csv_enum.Col_1); idx++) {
char const* enum_str = csv_enum.Col_1[idx].string;
char const* entry_to_str = csv_enum.Col_2[idx].string;
string_append_fmt( & enum_entries, "Op_%s,\n", enum_str );
string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
@ -160,7 +133,7 @@ CodeBody gen_eoperator( char const* path, bool use_c_definition = false )
#pragma push_macro("local_persist")
#undef local_persist
StrC lookup_size = string_to_strc(string_fmt_buf(GlobalAllocator, "%d", array_num(enum_strs) ));
StrC lookup_size = string_to_strc(string_fmt_buf(GlobalAllocator, "%d", array_num(csv_enum.Col_1) ));
CodeFn to_str = parse_function(token_fmt(
"entries", string_to_strc(to_str_entries)
, "num", lookup_size
@ -180,8 +153,7 @@ CodeBody gen_eoperator( char const* path, bool use_c_definition = false )
CodeBody result = def_body(CT_Global_Body);
body_append(result, enum_code);
if ( use_c_definition )
{
if ( use_c_definition ) {
CodeTypedef operator_t = parse_typedef(code( typedef enum Operator Operator; ));
body_append(result, operator_t);
}
@ -203,24 +175,15 @@ CodeBody gen_eoperator( char const* path, bool use_c_definition = false )
CodeBody gen_especifier( char const* path, bool use_c_definition = false )
{
char scratch_mem[kilobytes(4)];
Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( arena_allocator_info(& scratch), file_zero_terminate, path );
CSV_Object csv_nodes;
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes;
CSV_Columns2 csv_enum = parse_csv_two_columns(GlobalAllocator, path);
String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
for (usize idx = 0; idx < array_num(enum_strs); idx++)
for (usize idx = 0; idx < array_num(csv_enum.Col_1); idx++)
{
char const* enum_str = enum_strs[idx].string;
char const* entry_to_str = str_strs [idx].string;
char const* enum_str = csv_enum.Col_1[idx].string;
char const* entry_to_str = csv_enum.Col_2[idx].string;
string_append_fmt( & enum_entries, "Spec_%s,\n", enum_str );
string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
@ -271,7 +234,7 @@ CodeBody gen_especifier( char const* path, bool use_c_definition = false )
#undef do_once_end
#undef forceinline
#undef neverinline
StrC lookup_size = string_to_strc(string_fmt_buf(GlobalAllocator, "%d", array_num(enum_strs) ));
StrC lookup_size = string_to_strc(string_fmt_buf(GlobalAllocator, "%d", array_num(csv_enum.Col_1) ));
CodeFn to_str = parse_function(token_fmt(
"entries", string_to_strc(to_str_entries)
, "num", lookup_size

88
base/helpers/misc.hpp Normal file
View File

@ -0,0 +1,88 @@
#pragma once
#ifdef GEN_INTELLISENSE_DIRECTIVES
# define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
# define GEN_ENFORCE_STRONG_CODE_TYPES
# define GEN_EXPOSE_BACKEND
# include "gen.hpp"
# include "helpers/push_ignores.inline.hpp"
# include "helpers/helper.hpp"
# include "auxillary/builder.hpp"
# include "auxillary/builder.cpp"
# include "auxillary/scanner.hpp"
#include <stdlib.h>
using namespace gen;
#endif
// Will format a file with the given style at the provided path.
// Assumes clang-format is defined in an user-exposed or system enviornment PATH.
void clang_format_file( char const* path, char const* style_path )
{
GEN_ASSERT_NOT_NULL(path);
String resolved_path = string_make_strc(GlobalAllocator, to_strc_from_c_str(path));
String style_arg;
if (style_path) {
style_arg = string_make_strc(GlobalAllocator, txt("-style=file:"));
string_append_fmt( & style_arg, "%s ", style_path );
}
StrC clang_format = txt("clang-format ");
StrC cf_format_inplace = txt("-i ");
StrC cf_verbose = txt("-verbose ");
String command = string_make_strc( GlobalAllocator, clang_format );
string_append_strc( & command, cf_format_inplace );
string_append_strc( & command, cf_verbose );
string_append_string( & command, style_arg );
string_append_string( & command, resolved_path );
log_fmt("\tRunning clang-format:\n");
system( command );
log_fmt("\tclang-format finished formatting.\n");
}
// Will refactor a file with the given script at the provided path.
// Assumes refactor is defined in an user-exposed or system enviornment PATH.
// (See: ./gencpp/scripts/build.ci.ps1 for how)
void refactor_file( char const* path, char const* refactor_script )
{
GEN_ASSERT_NOT_NULL(path);
GEN_ASSERT_NOT_NULL(refactor_script);
String command = string_make_strc(GlobalAllocator, txt("refactor "));
string_append_strc( & command, txt("-debug ") );
string_append_strc( & command, txt("-num=1 ") );
string_append_fmt( & command, "-src=%s ", path );
string_append_fmt( & command,"-spec=%s ", refactor_script );
log_fmt("\tBeginning refactor:\n");
system(command);
log_fmt("\nRefactoring complete.\n");
#undef refactor
}
// Does either of the above or both to the provided code.
// Code returned will be untyped content (its be serialized)
Code code_refactor_and_format( Code code, char const* scratch_path, char const* refactor_script, char const* clang_format_sytle_path )
{
GEN_ASSERT(code);
GEN_ASSERT_NOT_NULL(scratch_path);
Builder scratch_file = builder_open("gen/scratch.hpp");
builder_print( & scratch_file, code);
builder_write(& scratch_file);
if (refactor_script) {
refactor_file(scratch_path, refactor_script);
}
if ( clang_format_sytle_path ) {
clang_format_file(scratch_path, clang_format_sytle_path);
}
Code result = scan_file( scratch_path );
remove("gen/scratch.hpp");
return result;
}

View File

@ -1,44 +1,58 @@
## Navigation
[Top](../Readme.md)
<- [docs - General](Readme.md)
## Current Design
`AST` is the actual managed node object for the library.
Its raw and really not meant to be used directly.
All user interaction must be with its pointer so the type they deal with is `AST*`.
For user-facing code, they should never be giveen a nullptr. Instead, they should be given a designated `Invalid` AST node.
In order to abstract away constant use of `AST*` its wrapped in a Code type which can be either:
In order to abstract away constant use of `AST*`, I wanted to provide a wrapper for it.
The simpliest being just a type alias.
```cpp
using Code = AST*;
When its the [C generated variant of the library](../gen_c_library/)
```c
typedef AST* Code;
tyepdef AST_<name>* Code<name>;
...
```
This is what the genc library would have to use due to its constraints of a langauge.
The actual content per type of AST is covered within [AST_Types.md](AST_Types.md).
These are pure PODS that just have the lay members relevant to the type of AST node they represent.
Each of them has a Code type alias specific to it.
Again, the simpliest case for these would be a type alias.
**or**
For C++:
```cpp
using struct AST_Typedef CodeTypedef;
struct Code {
AST* ast;
};
struct Code<name> {
...
AST_<name>* ast;
};
```
As of November 21st, 2023, the AST has had a strict layout for how its content is laid out.
This will be abandoned during its redesign that will occur starting with support for statments & expressions for either execution and type declarations.
Having a strict layout is too resctrictive vs allowing each AST type to have maximum control over the layout.
The full definitions of all asts are within:
The redesign will occur after the following todos are addressed:
* [`ast.hpp`](../base/components/ast.hpp)
* [`ast_types.hpp`](../base/components/ast_types.hpp)
* [`code_types.hpp`](../base/components/ast_types.hpp)
* [Improvements Lexer & Token struct#27](https://github.com/Ed94/gencpp/issues/27)
* [Generalize AST Flags to a single 4-byte flag#42](https://github.com/Ed94/gencpp/issues/42)
* [AST-Code Object Redesign.#38](https://github.com/Ed94/gencpp/issues/38)
* [Code-AST Documentation#40](https://github.com/Ed94/gencpp/issues/40)
* [AST::debug_str() improvements#33](https://github.com/Ed94/gencpp/issues/33)
* [AST::is_equal implemented and works with singleheader-test#31](https://github.com/Ed94/gencpp/issues/31)
* [Parser : Add ability to have a parse failure and continue with errors recorded.#35](https://github.com/Ed94/gencpp/issues/35)
* [Scanner : Add CodeFile#29](https://github.com/Ed94/gencpp/issues/29)
* [Auxiliary : AST visual debugger#36](https://github.com/Ed94/gencpp/issues/36)
## Serialization
All code types can either serialize using a function of the pattern:
```c
String <prefix>_to_string(Code code);
// or
<prefix>_to_string(Code code, String& result);
```
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_string_ptr` & `code_to_string`.
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.

View File

@ -1,10 +1,16 @@
## Navigation
[Top](../Readme.md)
<- [docs - General](Readme.md)
# AST Types Documentation
While the Readme for docs covers the data layout per AST, this will focus on the AST types avaialble, and their nuances.
## Body
These are containers representing a scope body of a definition that can be of the following `ECode` type:
These are containers representing a scope body of a definition that can be of the following `CodeType` type:
* Class_Body
* Enum_Body

View File

@ -1,3 +1,9 @@
## Navigation
[Top](../Readme.md)
<- [docs - General](Readme.md)
# Parser's Algorithim
gencpp uses a hand-written recursive descent parser. Both the lexer and parser currently handle a full C/C++ file in a single pass.
@ -7,7 +13,7 @@ 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 `StrC` type.
The tokens are stored (for now) in `gen::parser::Tokens`.
The tokens are stored (for now) in `gen::parser::Lexer_Tokens`.
Fields:
@ -16,7 +22,7 @@ Array<Token> Arr;
s32 Idx;
```
What token types are supported can be found in [ETokType.csv](../project/enums/ETokType.csv) you can also find the token types in [ETokType.h](../project/components/gen/etoktype.cpp) , which is the generated enum from the csv file.
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`:

View File

@ -1,10 +1,16 @@
## Navigation
[Top](../Readme.md)
<- [docs - General](Readme.md)
# Parsing
The library features a naive parser tailored for only what the library needs to construct the supported syntax of C++ into its AST.
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.
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 ~5600 loc. I hope to keep it under 10k loc worst case.
You can think of this parser of a 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.
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.
User exposed interface:
@ -47,10 +53,11 @@ 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. *These ASTs will be considered members or entries of braced scope they reside within*.
Each directive `#` line is considered one preproecessor unit, and will be treated as one Preprocessor AST.
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 )
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***
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:
@ -59,6 +66,8 @@ Exceptions:
* 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)*.
*(Exceptions are added on an on-demand basis)*
*(See functions `parse_operator_function_or_variable` and `parse_typedef` )*
@ -67,15 +76,23 @@ Adding your own exceptions is possible by simply modifying the parser to allow f
*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.*
If a macro is not defined withint e scope of parsing a set of files, it can be defined beforehand by:
* 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: `<name>(` 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`.
The lexing and parsing takes shortcuts from whats expected in the standard.
* 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.
* 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.*
* Attributes ( `[[]]` (standard), `__declspec` (Microsoft), or `__attribute__` (GNU) )
* Assumed to *come before specifiers* (`const`, `constexpr`, `extern`, `static`, etc) for a function or right afterthe return type.
* Or in the usual spot for class, structs, (*right after the declaration keyword*)
* typedefs have attributes with the type (`parse_type`)
* 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.

View File

@ -1,64 +1,42 @@
## Documentation
# General Docs
The project has no external dependencies beyond:
[Top](../Readme.md)
* `errno.h`
* `stat.h`
* `stdarg.h`
* `stddef.h`
* `stdio.h`
* `copyfile.h` (Mac)
* `types.h` (Linux)
* `unistd.h` (Linux/Mac)
* `intrin.h` (Windows)
* `io.h` (Windows with gcc)
* `windows.h` (Windows)
Contains:
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).
* [AST_Design](./AST_Design.md): Overvie of ASTs
* [AST Types](./AST_Types.md): Listing of all AST types along with their Code type interface.
* [Parsing](./Parsing.md): Overview of the parsing interface.
* [Parser Algo](./Parser_Algo.md): In-depth breakdown of the parser's implementation.
This library was written in a subset of C++ where the following are not used at all:
* RAII (Constructors/Destructors), lifetimes are managed using named static or regular functions.
* Language provide dynamic dispatch, RTTI
* Object-Oriented Inheritance
* Exceptions
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<Type>`, `Hashtable<Type>`, `swap<Type>`, and `AST/Code::cast<Type>`)
Two generic templated containers are used throughout the library:
* `template< class Type> struct Array`
* `template< class Type> struct HashTable`
Both Code and AST definitions have a `template< class Type> Code/AST :: cast()`. Its just an alternative way to explicitly cast to each other.
`template< class Type> swap( Type& a, Type& b)` is used over a macro.
Otherwise the library is free of any templates.
### *WHAT IS NOT PROVIDED*
### *CURRENTLY UNSUPPORTED*
**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 can be generated using base.cpp.
* `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` : Setting to `<true or 1>` 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
@ -67,87 +45,33 @@ As mentioned in root readme, the user is provided Code objects by calling the co
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)](../base/components/ast.hpp#L396-461)
```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)
```
https://github.com/Ed94/gencpp/blob/eea4ebf5c40d5d87baa465abfb1be30845b2377e/base/components/ast.hpp#L396-L461
*`CodeT` is a typedef for `ECode::Type` which has an underlying type of `u32`*
*`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`*
*`StringCahced` is a typedef for `String const`, to denote it is an interned string*
*`String` is the dynamically allocated string type for the library*
*`String` is the dynamically allocated string type for the library*
AST widths are setup to be AST_POD_Size.
AST widths are setup to be AST_POD_Size.
The width dictates how much the static array can hold before it must give way to using an allocated array:
```cpp
constexpr static
usize ArrSpecs_Cap =
int AST_ArrSpecs_Cap =
(
AST_POD_Size
- sizeof(AST*) * 3
- sizeof(Code)
- sizeof(StringCached)
- sizeof(CodeT)
- sizeof(Code) * 2
- sizeof(Token*)
- sizeof(Code)
- sizeof(CodeType)
- sizeof(ModuleFlag)
- sizeof(u32)
)
/ sizeof(SpecifierT) -1; // -1 for 4 extra bytes (Odd num of AST*)
/ sizeof(Specifier) - 1;
```
*Ex: If the AST_POD_Size is 128 the capacity of the static array is 20.*
@ -156,7 +80,7 @@ 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_string_allocator`, `get_cached_string`, `make_code`.
* Allocators are defined with the `AllocatorInfo` structure found in `dependencies\memory.hpp`
* 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
@ -164,30 +88,30 @@ Data Notes:
```
* ASTs are wrapped for the user in a Code struct which is a wrapper for a AST* type.
* Both AST and Code have member symbols but their data layout is enforced to be POD types.
* 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 `GlobalAllocator`, 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 single arena with a simple slag allocator.
* Linked lists used children nodes on bodies, and parameters.
* 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.
* 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:
* 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.
* `GEN_TOKEN_FMT_TOKEN_MAP_MEM_SIZE` : token_fmt_va uses local_persit memory of this size for the hashtable.
* `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`
The following CodeTypes are used which the user may optionally use strong typing with if they enable: `GEN_ENFORCE_STRONG_CODE_TYPES`
* CodeBody : Has support for `for-range` iterating across Code objects.
* CodeBody : Has support for `for : range` iterating across Code objects.
* CodeAttributes
* CodeComment
* CodeClass
@ -204,13 +128,13 @@ The following CodeTypes are used which the user may optionally use strong typing
* CodeNS
* CodeOperator
* CodeOpCast
* CodeParam : Has support for `for-range` iterating across parameters.
* CodeParam : Has support for `for : range` iterating across parameters.
* CodePreprocessCond
* CodePragma
* CodeSpecifiers : Has support for `for-range` iterating across specifiers.
* CodeSpecifiers : Has support for `for : range` iterating across specifiers.
* CodeStruct
* CodeTemplate
* CodeType
* CodeTypename
* CodeTypedef
* CodeUnion
* CodeUsing
@ -295,6 +219,7 @@ Code <name>
```
When using the body functions, its recommended to use the args macro to auto determine the number of arguments for the varadic:
```cpp
def_global_body( args( ht_entry, array_ht_entry, hashtable ));
@ -302,7 +227,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 +279,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.
@ -375,6 +300,7 @@ Code <name> = untyped_str( code(
```
Optionally, `code_str`, and `code_fmt` macros can be used so that the code macro doesn't have to be used:
```cpp
Code <name> = code_str( <some code without "" quotes > )
```
@ -404,8 +330,8 @@ The following are provided predefined by the library as they are commonly used:
* `module_global_fragment`
* `module_private_fragment`
* `fmt_newline`
* `param_varaidc` (Used for varadic definitions)
* `pragma_once`
* `param_varaidc` (Used for varadic definitions)
* `preprocess_else`
* `preprocess_endif`
* `spec_const`
@ -421,6 +347,7 @@ The following are provided predefined by the library as they are commonly used:
* `spec_local_persist` (local_persist macro)
* `spec_mutable`
* `spec_neverinline`
* `spec_noexcept`
* `spec_override`
* `spec_ptr`
* `spec_pure`
@ -452,8 +379,8 @@ Optionally the following may be defined if `GEN_DEFINE_LIBRARY_CODE_CONSTANTS` i
* `t_u16`
* `t_u32`
* `t_u64`
* `t_sw` (ssize_t)
* `t_uw` (size_t)
* `t_ssize` (ssize_t)
* `t_usize` (size_t)
* `t_f32`
* `t_f64`
@ -471,14 +398,11 @@ and have the desired specifiers assigned to them beforehand.
## Code generation and modification
There are three provided auxillary interfaces:
There are two 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.
@ -488,4 +412,4 @@ Editor and Scanner are disabled by default, use `GEN_FEATURE_EDITOR` and `GEN_FE
### Scanner Auxillary Interface
Provides *(eventually)* `scan_file` to automatically populate a CodeFile which contains a parsed AST (`Code`) of the file, with any contextual failures that are reported from the parser.

23
gen_c_library/Readme.md Normal file
View File

@ -0,0 +1,23 @@
## Navigation
# base
[Top](../Readme.md)
* [docs](../docs/Readme.md)
# C Library Generation
`c_library.cpp` generates both *segemnted* and *singleheader* variants of the library compliant with C11.
The output will be in the `gen_segmented/gen` directory (if the directory does not exist, it will create it).
If using the library's provided build scripts:
```ps1
.\build.ps1 <compiler> <debug or omit> c_library
```
All free from tag identifiers will be prefixed with `gen_` or `GEN_` as the namespace. This can either be changed after generation with a `.refactor` script (or your preferred subst method), OR by modifying c_library.refactor.
**If c_library.refactor is modified you may need to modify c_library.cpp and its [components](./components/). As some of the container generation relies on that prefix.**

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,7 @@ constexpr StrC implementation_guard_end = txt(R"(
#pragma endregion GENCPP IMPLEMENTATION GUARD
)");
void format_file( char const* path )
void CHANGE_format_file( char const* path )
{
String resolved_path = String::make(GlobalAllocator, to_strc_from_c_str(path));
@ -77,7 +77,7 @@ void format_file( char const* path )
#undef cf_verbse
}
Code format_code_to_untyped( Code code )
Code CHANGE_format_code_to_untyped( Code code )
{
Builder ecode_file_temp = Builder::open("gen/scratch.hpp");
ecode_file_temp.print(code);
@ -88,14 +88,6 @@ Code format_code_to_untyped( Code code )
return result;
}
CodeBody parse_file( const char* path )
{
FileContents file = file_read_contents( GlobalAllocator, true, path );
CodeBody code = parse_global_body( { file.size, (char const*)file.data } );
log_fmt("\nParsed: %s\n", path);
return code;
}
constexpr bool helper_use_c_definition = true;
int gen_main()
@ -114,8 +106,8 @@ int gen_main()
PreprocessorDefines.append(txt("Using_CodeOps("));
PreprocessorDefines.append(txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"));
PreprocessorDefines.append(txt("GEN_OPITMIZE_MAPPINGS_END"));
//PreprocessorDefines.append(txt("GEN_EXECUTION_EXPRESSION_SUPPORT"));
PreprocessorDefines.append(txt("GEN_PARAM_DEFAULT"));
//PreprocessorDefines.append(txt("GEN_EXECUTION_EXPRESSION_SUPPORT"));
Code push_ignores = scan_file( project_dir "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( project_dir "helpers/pop_ignores.inline.hpp" );
@ -231,7 +223,7 @@ do \
break;
case CT_Preprocess_If:
{
b32 found = ignore_preprocess_cond_block(txt("! GEN_C_LIKE_CPP"), entry, parsed_header_memory, header_memory );
b32 found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP"), entry, parsed_header_memory, header_memory );
if (found) break;
header_memory.append(entry);
@ -289,8 +281,8 @@ do \
break;
}
Code array_ssize = gen_array(txt("ssize"), txt("Array_ssize"));
Code array_string_cached = gen_array(txt("StringCached"), txt("Array_StringCached"));
Code array_ssize = gen_array(txt("gen_ssize"), txt("Array_gen_ssize"));
Code array_string_cached = gen_array(txt("gen_StringCached"), txt("Array_gen_StringCached"));
CodeBody parsed_header_strings = parse_file( project_dir "dependencies/strings.hpp" );
CodeBody header_strings = def_body(CT_Global_Body);
@ -383,7 +375,7 @@ do \
CodeTypedef td = cast(CodeTypedef, entry);
if (td->Name.contains(name_string_table))
{
CodeBody ht = gen_hashtable(txt("StrC"), name_string_table);
CodeBody ht = gen_hashtable(txt("gen_StrC"), name_string_table);
header_strings.append(ht);
break;
}
@ -396,7 +388,7 @@ do \
break;
}
CodeBody array_u8 = gen_array(txt("u8"), txt("Array_u8"));
CodeBody array_u8 = gen_array(txt("gen_u8"), txt("Array_gen_u8"));
CodeBody parsed_header_filesystem = parse_file( project_dir "dependencies/filesystem.hpp" );
CodeBody header_filesystem = def_body(CT_Global_Body);
@ -455,7 +447,7 @@ do \
break;
}
CodeBody array_adt_node = gen_array(txt("ADT_Node"), txt("Array_ADT_Node"));
CodeBody array_adt_node = gen_array(txt("gen_ADT_Node"), txt("Array_gen_ADT_Node"));
CodeBody parsed_header_parsing = parse_file( project_dir "dependencies/parsing.hpp" );
CodeBody header_parsing = def_body(CT_Global_Body);
@ -478,8 +470,8 @@ do \
header_parsing.append(fmt_newline);
// Add ADT_Node forward and typedef early.
CodeStruct adt_node_fwd = parse_struct(code( struct ADT_Node; ));
CodeTypedef adt_node_typedef = parse_typedef(code( typedef struct ADT_Node ADT_Node; ));
CodeStruct adt_node_fwd = parse_struct(code( struct gen_ADT_Node; ));
CodeTypedef adt_node_typedef = parse_typedef(code( typedef struct gen_ADT_Node gen_ADT_Node; ));
header_parsing.append(adt_node_fwd);
header_parsing.append(adt_node_typedef);
@ -644,12 +636,15 @@ do \
case CT_Preprocess_If:
{
CodePreprocessCond cond = cast(CodePreprocessCond, entry);
if (cond->Content.contains(txt("GEN_COMPILER_C")))
if (cond->Content.is_equal(txt("GEN_COMPILER_C")))
{
//++ entry; //
//ast.append(entry) // typedef
//for ( ; entry != parsed_ast.end() && entry->Type != CT_Preprocess_EndIf; ++ entry) {}
//++ entry; // Consume endif
++ entry; // #if
for ( ; entry != parsed_ast.end() && entry->Type != CT_Preprocess_Else; ++ entry) {
ast.append(entry);
}
for ( ; entry != parsed_ast.end() && entry->Type != CT_Preprocess_EndIf; ++ entry) {}
++ entry; // Consume endif
continue;
}
b32 found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP"), entry, parsed_ast, ast);
@ -1096,7 +1091,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
{
CodeBody body = cast(CodeBody, entry->Body);
CodeBody new_body = def_body(CT_Struct_Body);
for ( Code body_entry = body.begin(); body.end(); ++ body_entry ) switch(body_entry->Type)
for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch(body_entry->Type)
{
case CT_Preprocess_If:
{
@ -1124,7 +1119,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
break;
}
s32 idx = 0;
CodeBody parsed_header_end = parse_file( project_dir "components/header_end.hpp" );
CodeBody header_end = def_body(CT_Global_Body);
@ -1176,11 +1170,11 @@ R"(#define <interface_name>( code ) _Generic( (code), \
#pragma endregion Resolve Dependencies
#pragma region Resolve Components
CodeBody array_arena = gen_array(txt("Arena"), txt("Array_Arena"));
CodeBody array_pool = gen_array(txt("Pool"), txt("Array_Pool"));
CodeBody array_token = gen_array(txt("Token"), txt("Array_Token"));
CodeBody array_arena = gen_array(txt("gen_Arena"), txt("Array_gen_Arena"));
CodeBody array_pool = gen_array(txt("gen_Pool"), txt("Array_gen_Pool"));
CodeBody array_token = gen_array(txt("gen_Token"), txt("Array_gen_Token"));
Code src_static_data = scan_file( project_dir "components/static_data.cpp" );
Code src_static_data = scan_file( project_dir "components/static_data.cpp" );
Code src_ast_case_macros = scan_file( project_dir "components/ast_case_macros.cpp" );
Code src_code_serialization = scan_file( project_dir "components/code_serialization.cpp" );
Code src_interface = scan_file( project_dir "components/interface.cpp" );
@ -1367,7 +1361,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
break;
}
CodeBody array_code_typename = gen_array(txt("CodeTypename"), txt("Array_CodeTypename"));
CodeBody array_code_typename = gen_array(txt("gen_CodeTypename"), txt("Array_gen_CodeTypename"));
CodeBody parsed_src_parser = parse_file( project_dir "components/parser.cpp" );
CodeBody src_parser = def_body(CT_Global_Body);
@ -1464,7 +1458,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print_fmt( "\n#pragma region Parsing\n" );
header.print( format_code_to_untyped(header_parsing) );
header.print_fmt( "#pragma endregion Parsing\n\n" );
header.print_fmt( "#pragma endregion Parsing\n" );
header.print_fmt( "\nGEN_NS_END\n" );
header.print_fmt( roll_own_dependencies_guard_end );
@ -1493,6 +1487,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print_fmt("\n#pragma endregion AST\n");
header.print( format_code_to_untyped(interface) );
header.print(fmt_newline);
header.print_fmt("#pragma region Inlines\n");
header.print( format_code_to_untyped(inlines) );
@ -1500,16 +1495,14 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print(fmt_newline);
header.print( format_code_to_untyped(array_string_cached));
header.print(fmt_newline);
header.print( format_code_to_untyped(header_end) );
header.print_fmt( "\n#pragma region Builder\n" );
header.print( format_code_to_untyped(header_builder) );
header.print_fmt( "#pragma endregion Builder\n" );
header.print_fmt( "\n#pragma endregion Builder\n" );
header.print_fmt( "\nGEN_API_C_END\n" );
header.print_fmt( "GEN_NS_END\n\n" );
#pragma endregion Print Compoennts
}
@ -1520,8 +1513,8 @@ R"(#define <interface_name>( code ) _Generic( (code), \
#pragma region Print Dependencies
header.print_fmt( roll_own_dependencies_guard_start );
header.print_fmt( "GEN_NS_BEGIN\n\n");
header.print_fmt( "GEN_API_C_BEGIN\n\n" );
header.print_fmt( "GEN_NS_BEGIN\n");
header.print_fmt( "GEN_API_C_BEGIN\n" );
header.print( src_impl_start );
header.print( src_debug );
@ -1535,7 +1528,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print_fmt( "\n#pragma region Parsing\n" );
header.print( scan_file( project_dir "dependencies/parsing.cpp" ) );
header.print_fmt( "#pragma endregion Parsing\n\n" );
header.print_fmt( "\n#pragma endregion Parsing\n\n" );
header.print_fmt( "GEN_NS_END\n");
header.print_fmt( roll_own_dependencies_guard_end );
@ -1546,6 +1539,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print_fmt( "\nGEN_NS_BEGIN\n");
header.print( fmt_newline);
header.print( format_code_to_untyped(array_arena));
header.print( fmt_newline);
header.print( format_code_to_untyped(array_pool));
@ -1572,17 +1566,17 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print( src_parsing_interface );
header.print_fmt( "\n#pragma endregion Parsing\n" );
header.print( src_untyped );
header.print_fmt( "\n#pragma endregion Interface\n\n");
header.print_fmt( "\n#pragma endregion Interface\n\n");
header.print_fmt( "#pragma region Builder\n" );
header.print( scan_file( project_dir "auxillary/builder.cpp" ) );
header.print_fmt( "\n#pragma endregion Builder\n\n" );
header.print_fmt( "#pragma endregion Builder\n\n" );
// header.print_fmt( "\n#pragma region Scanner\n" );
// header.print( scan_file( project_dir "auxillary/scanner.hpp" ) );
// header.print_fmt( "#pragma endregion Scanner\n\n" );
header.print_fmt( "\n#pragma region Scanner\n" );
header.print( scan_file( project_dir "auxillary/scanner.hpp" ) );
header.print_fmt( "#pragma endregion Scanner\n\n" );
header.print_fmt( "\nGEN_API_C_END\n" );
header.print_fmt( "GEN_API_C_END\n" );
#pragma endregion Print Components
header.print_fmt( implementation_guard_end );

View File

@ -0,0 +1,539 @@
__VERSION 1
// not : Ignore
// include : #includes
// word : Alphanumeric or underscore
// namespace : Prefix search and replace (c-namspaces).
// regex : Unavailable in __VERSION 1.
// Precedence (highest to lowest):
// word, namespace, regex
// Gen Macro namespace
// namespace GEN_, new_namespace_
// c_library.refactor
// Used to prefix all exposed identifiers with the gen_namespace by c_library.cpp using ./gencpp/scripts/helpers/refactor.exe
// Macros
word global, gen_global
word internal, gen_internal
word local_persist, gen_local_persist
word bit, gen_bit
word bitfield_is_equal, gen_bitfield_is_equal
word cast, gen_cast
word ccast, gen_ccast
word pcast, gen_pcast
word rcast, gen_rcast
word scast, gen_scast
word stringize_va, gen_stringize_va
word stringize, gen_stringize
word do_once, gen_do_once
word do_once_start, gen_do_once_start
word do_once_end, gen_do_once_end
word labeled_scope_start, gen_labeled_scope_start
word labeled_scope_end, gen_labeled_scope_end
word compiler_decorated_func_name, gen_compiler_decorated_func_name
word num_args_impl, gen_num_args_impl
word num_args, gen_num_args
word clamp, gen_clamp
word count_of, gen_count_of
word is_between, gen_is_between
word size_of, gen_size_of
word max, gen_max
word min, gen_min
word offset_of, gen_offset_of
word forceinline, gen_forceinline
word neverinline, gen_neverinline
word static_assert, gen_static_assert
word thread_local, gen_thread_local
word typeof, gen_typeof
word enum_underlying, gen_enum_underlying
word nullptr, gen_nullptr
word struct_init, gen_struct_init
word hash, gen_hash
// Basic Types
word u8, gen_u8
word s8, gen_s8
word u16, gen_u16
word s16, gen_s16
word u32, gen_u32
word s32, gen_s32
word u64, gen_u64
word s64, gen_s64
word usize, gen_usize
word ssize, gen_ssize
word sptr, gen_sptr
word uptr, gen_uptr
word f32, gen_f32
word f64, gen_f64
word b8, gen_b8
word b16, gen_b16
word b32, gen_b32
word mem_ptr, gen_mem_ptr
word mem_ptr_const, gen_mem_ptr_cnst
// Debug
word assert_handler, gen_assert_handler
word assert_crash, gen_assert_crash
word process_exit, gen_process_exit
// Memory
word kilobytes, gen_kilobytes
word megabytes, gen_megabytes
word gigabytes, gen_gigabytes
word terabytes, gen_terabytes
word swap, gen_swap
word is_power_of_two, gen_is_power_of_two
word align_forward, gen_align_forward
word align_forward_by_value, gen_align_forward_by_value
word pointer_add, gen_pointer_add
word pointer_add_const, gen_pointer_add_const
word pointer_diff, gen_pointer_diff
word mem_copy, gen_mem_copy
word mem_find, gen_mem_find
word mem_move, gen_mem_move
word mem_set, gen_mem_set
word zero_size, gen_zero_size
word zero_item, gen_zero_item
word zero_array, gen_zero_array
word AllocType, gen_AllocType
word AllocatorProc, gen_AllocatorProc
word AllocatorInfo, gen_AllocatorInfo
word AllocFlag, gen_AllocFlag
word alloc, gen_alloc
word alloc_align, gen_alloc_align
word allocator_free, gen_allocator_free
word free_all, gen_free_all
word resize, gen_resize
word resize_align, gen_resize_align
word alloc_item, gen_alloc_item
word alloc_array, gen_alloc_array
word heap_stats_init, gen_heap_stats_init
word heap_stats_used_memory, gen_heap_stats_used_memory
word heap_stats_alloc_count, gen_heap_stats_alloc_count
word heap_stats_check, gen_heap_stats_check
word default_resize_align, gen_default_resize_align
word heap_allocator_proc, gen_heap_allocator_proc
word heap, gen_heap
word malloc, gen_malloc
word mfree, gen_mfree
word VirtualMemory, gen_VirtualMemory
word vm_from_memory, gen_vm_from_memory
word vm_alloc, gen_vm_alloc
word vm_free, gen_vm_free
word vm_trim, gen_vm_trim
word vm_purge, gen_vm_purge
word virtual_memory_page_size, gen_virtual_memory_page_size
// Memory: Arena
word Arena, gen_Arena
namespace arena_, gen_arena_
// word arena_allocator_info
// word arena_init_from_memory
// word arena_init_from_allocator
// word arena_init_sub
// word arena_alignment_of
// word arena_check
// word arena_size_remaining
// Memory: FixedArena
namespace FixedArena_, gen_FixedArena_
namespace fixed_arena_, gen_fixed_arena_
// Memory: Pool
word Pool, gen_Pool
namespace pool_, gen_pool_
// Printing
namespace str_, gen_str_
word PrintF_Buffer, gen_PrintF_Buffer
word Msg_Invalid_Value, gen_Msg_Invalid_Value
word log_fmt, gen_log_fmt
// String Ops
namespace char_, gen_char_
word digit_to_int, gen_digit_to_int
word hex_digit_to_init, gen_hex_digit_to_init
word i64_to_str, gen_i64_to_str
word u64_to_str, gen_u64_to_str
// Containers
namespace GENERIC_SLOT_, GEN_GENERIC_SLOT_
word Array, gen_Array
word Array_ssize, gen_Array_gen_ssize
word ArrayHeader, gen_ArrayHeader
namespace Array_, gen_Array_
namespace array_, gen_array_
word HashTable, gen_HashTable
namespace HashTable_, gen_HashTable_
namespace hashtable_, gen_hashtable_
namespace HT_, gen_HT_
namespace HTE_, gen_HTE_
namespace arr_hte_, gen_arr_hte_
namespace Arr_HTE_, gen_Arr_HTE_
// Hashing
word crc32, gen_crc32
word crc64, gen_crc64
// Strings
word StrC, gen_StrC
word to_strc_from_c_str, gen_to_strc_from_c_str
namespace strc_, gen_strc_
word cast_to_strc, gen_cast_to_strc
word StringHeader, gen_StringHeader
word String, gen_String
namespace string_, gen_string_
word StringCached, gen_StringCached
word StringTable, gen_StringTable
namespace StringTable_, gen_StringTable_
// File Handling
word FileModeFlag, gen_FileModeFlag
word SeekWhenceType, gen_SeekWhenceType
word FileError, gen_FileError
word FileDescriptor, gen_FileDescriptor
word FileMode, gen_FileMode
word FileOperations, gen_FileOperations
word FileOperations, gen_FileOperations
default_file_operations
word FileTime, word FileTime
word DirType, gen_DirType
word DirInfo, gen_DirInfo
word DirEntry, gen_DirEntry
word DirInfo, gen_DirInfo
word FileInfo, gen_FileInfo
word FileStandardType, gen_FileStandardType
namespace file_, gen_file_
word gen_FileContents, gen_FileContents
// Timing
word read_cpu_time_stamp_counter, gen_read_cpu_time_stamp_counter
word time_rel, gen_time_rel
word time_rel_ms, gen_time_rel_ms
// Parsing
// Parsing: ADT
word ADT_Node, gen_ADT_Node
word ADT_Type, gen_ADT_Type
word ADT_Props, gen_ADT_Props
word ADT_NamingStyle, gen_ADT_NamingStyle
word ADT_AssignStyle, gen_ADT_AssignStyle
word ADT_DelimStyle, gen_ADT_DelimStyle
word ADT_Error, gen_ADT_Error
word ADT_Node, gen_ADT_Node
namespace adt_, gen_adt_
word CSV_Error, gen_CSV_Error
word CSV_Object, gen_CSV_Object
namespace csv_, gen_csv_
// Types.hpp
word log_failure, gen_log_failure
word AccessSpec, gen_AccessSpec
word access_spec_to_str, gen_access_spec_to_str
word CodeFlag, gen_CodeFlag
word EnumDecl, gen_EnumDecl
word ModuleFlag, gen_ModuleFlag
word module_flag_to_str, gen_module_flag_to_str
word EPreprocessCond, gen_EPreprocessCOnd
word ETypenameTag, gen_ETypenameTag
word CodeType, gen_CodeType
word codetype_to_str, gen_codetype_to_str
word codetype_to_keyword_str, gen_codetype_to_keyword_str
word Operator, gen_Operator
word operator_to_str, gen_operator_to_str
word Specifier, gen_Specifier
word spec_to_str, gen_spec_to_str
word spec_is_trailing, gen_spec_is_trailing
// word strc_to_specifier, gen_strc_to_specifier
// AST
word AST, gen_AST
namespace AST_, gen_AST_
word Code, gen_Code
word Token, gen_Token
word CodeBody, gen_CodeBody
word CodeAttributes, gen_CodeAttributes
word CodeComment, gen_CodeComment
word CodeClass, gen_CodeClass
word CodeConstructor, gen_CodeConstructor
word CodeDefine, gen_CodeDefine
word CodeDestructor, gen_CodeDestructor
word CodeEnum, gen_CodeEnum
word CodeExec, gen_CodeExec
word CodeExtern, gen_CodeExtern
word CodeInclude, gen_CodeInclude
word CodeFriend, gen_CodeFriend
word CodeFn, gen_CodeFn
word CodeModule, gen_CodeModule
word CodeNS, gen_CodeNS
word CodeOperator, gen_CodeOperator
word CodeOpCast, gen_CodeOpCast
word CodePragma, gen_CodePragma
word CodeParam, gen_CodeParam
word CodePreprocessCo, gen_CodePreprocessCo
word CodeSpecifiers, gen_CodeSpecifiers
word CodeTemplate, gen_CodeTemplate
word CodeTypename, gen_CodeTypename
word CodeTypedef, gen_CodeTypedef
word CodeUnion, gen_CodeUnion
word CodeUsing, gen_CodeUsing
word CodeVar, gen_CodeVar
// Code Interface
namespace code_, gen_code_
word Code_Global, gen_Code_Global
word Code_Invalid, gen_Code_Invalid
word Code_POD, gen_Code_POD
word AST_POD_Size, gen_AST_POD_Size
word AST_ArrSpecs_Cap, gen_AST_ArrSpecs_Cap
word InvalidCode, gen_InvalidCode
word NullCode, gen_NullCode
namespace begin_, gen_begin_
namespace end_, gen_end_
namespace next_, gen_next_
namespace body_, gen_body_
namespace class_, gen_class_
namespace params_, gen_params_
namespace specifiers_, gen_specifiers_
namespace struct_, gen_struct_
namespace attributes_, gen_attributes_
namespace comment_, gen_comment_
namespace constructor, gen_constructor_
namespace define_, gen_define_
namespace destructor, gen_destructor_
namespace enum_, gen_enum_
namespace exec_, gen_exec_
namespace extern_, gen_extern_
namespace include_, gen_include_
namespace friend_, gen_friend_
namespace fn_, gen_fn_
namespace module_, gen_module_
namespace code_op, gen_code_op_
namespace opcast_, gen_opcast_
namespace pragma_, gen_pragma_
namespace preprocess_, gen_preprocess_
namespace template_, gen_template_
namespace typename_, gen_typename_
namespace typedef_, gen_typedef_
namesapce union_, gen_union_
namespace using_, gen_using_
namespace var_, gen_var_
// Gen Interface
word init, gen_init
word deinit, gen_deinit
word reset, gen_reset
word get_cached_string, gen_get_cached_string
word make_code, gen_make_code
namespace set_allocator_, gen_set_allocator_
namespace def_, gen_def_
namespace parse_, gen_parse_
namespace token_, gen_token_
namespace untyped_, gen_untyped_
// Constants
word TokenMap_FixedArena, gen_TokenMap_FixedArena
word InitSize_DataArrays, gen_InitSize_DataArrays
word Global_BucketSize, gen_Global_BucketSize
word CodePool_NumBlocks, gen_CodePool_NumBlocks
word SizePer_StringArena, gen_SizePer_StringArena
word MaxCommentLineLength, gen_MaxCommentLineLength
word MaxNameLength, gen_MaxNameLength
word MaxUntypedStrLength, gen_MaxUntypedStrLength
word LexAllocator_Size, gen_LexAllocator_Size
word Builder_StrBufferReserve, gen_Builder_StrBufferReserve
word access_public, gen_access_public
word access_protected, gen_access_protected
word access_private, gen_access_private
word attrib_api_export, gen_attrib_api_export
word attrib_api_import, gen_attrib_api_import
word module_global_fragment, gen_module_global_fragment
word module_private_fragment, gen_module_private_fragment
word fmt_newline, gen_fmt_newline
word pragma_once, gen_pragma_once
word param_varadic, gen_param_varadic
word preprocess_else, gen_preprocess_else
namespace spec_, gen_spec_
namespace t_, gen_t_
word PreprocessorDefines, gen_PreprocessorDefines
// Backend
word GlobalAllocator, gen_GlobalAllocator
word Global_AllocatorBuckets, gen_Global_AllocatorBuckets
word CodePools, gen_CodePools
word StringArenas, gen_StringArenas
word StringCache, gen_StringCache
word LexArena, gen_LexArena
word Allocator_DataArrays, gen_Allocator_DataArrays
word Allocator_CodePool, gen_Allocator_CodePool
word Allocator_Lexer, gen_Allocator_Lexer
word Allocator_StringArena, gen_Allocator_StringArena
word Allocator_StringTable, gen_Allocator_StringTable
word Allocator_TypeTable, gen_Allocator_TypeTable
// Builder
word Builder, gen_Builder
namespace builder_, gen_builder_
// Implementation (prviate)
word _format_info, gen__format_info
namespace _print_, gen__print_
word _heap_stats, gen__heap_stats
word _heap_alloc_info, gen__heap_alloc_info
word _crc32_table, gen__crc32_table
word _crc64_table, gen__crc64_table
word _alloc_utf8_to_ucs2, gen__alloc_utf8_to_ucs2
word _win32_file_seek, gen__win32_file_seek
word _win32_file_read, gen__win32_file_read
word _win32_file_write, gen__win32_file_write
word _win32_file_close, gen__win32_file_close
word _win32_file_open, gen__win32_file_open
word _posix_file_seek, gen__posix_file_seek
word _posix_file_read, gen__posix_file_read
word _posix_file_write, gen__posix_file_write
word _posix_file_close, gen__posix_file_close
word _posix_file_open, gen__posix_file_open
word _dirinfo_free_entry, gen__dirinfo_free_entry
word _std_file_set, gen__std_file_set
word _memory_fd, gen__memory_fd
word _file_stream_fd_make, gen__file_stream_fd_make
word _file_stream_from_fd, gen__file_stream_from_fd
word _memory_file_seek, gen__memory_file_seek
word _memory_file_read, gen__memory_file_read
word _memory_file_write, gen__memory_file_write
word _memory_file_close, gen__memory_file_close
word _unix_gettime, gen__unix_gettime
word _adt_fprintf, gen__adt_fprintf
word _adt_get_value, gen__adt_get_value
word _adt_get_field, gen__adt_get_field
word _csv_write_record, gen__csv_write_record
word _csv_write_header, gen__csv_write_header
word Global_Allocator_Proc, gen_Global_Allocator_Proc
word define_constants, gen_define_constants
word operator__validate, gen_operator__validate
word parser_init, gen_parser_init
word parser_deinit, gen_parser_deinit
word TokType, gen_TokType
word toktype_to_str, gen_toktype_to_str
// word strc_to_toktype, gen_strc_to_toktype
word NullToken, gen_NullToken
namespace tok_, gen_tok_
word TokArray, gen_TokArray
namespace lex_, gen_lex_
namespace Lexer_, gen_Lexer_
word LexContext, gen_LexContext
word lex, gen_lex
word StackNode, gen_StackNode
word ParseContext, gen_ParseContext
// namespace parse_, gen_parse_
namespace parser_, gen_parser_

View File

@ -21,7 +21,7 @@ CodeBody gen_array_base()
Code grow_formula = untyped_str( txt( "#define array_grow_formula( value ) ( 2 * value + 8 )\n" ));
Code get_header = untyped_str( txt( "#define array_get_header( self ) ( (ArrayHeader*)( self ) - 1)\n" ));
Code type_define = untyped_str( txt( "#define Array(Type) Array_##Type\n"));
Code type_define = untyped_str( txt( "#define Array(Type) gen_Array_##Type\n"));
Code array_begin = def_define(txt("array_begin(array)"), code( (array) ));
Code array_end = def_define(txt("array_end(array)"), code( (array + array_get_header(array)->Num ) ));

View File

@ -4,4 +4,5 @@
int main()
{
// init();
__debugbreak();
}

21
gen_segmented/Readme.md Normal file
View File

@ -0,0 +1,21 @@
## Navigation
# base
[Top](../Readme.md)
* [docs](../docs/Readme.md)
# Segemented Library Generation
The principal (user) files are `gen.hpp` and `gen.cpp`.
They contain includes for its various components: `components/<component_name>.<hpp/cpp>`
Dependencies are bundled into `gen.dep.<hpp/cpp>`. They are included in `gen.<hpp/cpp>` before component includes.
Just like the `gen.<hpp/cpp>` they include their components: `dependencies/<dependency_name>.<hpp/cpp>`
If using the library's provided build scripts:
```ps1
.\build.ps1 <compiler> <debug or omit> segmented
```

View File

@ -2,21 +2,15 @@
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_C_LIKE_CPP 1
#include "../project/gen.cpp"
#include "../base/gen.cpp"
#include "helpers/push_ignores.inline.hpp"
#include "helpers/helper.hpp"
GEN_NS_BEGIN
#include "helpers/push_container_defines.inline.hpp"
#include "dependencies/parsing.cpp"
#include "helpers/pop_container_defines.inline.hpp"
#include "helpers/base_codegen.hpp"
#include "helpers/misc.hpp"
GEN_NS_END
#include "auxillary/builder.hpp"
#include "auxillary/builder.cpp"
#include "auxillary/scanner.hpp"
using namespace gen;
constexpr char const* generation_notice =
@ -25,50 +19,20 @@ constexpr char const* generation_notice =
#include <cstdlib> // for system()
void format_file( char const* path )
{
String resolved_path = string_make_strc(GlobalAllocator, to_strc_from_c_str(path));
constexpr char const* path_format_style = "../scripts/.clang-format ";
constexpr char const* scratch_file = "gen/scratch.hpp";
constexpr char const* path_base = "../base/";
String style_arg = string_make_strc(GlobalAllocator, txt("-style=file:"));
string_append_strc( & style_arg, txt("../scripts/.clang-format "));
// Need to execute clang format on the generated file to get it to match the original.
#define clang_format txt("clang-format ")
#define cf_format_inplace txt("-i ")
#define cf_verbose txt("-verbose ")
String command = string_make_strc( GlobalAllocator, clang_format );
string_append_strc( & command, cf_format_inplace );
string_append_strc( & command, cf_verbose );
string_append_string( & command, style_arg );
string_append_string( & command, resolved_path );
log_fmt("\tRunning clang-format on file:\n");
system( command );
log_fmt("\tclang-format finished reformatting.\n");
#undef cf_cmd
#undef cf_format_inplace
#undef cf_style
#undef cf_verbse
}
Code dump_to_scratch_and_retireve( Code code )
{
Builder ecode_file_temp = builder_open("gen/scratch.hpp");
builder_print( & ecode_file_temp, code);
builder_write(& ecode_file_temp);
format_file("gen/scratch.hpp");
Code result = scan_file( "gen/scratch.hpp" );
remove("gen/scratch.hpp");
return result;
Code format( Code code ) {
return code_refactor_and_format(code, scratch_file, nullptr, path_format_style );
}
int gen_main()
{
gen::init();
// PreprocessorDefines.append("GEN_NS");
Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( "helpers/pop_ignores.inline.hpp" );
Code push_ignores = scan_file( path_base "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( path_base "helpers/pop_ignores.inline.hpp" );
// gen_dep.hpp
{
@ -176,11 +140,11 @@ int gen_main()
builder_print_fmt(header, "#pragma region Types\n" );
builder_print( header, types );
builder_print( header, fmt_newline);
builder_print( header, dump_to_scratch_and_retireve(ecode) );
builder_print( header, format(ecode) );
builder_print( header, fmt_newline);
builder_print( header, dump_to_scratch_and_retireve(eoperator) );
builder_print( header, format(eoperator) );
builder_print( header, fmt_newline);
builder_print( header, dump_to_scratch_and_retireve(especifier) );
builder_print( header, format(especifier) );
builder_print( header, fmt_newline);
builder_print_fmt( header, "#pragma endregion Types\n\n" );
@ -195,7 +159,7 @@ int gen_main()
builder_print_fmt( header, "\n#pragma region Inlines\n" );
builder_print( header, inlines );
builder_print( header, fmt_newline );
builder_print( header, dump_to_scratch_and_retireve(ast_inlines) );
builder_print( header, format(ast_inlines) );
builder_print( header, fmt_newline );
builder_print_fmt( header, "#pragma endregion Inlines\n" );
@ -206,22 +170,22 @@ int gen_main()
Builder header_ecode = builder_open( "components/gen/ecode.hpp" );
builder_print( & header_ecode, gen_component_header );
builder_print( & header_ecode, ecode );
builder_print( & header_ecode, format(ecode) );
builder_write( & header_ecode);
Builder header_eoperator = builder_open( "components/gen/eoperator.hpp" );
builder_print( & header_eoperator, gen_component_header );
builder_print( & header_eoperator, eoperator );
builder_print( & header_eoperator, format(eoperator) );
builder_write( & header_eoperator );
Builder header_especifier = builder_open( "components/gen/especifier.hpp" );
builder_print( & header_especifier, gen_component_header );
builder_print( & header_especifier, especifier );
builder_print( & header_especifier, format(especifier) );
builder_write( & header_especifier);
Builder header_ast_inlines = builder_open( "components/gen/ast_inlines.hpp" );
builder_print( & header_ast_inlines, gen_component_header );
builder_print( & header_ast_inlines, ast_inlines );
builder_print( & header_ast_inlines, format(ast_inlines) );
builder_write( & header_ast_inlines);
}
@ -240,10 +204,10 @@ int gen_main()
Code untyped = scan_file( "components/interface.untyped.cpp" );
CodeBody etoktype = gen_etoktype( "enums/ETokType.csv", "enums/AttributeTokens.csv" );
//CodeNS nspaced_etoktype = def_namespace( name(parser), def_namespace_body( args(etoktype)) );
CodeBody nspaced_etoktype = def_global_body( args(
etoktype
));
Code formatted_toktype = format(nspaced_etoktype);
Builder _src = builder_open( "gen/gen.cpp" );
Builder* src = & _src;
@ -264,7 +228,7 @@ int gen_main()
builder_print( src, interface );
builder_print( src, upfront );
builder_print_fmt( src, "\n#pragma region Parsing\n\n" );
builder_print( src, dump_to_scratch_and_retireve(nspaced_etoktype) );
builder_print( src, formatted_toktype );
builder_print( src, lexer );
builder_print( src, parser );
builder_print( src, parsing_interface );
@ -278,7 +242,7 @@ int gen_main()
Builder src_etoktype = builder_open( "components/gen/etoktype.cpp" );
builder_print( & src_etoktype, gen_component_header );
builder_print( & src_etoktype, nspaced_etoktype );
builder_print( & src_etoktype, formatted_toktype );
builder_write( & src_etoktype);
}

View File

@ -1,4 +1,18 @@
## Navigation
# base
[Top](../Readme.md)
* [docs](../docs/Readme.md)
# Singleheader
Creates a single header file version of the library using `singleheader.cpp`.
Follows the same convention seen in the gb, stb, and zpl libraries.
If using the library's provided build scripts:
```ps1
.\build.ps1 <compiler> <debug or omit> singleheader
```

View File

@ -1,3 +1,17 @@
## Navigation
# base
[Top](../Readme.md)
* [docs](../docs/Readme.md)
# Unreal Engine Version Generator
This generates a variant of gencpp thats compatiable with use as a thirdparty module within a plugin or module of an Unreal Project or the Engine itself.
This generates a variant of gencpp thats compatiable with use as a thirdparty module within a plugin or module of an Unreal Project or the Engine itself.
If using the library's provided build scripts:
```ps1
.\build.ps1 <compiler> <debug or omit> unreal
```

View File

@ -7,7 +7,9 @@
#include "helpers/helper.hpp"
GEN_NS_BEGIN
#include "helpers/push_container_defines.inline.hpp"
#include "dependencies/parsing.cpp"
#include "helpers/pop_container_defines.inline.hpp"
GEN_NS_END
#include "auxillary/builder.hpp"
@ -52,7 +54,7 @@ global bool generate_scanner = true;
void format_file( char const* path )
{
String resolved_path = String::make(GlobalAllocator, to_str(path));
String resolved_path = String::make(GlobalAllocator, to_strc_from_c_str(path));
String style_arg = String::make(GlobalAllocator, txt("-style=file:"));
style_arg.append("../scripts/.clang-format ");
@ -99,7 +101,7 @@ int gen_main()
// gen_dep.hpp
{
CodeBody macros = def_body( CodeT::Global_Body );
CodeBody macros = def_body( CT_Global_Body );
{
FileContents content = file_read_contents( GlobalAllocator, true, project_dir "dependencies/macros.hpp" );
CodeBody ori_macros = parse_global_body( StrC { content.size, (char const*)content.data });
@ -110,10 +112,9 @@ int gen_main()
{
switch (code->Type)
{
using namespace ECode;
case Preprocess_Define:
case CT_Preprocess_Define:
{
CodeDefine define = code.cast<CodeDefine>();
CodeDefine define = cast(CodeDefine, code);
if ( define->Name.starts_with(txt("global")) )
{
macros.append(parse_global_body(txt("#define global // Global variables")));

View File

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.*,</IncludeFilter>
<ExcludeFilter>*.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate,**/sanity.gen.hpp,</ExcludeFilter>
<IncludeFilter>&amp;apos;.&amp;apos;,**/project/**,</IncludeFilter>
<ExcludeFilter>*.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate,**/sanity.gen.hpp,**/gen_c_library,**/gen_segmented,**/gen_singlheader,**/test,**/gen_unreal_engine,**/scripts,**/docs,</ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<ShowEmptyFolders>true</ShowEmptyFolders>

View File

@ -1,66 +0,0 @@
# Documentation
The library is fragmented into a series of headers and source files meant to be scanned in and then generated to a tailored format for the target `gen` files.
The principal (user) files are `gen.hpp` and `gen.cpp`.
They contain includes for its various components: `components/<component_name>.<hpp/cpp>`
Dependencies are bundled into `gen.dep.<hpp/cpp>`.
Just like the `gen.<hpp/cpp>` they include their components: `dependencies/<dependency_name>.<hpp/cpp>`
Code not making up the core library is located in `auxiliary/<auxiliary_name>.<hpp/cpp>`. These are optional extensions or tools for the library.
Both libraries use *pre-generated* (self-hosting I guess) version of the library to then generate the latest version of itself.
The default `gen.bootstrap.cpp` located in the project folder is meant to be produce a standard segmented library, where the components of the library
have relatively dedicated header and source files. Dependencies included at the top of the file and each header starting with a pragma once.
The output will be in the `project/gen` directory (if the directory does not exist, it will create it).
Use those to get a general idea of how to make your own tailored version.
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.
By default the base library implementation strictly uses a C-like interface. This is to allow for the generation of a C-variant of the library using [gen_c_library](../gen_c_library/). However, the library was written in C++ and supports some of its features:
* `GEN_SUPPORT_CPP_REFERENCES` : Will enable support for reference interface on some definitions
* `GEN_SUPPORT_CPP_MEMBER_FEATURES` : Will enable support for definitions to have their interface as members.
*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)*
## On multi-threading
Currently unsupported. I want the library to be *stable* and *correct*, with the addition of exhausting all basic single-threaded optimizations before I consider multi-threading.
## Extending the library
This library is relatively very small, and can be extended without much hassle.
The convention you'll see used throughout the interface of the library is as follows:
1. Check name or parameters to make sure they are valid for the construction requested
2. Create a code object using `make_code`.
3. Populate immediate fields (Name, Type, ModuleFlags, etc)
4. Populate sub-entires using `add_entry`. If using the default serialization function `to_string`, follow the order at which entires are expected to appear (there is a strong ordering expected).
Names or Content fields are interned strings and thus showed be cached using `get_cached_string` if its desired to preserve that behavior.
`def_operator` is the most sophisticated constructor as it has multiple permutations of definitions that could be created that are not trivial to determine if valid.
The library has its code segmented into component files, use it to help create a derived version without needing to have to rewrite a generated file directly or build on top of the header via composition or inheritance.
The parser is documented under `docs/Parsing.md` and `docs/Parser_Algo.md`.
## A note on compilation and runtime generation speed
The library is designed to be fast to compile and generate code at runtime as fast as resonable possible on a debug build.
Its recommended that your metaprogam be compiled using a single translation unit (unity build).

View File

@ -1,5 +0,0 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# include "scanner.hpp"
#endif

View File

@ -1,10 +0,0 @@
#pragma once
#include "gen.hpp"
GEN_NS_BEGIN
#include "dependencies/parsing.hpp"
GEN_NS_END
using namespace gen;

View File

@ -1,5 +1,10 @@
# Format Style Options - Created with Clang Power Tools
---
AttributeMacros: [enum_underlying]
StatementMacros: [GEN_NS_BEGIN, GEN_NS_END, GEN_NS_PARSER_BEGIN, GEN_NS_PARSER_END, GEN_API_C_BEGIN, GEN_API_C_END]
TypenameMacros: [Array, Hashtable]
SkipMacroDefinitionBody: true
AccessModifierOffset: -4
AlignAfterOpenBracket: BlockIndent

View File

@ -4,23 +4,10 @@ Generation, testing, and cleanup scripts for the test directory are found here a
## Refactoring
`refactor.ps1` Provides a way to run the [refactor](github.com/Ed94/refactor) program. It uses the `gencpp.refactor` script to complete a mass refactor of all content within the files of the specified within the script.
`refactor.ps1` Provides a way to run the [refactor](github.com/Ed94/refactor) program. It uses the a `.refactor` script (such as [`gencpp.refactor`](../base/gencpp.refactor)) to complete a mass refactor of all content within the files of the specified within the script.
Currently `refactor` only supports naive sort of *find and replace* feature set and will not be able to rename identifiers excluisvely to a specific context (such as only renaming member names of a specific struct, etc).
**Note: The following macros are used with specifiers and token parsing within the library:**
* global
* internal
* local_persist
* forceinline
* neverinline
IF they are changed the following files would need adjustment:
* `./project/enums/ESpecifier.csv`
* `./project/enums/ETokType.csv`
* `./project/helpers/helper.hpp`
Currently `refactor` only supports naive sort of *find and replace* feature set and will not be able to rename identifiers excluisvely to a specific context (such as only renaming member names of a specific struct, etc).
Its main uage is the [c_library generation](../gen_c_library/).
## Build & Run Scripts
@ -28,13 +15,14 @@ IF they are changed the following files would need adjustment:
Remove any generated content from the repository.
**`build.ps1`**
Build bootstrap, singleheader, or tests. Supports MSVC or clang, release or debug.
Build c_library, segmented, singleheader, unreal. Supports msvc or clang, release or debug.
```
args:
bootstrap
c_library
segemented
singleheader
test
unreal
clang
msvc : By default this project builds with clang, specifying msvc will build with MSVC.
debug
@ -42,6 +30,6 @@ args:
```
**`package_release.ps1`**
Will build the project as fast as possible, then package the release into a zip file.
Will build the build all, then package the release into a zip file.
*Note: My env is Windows 11 with MSVC 2022 and clang 16.0.6*

Some files were not shown because too many files have changed in this diff Show More