7 Commits

Author SHA1 Message Date
Ed_
772d0de5c1 proofing 2024-12-16 00:58:25 -05:00
Ed_
cb50f93af5 Updates to gen_c_library docs 2024-12-16 00:47:46 -05:00
Ed_
e4f564b165 Tok_Capture_* -> Tok_Paren_*
Was not a correct name for it
2024-12-15 23:28:44 -05:00
Ed_
0b78b74fbc update cpp splash 2024-12-15 23:05:33 -05:00
Ed_
5d8883ec45 trying diff splash 2024-12-15 23:02:32 -05:00
Ed_
c90c210e04 fixes for c library 2024-12-15 22:53:32 -05:00
Ed_
980d1d7134 Merge pull request #66 from Ed94/defines_n_macros_upgrades
Macros have been updated as needed to get reliability up to parity with usage in Unreal
2024-12-15 16:58:20 -08:00
36 changed files with 512 additions and 237 deletions

2
.gitignore vendored
View File

@ -39,3 +39,5 @@ gen_c_library/gen
**/*.vcxproj
**/*.vcxproj.filters
**/*.vcxproj.user
test/c_library/gen
test/cpp_library/gen

View File

@ -28,27 +28,6 @@
"/FC"
]
},
{
"name": "Win32 msvc c_library",
"includePath": [
"${workspaceFolder}/gen_c_library/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"GEN_TIME",
"GEN_IMPLEMENTATION",
// "GEN_DONT_USE_NAMESPACE"
"GEN_INTELLISENSE_DIRECTIVES",
"INTELLISENSE_DIRECTIVES"
],
"cppStandard": "c++17",
"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": "${workspaceFolder}/.vscode/tasks.json"
},
{
"name": "Win32 clang",
"includePath": [
@ -64,10 +43,56 @@
"GEN_INTELLISENSE_DIRECTIVES",
"INTELLISENSE_DIRECTIVES"
],
"cStandard": "c11",
"cppStandard": "c++17",
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "clang++.exe",
"intelliSenseMode": "windows-clang-x64",
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
},
{
"name": "Win32 msvc c_library",
"includePath": [
"${workspaceFolder}/gen_c_library/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"GEN_TIME",
"GEN_IMPLEMENTATION",
// "GEN_DONT_USE_NAMESPACE"
"GEN_INTELLISENSE_DIRECTIVES",
"INTELLISENSE_DIRECTIVES"
],
"cStandard": "c11",
"cppStandard": "c++17",
"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": "${workspaceFolder}/.vscode/tasks.json"
},
{
"name": "Win32 msvc c_library test",
"includePath": [
"${workspaceFolder}/test/c_library/**",
"${workspaceFolder}/gen_c_library/gen/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"GEN_TIME",
"GEN_IMPLEMENTATION",
// "GEN_DONT_USE_NAMESPACE"
"GEN_INTELLISENSE_DIRECTIVES",
"INTELLISENSE_DIRECTIVES"
],
"cStandard": "c11",
"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": "${workspaceFolder}/.vscode/tasks.json"
}
],
"version": 4

View File

@ -1,6 +1,9 @@
# gencpp
An attempt at simple staged metaprogramming for C/C++.
An attempt at simple staged metaprogramming for C/C++. Reflect and generate code for your codebase at runtime!
![splash-cpp](./docs/assets/Code_-_Insiders_2024-12-15_23-04-07.gif)
![splash-c](./docs/assets/Code_-_Insiders_2024-12-15_22-57-58.gif)
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.
@ -49,7 +52,11 @@ Within `program.cpp` :
u32 gen_main()
{
gen::Context ctx;
gen::init(& ctx);
...
gen::deinit(& ctx);
return 0;
}
#endif

View File

@ -8,6 +8,12 @@
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.
If using the library's provided build scripts:
```ps1
.\build.ps1 <compiler> <debug or omit> base
```
Standard formats:
* **base**: Files are in granular pieces separated into four directories:
@ -27,7 +33,7 @@ Standard formats:
* **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.
* **gen_c_library**: The library is heavily modifed into C11 compliant code. A segemented and single-header set of variants are generated.
Code not making up the core library is located in `auxiliary/<auxiliary_name>.<hpp/cpp>`. These are optional extensions or tools for the library.

View File

@ -1038,10 +1038,22 @@ void specifiers_to_strbuilder_ref( CodeSpecifiers self, StrBuilder* result )
s32 left = self->NumEntries;
while ( left -- )
{
Str spec = spec_to_str( self->ArrSpecs[idx] );
strbuilder_append_fmt( result, "%.*s ", spec.Len, spec.Ptr );
Specifier spec = self->ArrSpecs[idx];
Str spec_str = spec_to_str( spec );
if ( idx > 0 ) switch (spec) {
case Spec_Ptr:
case Spec_Ref:
case Spec_RValue:
break;
default:
strbuilder_append_str(result, txt(" "));
break;
}
strbuilder_append_fmt( result, "%S", spec_str );
idx++;
}
strbuilder_append_str(result, txt(" "));
}
StrBuilder struct_to_strbuilder(CodeStruct self)
@ -1445,7 +1457,7 @@ void var_to_strbuilder_ref(CodeVar self, StrBuilder* result )
strbuilder_append_fmt( result, "%SB ", attributes_to_strbuilder(self->Attributes) );
if ( self->Specs )
strbuilder_append_fmt( result, "%SB\n", specifiers_to_strbuilder(self->Specs) );
strbuilder_append_fmt( result, "%SB", specifiers_to_strbuilder(self->Specs) );
strbuilder_append_fmt( result, "%SB %S", typename_to_strbuilder(self->ValueType), self->Name );

View File

@ -24,8 +24,8 @@ enum TokType : u32
Tok_BraceCurly_Close,
Tok_BraceSquare_Open,
Tok_BraceSquare_Close,
Tok_Capture_Start,
Tok_Capture_End,
Tok_Paren_Open,
Tok_Paren_Close,
Tok_Comment,
Tok_Comment_End,
Tok_Comment_Start,

View File

@ -15,7 +15,7 @@
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
| | | | | __} | |
| l_l l_l {___/ |
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
! ============================================================================================ |
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |

View File

@ -503,7 +503,7 @@ void register_macros( s32 num, ... )
va_end(va);
}
void register_macros( s32 num, Macro* macros )
void register_macros_arr( s32 num, Macro* macros )
{
GEN_ASSERT(num > 0);
do

View File

@ -93,6 +93,9 @@ struct Context
// TODO(Ed): Active parse context vs a parse result need to be separated conceptually
ParseContext parser;
// TODO(Ed): Formatting - This will eventually be in a separate struct when in the process of serialization of the builder.
s32 temp_serialize_indent;
};
// Initialize the library. There first ctx initialized must exist for lifetime of other contextes that come after as its the one that
@ -121,7 +124,11 @@ GEN_API void register_macro( Macro macro );
// Ease of use batch registration
GEN_API void register_macros( s32 num, ... );
GEN_API void register_macros( s32 num, Macro* macros );
GEN_API void register_macros_arr( s32 num, Macro* macros );
#if GEN_COMPILER_CPP
forceinline void register_macros( s32 num, Macro* macros ) { return register_macros_arr(num, macros); }
#endif
// Used internally to retrive or make string allocations.
// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena)
@ -277,29 +284,44 @@ GEN_API CodeBody def_body( CodeType type );
/// or provide as an array of Code objects.
GEN_API CodeBody def_class_body ( s32 num, ... );
GEN_API CodeBody def_class_body ( s32 num, Code* codes );
GEN_API CodeBody def_class_body_arr ( s32 num, Code* codes );
GEN_API CodeDefineParams def_define_params ( s32 num, ... );
GEN_API CodeDefineParams def_define_params ( s32 num, CodeDefineParams* codes );
GEN_API CodeDefineParams def_define_params_arr ( s32 num, CodeDefineParams* codes );
GEN_API CodeBody def_enum_body ( s32 num, ... );
GEN_API CodeBody def_enum_body ( s32 num, Code* codes );
GEN_API CodeBody def_enum_body_arr ( s32 num, Code* codes );
GEN_API CodeBody def_export_body ( s32 num, ... );
GEN_API CodeBody def_export_body ( s32 num, Code* codes);
GEN_API CodeBody def_export_body_arr ( s32 num, Code* codes);
GEN_API CodeBody def_extern_link_body ( s32 num, ... );
GEN_API CodeBody def_extern_link_body( s32 num, Code* codes );
GEN_API CodeBody def_extern_link_body_arr ( s32 num, Code* codes );
GEN_API CodeBody def_function_body ( s32 num, ... );
GEN_API CodeBody def_function_body ( s32 num, Code* codes );
GEN_API CodeBody def_function_body_arr ( s32 num, Code* codes );
GEN_API CodeBody def_global_body ( s32 num, ... );
GEN_API CodeBody def_global_body ( s32 num, Code* codes );
GEN_API CodeBody def_global_body_arr ( s32 num, Code* codes );
GEN_API CodeBody def_namespace_body ( s32 num, ... );
GEN_API CodeBody def_namespace_body ( s32 num, Code* codes );
GEN_API CodeBody def_namespace_body_arr ( s32 num, Code* codes );
GEN_API CodeParams def_params ( s32 num, ... );
GEN_API CodeParams def_params ( s32 num, CodeParams* params );
GEN_API CodeParams def_params_arr ( s32 num, CodeParams* params );
GEN_API CodeSpecifiers def_specifiers ( s32 num, ... );
GEN_API CodeSpecifiers def_specifiers ( s32 num, Specifier* specs );
GEN_API CodeSpecifiers def_specifiers_arr ( s32 num, Specifier* specs );
GEN_API CodeBody def_struct_body ( s32 num, ... );
GEN_API CodeBody def_struct_body ( s32 num, Code* codes );
GEN_API CodeBody def_struct_body_arr ( s32 num, Code* codes );
GEN_API CodeBody def_union_body ( s32 num, ... );
GEN_API CodeBody def_union_body ( s32 num, Code* codes );
GEN_API CodeBody def_union_body_arr ( s32 num, Code* codes );
#if GEN_COMPILER_CPP
forceinline CodeBody def_class_body ( s32 num, Code* codes ) { return def_class_body_arr(num, codes); }
forceinline CodeDefineParams def_define_params ( s32 num, CodeDefineParams* codes ) { return def_define_params_arr(num, codes); }
forceinline CodeBody def_enum_body ( s32 num, Code* codes ) { return def_enum_body_arr(num, codes); }
forceinline CodeBody def_export_body ( s32 num, Code* codes) { return def_export_body_arr(num, codes); }
forceinline CodeBody def_extern_link_body( s32 num, Code* codes ) { return def_extern_link_body_arr(num, codes); }
forceinline CodeBody def_function_body ( s32 num, Code* codes ) { return def_function_body_arr(num, codes); }
forceinline CodeBody def_global_body ( s32 num, Code* codes ) { return def_global_body_arr(num, codes); }
forceinline CodeBody def_namespace_body ( s32 num, Code* codes ) { return def_namespace_body_arr(num, codes); }
forceinline CodeParams def_params ( s32 num, CodeParams* params ) { return def_params_arr(num, params); }
forceinline CodeSpecifiers def_specifiers ( s32 num, Specifier* specs ) { return def_specifiers_arr(num, specs); }
forceinline CodeBody def_struct_body ( s32 num, Code* codes ) { return def_struct_body_arr(num, codes); }
forceinline CodeBody def_union_body ( s32 num, Code* codes ) { return def_union_body_arr(num, codes); }
#endif
#pragma endregion Upfront

View File

@ -73,7 +73,7 @@ CodeConstructor parse_constructor( Str def )
if ( NumSpecifiers )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
// <specifiers> ...
}

View File

@ -1369,7 +1369,7 @@ CodeBody def_class_body( s32 num, ... )
return result;
}
CodeBody def_class_body( s32 num, Code* codes )
CodeBody def_class_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_class_body );
@ -1432,7 +1432,7 @@ CodeDefineParams def_define_params( s32 num, ... )
return result;
}
CodeDefineParams def_define_params( s32 num, CodeDefineParams* codes )
CodeDefineParams def_define_params_arr( s32 num, CodeDefineParams* codes )
{
def_body_code_array_start( def_define_params );
@ -1491,7 +1491,7 @@ CodeBody def_enum_body( s32 num, ... )
return (CodeBody) result;
}
CodeBody def_enum_body( s32 num, Code* codes )
CodeBody def_enum_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_enum_body );
@ -1552,7 +1552,7 @@ CodeBody def_export_body( s32 num, ... )
return result;
}
CodeBody def_export_body( s32 num, Code* codes )
CodeBody def_export_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_export_body );
@ -1618,7 +1618,7 @@ CodeBody def_extern_link_body( s32 num, ... )
return result;
}
CodeBody def_extern_link_body( s32 num, Code* codes )
CodeBody def_extern_link_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_extern_linkage_body );
@ -1685,7 +1685,7 @@ CodeBody def_function_body( s32 num, ... )
return result;
}
CodeBody def_function_body( s32 num, Code* codes )
CodeBody def_function_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_function_body );
@ -1756,7 +1756,7 @@ CodeBody def_global_body( s32 num, ... )
return result;
}
CodeBody def_global_body( s32 num, Code* codes )
CodeBody def_global_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_global_body );
@ -1827,7 +1827,7 @@ CodeBody def_namespace_body( s32 num, ... )
return result;
}
CodeBody def_namespace_body( s32 num, Code* codes )
CodeBody def_namespace_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_namespace_body );
@ -1889,7 +1889,7 @@ CodeParams def_params( s32 num, ... )
return result;
}
CodeParams def_params( s32 num, CodeParams* codes )
CodeParams def_params_arr( s32 num, CodeParams* codes )
{
def_body_code_array_start( def_params );
@ -1945,7 +1945,7 @@ CodeSpecifiers def_specifiers( s32 num, ... )
return result;
}
CodeSpecifiers def_specifiers( s32 num, Specifier* specs )
CodeSpecifiers def_specifiers_arr( s32 num, Specifier* specs )
{
if ( num <= 0 ) {
log_failure("gen::def_specifiers: num cannot be zero or less");
@ -2004,7 +2004,7 @@ CodeBody def_struct_body( s32 num, ... )
return result;
}
CodeBody def_struct_body( s32 num, Code* codes )
CodeBody def_struct_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_struct_body );
@ -2065,7 +2065,7 @@ CodeBody def_union_body( s32 num, ... )
return result;
}
CodeBody def_union_body( s32 num, Code* codes )
CodeBody def_union_body_arr( s32 num, Code* codes )
{
def_body_code_array_start( def_union_body );

View File

@ -151,7 +151,7 @@ s32 lex_preprocessor_define( LexContext* ctx )
macro.Flags |= MF_Functional;
}
Token opening_paren = { { ctx->scanner, 1 }, Tok_Capture_Start, ctx->line, ctx->column, TF_Preprocess };
Token opening_paren = { { ctx->scanner, 1 }, Tok_Paren_Open, ctx->line, ctx->column, TF_Preprocess };
array_append( _ctx->Lexer_Tokens, opening_paren );
move_forward();
@ -242,7 +242,7 @@ s32 lex_preprocessor_define( LexContext* ctx )
);
return Lex_ReturnNull;
}
Token closing_paren = { { ctx->scanner, 1 }, Tok_Capture_End, ctx->line, ctx->column, TF_Preprocess };
Token closing_paren = { { ctx->scanner, 1 }, Tok_Paren_Close, ctx->line, ctx->column, TF_Preprocess };
array_append(_ctx->Lexer_Tokens, closing_paren);
move_forward();
}
@ -532,7 +532,7 @@ void lex_found_token( LexContext* ctx )
ctx->token.Type = macrotype_to_toktype(macro->Type);
b32 is_functional = macro_is_functional(* macro);
resolved_to_macro = has_args ? is_functional : ! is_functional;
if ( ! resolved_to_macro ) {
if ( ! resolved_to_macro && GEN_BUILD_DEBUG ) {
log_fmt("Info(%d, %d): %S identified as a macro but usage here does not resolve to one (interpreting as identifier)\n"
, ctx->token.Line
, ctx->token.Line
@ -797,7 +797,7 @@ TokArray lex( Str content )
{
Str text = { c.scanner, 1 };
c.token.Text = text;
c.token.Type = Tok_Capture_Start;
c.token.Type = Tok_Paren_Open;
if (c.left)
move_forward();
@ -807,7 +807,7 @@ TokArray lex( Str content )
{
Str text = { c.scanner, 1 };
c.token.Text = text;
c.token.Type = Tok_Capture_End;
c.token.Type = Tok_Paren_Close;
if (c.left)
move_forward();

View File

@ -601,18 +601,18 @@ CodeAttributes parse_attributes()
else if ( check( Tok_Decl_GNU_Attribute ) )
{
eat( Tok_Decl_GNU_Attribute );
eat( Tok_Capture_Start );
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
eat( Tok_Paren_Open );
// __attribute__((
while ( left && currtok.Type != Tok_Capture_End )
while ( left && currtok.Type != Tok_Paren_Close )
{
eat( currtok.Type );
}
// __attribute__(( <Content>
eat( Tok_Capture_End );
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
eat( Tok_Paren_Close );
// __attribute__(( <Content> ))
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
@ -620,16 +620,16 @@ CodeAttributes parse_attributes()
else if ( check( Tok_Decl_MSVC_Attribute ) )
{
eat( Tok_Decl_MSVC_Attribute );
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
// __declspec(
while ( left && currtok.Type != Tok_Capture_End )
while ( left && currtok.Type != Tok_Paren_Close )
{
eat( currtok.Type );
}
// __declspec( <Content>
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// __declspec( <Content> )
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
@ -640,20 +640,20 @@ CodeAttributes parse_attributes()
// <Attribute>
// If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...)
if ( check( Tok_Capture_Start))
if ( check( Tok_Paren_Open))
{
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
s32 level = 0;
while (left && currtok.Type != Tok_Capture_End && level == 0)
while (left && currtok.Type != Tok_Paren_Close && level == 0)
{
if (currtok.Type == Tok_Capture_Start)
if (currtok.Type == Tok_Paren_Open)
++ level;
if (currtok.Type == Tok_Capture_End)
if (currtok.Type == Tok_Paren_Close)
--level;
eat(currtok.Type);
}
eat(Tok_Capture_End);
eat(Tok_Paren_Close);
}
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
@ -1028,7 +1028,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
if ( NumSpecifiers )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <Attributes> <Specifiers>
@ -1078,7 +1078,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
case Tok_Type_int:
case Tok_Type_double:
{
if ( nexttok.Type == Tok_Capture_Start && name.Text.Len && currtok.Type == Tok_Identifier )
if ( nexttok.Type == Tok_Paren_Open && name.Text.Len && currtok.Type == Tok_Identifier )
{
if ( c_str_compare_len( name.Text.Ptr, currtok.Text.Ptr, name.Text.Len ) == 0 )
{
@ -1183,7 +1183,7 @@ Code parse_complicated_definition( TokType which )
spec = tokens.Arr[spec_idx];
}
if ( tokens.Arr[spec_idx].Type == Tok_Capture_End )
if ( tokens.Arr[spec_idx].Type == Tok_Paren_Close )
{
// Forward declaration with trailing specifiers for a procedure
tok = tokens.Arr[spec_idx];
@ -1318,9 +1318,9 @@ Code parse_assignment_expression()
level++;
if (currtok.Type == Tok_BraceCurly_Close )
level--;
if (currtok.Type == Tok_Capture_Start)
if (currtok.Type == Tok_Paren_Open)
level++;
else if (currtok.Type == Tok_Capture_End)
else if (currtok.Type == Tok_Paren_Close)
level--;
eat( currtok.Type );
@ -1753,7 +1753,7 @@ CodeBody parse_global_nspace( CodeType which )
if ( NumSpecifiers )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <Attributes> <Specifiers>
}
@ -1873,7 +1873,7 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers )
if (nav.Type == Tok_Operator && nav.Text.Ptr[1] == '>')
-- template_level;
if ( nav.Type == Tok_Capture_Start)
if ( nav.Type == Tok_Paren_Open)
{
if (template_level != 0 )
++ capture_level;
@ -1881,12 +1881,12 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers )
break;
}
if ( template_level != 0 && nav.Type == Tok_Capture_End)
if ( template_level != 0 && nav.Type == Tok_Paren_Close)
-- capture_level;
}
}
if ( nav.Type == Tok_Capture_Start )
if ( nav.Type == Tok_Paren_Open )
break;
}
@ -1932,10 +1932,10 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers )
if (tok_left.Type == Tok_Operator && tok_left.Text.Ptr[1] == '>')
-- template_level;
if ( template_level != 0 && tok_left.Type == Tok_Capture_Start)
if ( template_level != 0 && tok_left.Type == Tok_Paren_Open)
++ capture_level;
if ( template_level != 0 && tok_left.Type == Tok_Capture_End)
if ( template_level != 0 && tok_left.Type == Tok_Paren_Close)
-- capture_level;
if ( capture_level == 0 && template_level == 0 && tok_left.Type == Tok_Identifier )
@ -2483,7 +2483,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
Token name = parse_identifier(nullptr);
_ctx->parser.Scope->Name = name.Text;
bool detected_capture = check( Tok_Capture_Start );
bool detected_capture = check( Tok_Paren_Open );
// Check three tokens ahead to make sure that were not dealing with a constructor initialization...
// ( 350.0f , <--- Could be the scenario
@ -2508,11 +2508,11 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
{
Token tok = _ctx->parser.Tokens.Arr[ idx ];
if ( tok.Type == Tok_Capture_Start )
if ( tok.Type == Tok_Paren_Open )
level++;
else if ( tok.Type == Tok_Capture_End && level > 0 )
else if ( tok.Type == Tok_Paren_Close && level > 0 )
level--;
if (level == 0 && tok.Type == Tok_Capture_End)
if (level == 0 && tok.Type == Tok_Paren_Close)
break;
}
++ idx; // Will incremnt to possible comma position
@ -2609,7 +2609,7 @@ CodeParams parse_params( bool use_template_capture )
push_scope();
if ( ! use_template_capture ) {
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
// (
}
else {
@ -2618,9 +2618,9 @@ CodeParams parse_params( bool use_template_capture )
// <
}
if ( ! use_template_capture && check( Tok_Capture_End ) )
if ( ! use_template_capture && check( Tok_Paren_Close ) )
{
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// )
parser_pop(& _ctx->parser);
return NullCode;
@ -2651,7 +2651,7 @@ CodeParams parse_params( bool use_template_capture )
}
#define CheckEndParams() \
(use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Capture_End))
(use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Paren_Close))
// TODO(Ed): Use expression macros or this? macro as attribute?
// Ex: Unreal has this type of macro: vvvvvvvvv
@ -2719,10 +2719,10 @@ CodeParams parse_params( bool use_template_capture )
if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>')
-- template_level;
if ( currtok.Type == Tok_Capture_Start)
if ( currtok.Type == Tok_Paren_Open)
++ capture_level;
if ( currtok.Type == Tok_Capture_End)
if ( currtok.Type == Tok_Paren_Close)
-- capture_level;
value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr;
@ -2833,10 +2833,10 @@ CodeParams parse_params( bool use_template_capture )
if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>')
-- template_level;
if ( currtok.Type == Tok_Capture_Start)
if ( currtok.Type == Tok_Paren_Open)
++ capture_level;
if ( currtok.Type == Tok_Capture_End)
if ( currtok.Type == Tok_Paren_Close)
-- capture_level;
value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr;
@ -2868,7 +2868,7 @@ CodeParams parse_params( bool use_template_capture )
if ( ! use_template_capture )
{
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// ( <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, .. )
}
else
@ -2941,20 +2941,20 @@ Code parse_simple_preprocess( TokType which )
// TODO(Ed) : Parse this properly later (expression and statement support)
if ( macro && macro_is_functional(* macro) )
{
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
s32 level = 0;
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
{
if ( currtok.Type == Tok_Capture_Start )
if ( currtok.Type == Tok_Paren_Open )
level++;
else if ( currtok.Type == Tok_Capture_End && level > 0 )
else if ( currtok.Type == Tok_Paren_Close && level > 0 )
level--;
eat( currtok.Type );
}
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// <Macro> ( <params> )
full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr;
@ -3067,21 +3067,21 @@ Code parse_static_assert()
_ctx->parser.Scope->Name = content.Text;
eat( Tok_StaticAssert );
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
// static_assert(
// TODO(Ed) : Parse this properly.
s32 level = 0;
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
{
if ( currtok.Type == Tok_Capture_Start )
if ( currtok.Type == Tok_Paren_Open )
level++;
else if ( currtok.Type == Tok_Capture_End )
else if ( currtok.Type == Tok_Paren_Close )
level--;
eat( currtok.Type );
}
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
eat( Tok_Statement_End );
// static_assert( <Content> );
@ -3183,9 +3183,9 @@ CodeVar parse_variable_after_name(
// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> }
}
if ( currtok.Type == Tok_Capture_Start )
if ( currtok.Type == Tok_Paren_Open )
{
eat( Tok_Capture_Start);
eat( Tok_Paren_Open);
// <Attributes> <Specifiers> <ValueType> <Name> (
Token expr_token = currtok;
@ -3193,12 +3193,12 @@ CodeVar parse_variable_after_name(
using_constructor_initializer = true;
s32 level = 0;
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
{
if ( currtok.Type == Tok_Capture_Start )
if ( currtok.Type == Tok_Paren_Open )
level++;
else if ( currtok.Type == Tok_Capture_End && level > 0 )
else if ( currtok.Type == Tok_Paren_Close && level > 0 )
level--;
eat( currtok.Type );
@ -3206,7 +3206,7 @@ CodeVar parse_variable_after_name(
expr_token.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_token.Text.Ptr;
expr = untyped_str( tok_to_str(expr_token) );
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> )
}
@ -3406,9 +3406,9 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
s32 level = 0;
while ( left && ( currtok.Type != Tok_BraceCurly_Open || level > 0 ) )
{
if (currtok.Type == Tok_Capture_Start)
if (currtok.Type == Tok_Paren_Open)
level++;
else if ( currtok.Type == Tok_Capture_End )
else if ( currtok.Type == Tok_Paren_Close )
level--;
eat( currtok.Type );
@ -3498,7 +3498,7 @@ CodeDefine parser_parse_define()
Macro* macro = lookup_macro(define->Name);
if (macro_is_functional(* macro)) {
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
// #define <Name> (
// We provide the define params even if empty to make sure '()' are serialized.
@ -3506,7 +3506,7 @@ CodeDefine parser_parse_define()
params = (CodeDefineParams) make_code();
params->Type = CT_Parameters_Define;
if ( left && currtok.Type != Tok_Capture_End ) {
if ( left && currtok.Type != Tok_Paren_Close ) {
params->Name = currtok.Text;
params->NumEntries ++;
@ -3514,7 +3514,7 @@ CodeDefine parser_parse_define()
// #define <Name> ( <param>
}
while( left && currtok.Type != Tok_Capture_End ) {
while( left && currtok.Type != Tok_Paren_Close ) {
eat( Tok_Comma );
// #define <Name> ( <param>,
@ -3527,7 +3527,7 @@ CodeDefine parser_parse_define()
eat( Tok_Preprocess_Define_Param );
}
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// #define <Name> ( <params> )
define->Params = params;
@ -3595,8 +3595,8 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers )
CodeComment inline_cmt = NullCode;
// <Virtual Specifier> ~<Name>
eat( Tok_Capture_Start );
eat( Tok_Capture_End );
eat( Tok_Paren_Open );
eat( Tok_Paren_Close );
// <Virtual Specifier> ~<Name>()
bool pure_virtual = false;
@ -4012,7 +4012,7 @@ CodeFriend parser_parse_friend()
}
if ( NumSpecifiers ) {
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <friend> <specifiers>
}
@ -4129,7 +4129,7 @@ CodeFn parser_parse_function()
}
if ( NumSpecifiers ) {
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <export> <Attributes> <Specifiers>
@ -4237,7 +4237,7 @@ CodeOperator parser_parse_operator()
}
if ( NumSpecifiers ) {
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <export> <Attributes> <Specifiers>
@ -4286,8 +4286,8 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers )
Token scope_name_tok = { scope_name, Tok_Identifier, 0, 0, TF_Null };
_ctx->parser.Scope->Name = scope_name_tok.Text;
eat( Tok_Capture_Start );
eat( Tok_Capture_End );
eat( Tok_Paren_Open );
eat( Tok_Paren_Close );
// <Specifiers> <Qualifier> :: ... operator <UnderlyingType>()
// TODO(Ed) : operator cast can have const, volatile, l-value, r-value noexecept qualifying specifiers.
@ -4475,7 +4475,7 @@ CodeTemplate parser_parse_template()
}
if ( NumSpecifiers ) {
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <export> template< <Parameters> > <Attributes> <Specifiers>
}
@ -4638,18 +4638,18 @@ else if ( currtok.Type == Tok_DeclType )
eat( Tok_DeclType );
// <Attributes> <Specifiers> decltype
eat( Tok_Capture_Start );
while ( left && currtok.Type != Tok_Capture_End )
eat( Tok_Paren_Open );
while ( left && currtok.Type != Tok_Paren_Close )
{
if ( currtok.Type == Tok_Capture_Start )
if ( currtok.Type == Tok_Paren_Open )
level++;
if ( currtok.Type == Tok_Capture_End )
if ( currtok.Type == Tok_Paren_Close )
level--;
eat( currtok.Type );
}
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text;
_ctx->parser.Scope->Name = name;
@ -4733,7 +4733,7 @@ else if ( currtok.Type == Tok_DeclType )
#ifdef GEN_USE_NEW_TYPENAME_PARSING
if ( NumSpecifiers )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
NumSpecifiers = 0;
}
#endif
@ -4758,7 +4758,7 @@ else if ( currtok.Type == Tok_DeclType )
is_function_typename = true;
++scanner;
}
is_function_typename = scanner->Type == Tok_Capture_Start;
is_function_typename = scanner->Type == Tok_Paren_Open;
Token* first_capture = scanner;
if ( is_function_typename )
@ -4768,7 +4768,7 @@ else if ( currtok.Type == Tok_DeclType )
++scanner;
// Go back to the first capture start found
while ( scanner->Type != Tok_Capture_Start )
while ( scanner->Type != Tok_Paren_Open )
--scanner;
last_capture = scanner;
@ -4813,7 +4813,7 @@ else if ( currtok.Type == Tok_DeclType )
#else
if ( NumSpecifiers )
return_type->Specs = def_specifiers( NumSpecifiers, ( Specifier* )specs_found );
return_type->Specs = def_specifiers_arr( NumSpecifiers, ( Specifier* )specs_found );
// Reset specifiers, the function itself will have its own suffix specifiers possibly.
NumSpecifiers = 0;
@ -4822,7 +4822,7 @@ else if ( currtok.Type == Tok_DeclType )
name = NullToken;
// The next token can either be a capture for the identifier or it could be the identifier exposed.
if ( ! check( Tok_Capture_Start ) )
if ( ! check( Tok_Paren_Open ) )
{
// Started with an identifier immeidately, which means its of the format: <ReturnType> <identifier> <capture>;
name = parse_identifier(nullptr);
@ -4842,7 +4842,7 @@ else if ( currtok.Type == Tok_DeclType )
// Parse immeidate capture which would be with parse_params()
// Eat Capture End
#ifdef GEN_USE_NEW_TYPENAME_PARSING
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
// <Attributes> <ReturnType> (
// Binding specifiers
@ -4864,7 +4864,7 @@ else if ( currtok.Type == Tok_DeclType )
if ( NumSpecifiers )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
NumSpecifiers = 0;
// <Attributes> <ReturnType> ( <Specifiers>
@ -4875,11 +4875,11 @@ else if ( currtok.Type == Tok_DeclType )
// Immeidate parameters
if ( check( Tok_Capture_Start ) )
if ( check( Tok_Paren_Open ) )
params_nested = parse_params();
// <Attributes> <ReturnType> ( <Specifiers> <Identifier> ( <Parameters> )
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// <Attributes> <ReturnType> ( <Specifiers> <Identifier> ( <Parameters> ) )
#else
@ -4887,21 +4887,21 @@ else if ( currtok.Type == Tok_DeclType )
// Everything within this capture will just be shoved into the name field including the capture tokens themselves.
name = currtok;
eat( Tok_Capture_Start );
eat( Tok_Paren_Open );
// <Attributes> <ReturnType> (
s32 level = 0;
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
{
if ( currtok.Type == Tok_Capture_Start )
if ( currtok.Type == Tok_Paren_Open )
level++;
if ( currtok.Type == Tok_Capture_End )
if ( currtok.Type == Tok_Paren_Close )
level--;
eat( currtok.Type );
}
eat( Tok_Capture_End );
eat( Tok_Paren_Close );
// <Attributes> <ReturnType> ( <Expression> )
name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr;
@ -4935,7 +4935,7 @@ else if ( currtok.Type == Tok_DeclType )
#ifdef GEN_USE_NEW_TYPENAME_PARSING
if ( NumSpecifiers )
{
func_suffix_specs = def_specifiers( NumSpecifiers, specs_found );
func_suffix_specs = def_specifiers_arr( NumSpecifiers, specs_found );
NumSpecifiers = 0;
}
#endif
@ -4985,7 +4985,7 @@ else if ( currtok.Type == Tok_DeclType )
#else
if ( NumSpecifiers )
{
CodeSpecifiers specifiers = def_specifiers( NumSpecifiers, ( Specifier* )specs_found );
CodeSpecifiers specifiers = def_specifiers_arr( NumSpecifiers, ( Specifier* )specs_found );
result->Specs = specifiers;
}
#endif
@ -5523,7 +5523,7 @@ CodeVar parser_parse_variable()
}
if ( NumSpecifiers ) {
specifiers = def_specifiers( NumSpecifiers, specs_found );
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
}
// <ModuleFlags> <Attributes> <Specifiers>

View File

@ -5,10 +5,9 @@
#pragma region StaticData
global Context* _ctx;
#pragma region Constants
global u32 context_counter;
#pragma region Constants
global Macro enum_underlying_macro;
global Code Code_Global;

View File

@ -284,8 +284,7 @@ bool array_fill(Array<Type> array, usize begin, usize end, Type value)
if (begin < 0 || end > header->Num)
return false;
for (ssize idx = ssize(begin); idx < ssize(end); idx++)
{
for (ssize idx = ssize(begin); idx < ssize(end); idx++) {
array[idx] = value;
}

View File

@ -11,10 +11,10 @@
#if GEN_BUILD_DEBUG
# if defined( GEN_COMPILER_MSVC )
# if _MSC_VER < 1300
#pragma message("GEN_BUILD_DEBUG: __asm int 3")
// #pragma message("GEN_BUILD_DEBUG: __asm int 3")
# define GEN_DEBUG_TRAP() __asm int 3 /* Trap to debugger! */
# else
#pragma message("GEN_BUILD_DEBUG: __debugbreak()")
// #pragma message("GEN_BUILD_DEBUG: __debugbreak()")
# define GEN_DEBUG_TRAP() __debugbreak()
# endif
# elif defined( GEN_COMPILER_TINYC )
@ -23,7 +23,7 @@
# define GEN_DEBUG_TRAP() __builtin_trap()
# endif
#else
#pragma message("GEN_BUILD_DEBUG: omitted")
// #pragma message("GEN_BUILD_DEBUG: omitted")
# define GEN_DEBUG_TRAP()
#endif

View File

@ -90,11 +90,11 @@
#ifndef do_once
#define do_once() \
static int __do_once_counter_##src_line_str = 0; \
local_persist int __do_once_counter_##src_line_str = 0; \
for(; __do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1 ) \
#define do_once_defer( expression ) \
static int __do_once_counter_##src_line_str = 0; \
local_persist int __do_once_counter_##src_line_str = 0; \
for(;__do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1, (expression)) \
#define do_once_start \

View File

@ -13,8 +13,8 @@ BraceCurly_Open, "{"
BraceCurly_Close, "}"
BraceSquare_Open, "["
BraceSquare_Close, "]"
Capture_Start, "("
Capture_End, ")"
Paren_Open, "("
Paren_Close, ")"
Comment, "__comment__"
Comment_End, "__comment_end__"
Comment_Start, "__comment_start__"

1 Invalid __invalid__
13 BraceCurly_Close }
14 BraceSquare_Open [
15 BraceSquare_Close ]
16 Capture_Start Paren_Open (
17 Capture_End Paren_Close )
18 Comment __comment__
19 Comment_End __comment_end__
20 Comment_Start __comment_start__

View File

@ -238,6 +238,7 @@ Interface :
* parse_class
* parse_constructor
* parse_define
* parse_destructor
* parse_enum
* parse_export_body
@ -322,6 +323,7 @@ Code <name> = parse_<function name>( gen_code_str );
The following are provided predefined by the library as they are commonly used:
* `enum_underlying_macro`
* `access_public`
* `access_protected`
* `access_private`

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

View File

@ -1,7 +1,5 @@
## Navigation
# base
[Top](../Readme.md)
* [docs](../docs/Readme.md)
@ -15,9 +13,133 @@ The output will be in the `gen_segmented/gen` directory (if the directory does n
If using the library's provided build scripts:
```ps1
.\build.ps1 <compiler> <debug or omit> c_library
.\build.ps1 <compiler> <debug or omit> c_lib
```
To generate a static or dynamic library:
```ps1
.\build.ps1 <compiler> <debug or omit> c_lib_static c_lib_dyn
```
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](./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.**
## Generation structure
1. Files are scanned in or parsed.
* If they are parsed, its dude to requiring some changes to either naming, or adding additonal definitions (container generation, typedefs, etc).
2. All scanned or parsed code is refactored (identifiers substs) and/or formatted.
3. Singleheader generated.
4. Segemented headers and source generated.
## Templated container generation
The array and hashtable containers used across this library are generated using the following implementatioon:
* [containers.array.hpp](./components/containers.array.hpp)
* [containers.hashtable.hpp](./components/containers.hashtable.hpp)
These are functionally (and interface wise) equivalent to the library's `Array<Type>` `HashTable<Type>` within [containers.hpp](../base/dependencies/containers.hpp)
Both files follow the same patter of providing three procedures:
* `gen_<container>_base` : Intended to be called once, defines universal "base" definitions.
* `gen_<container>` : Called per instatiation of the container for a given set of dependent args.
* `gen_<container>_generic_selection_interface` : Intended to be called once after all of the instantiated containers have finished generating. It will generate a set of generic selection macros as described by Macro Usage section below.
A simple `<container>_DefinitionCounter` is used to know how many instantiations of the template have occured. This is used to determine how to define `GENERIC_SLOT_<ID>_<functionID>` for the generic interface along with how many slots the `_Generic` macro will need to have generated.
## Macro Usage
For the most part macros are kept minimal with exception to `_Generic`...
*(I will be explaining this thing for the rest of this seciton along with gencpp c library's usage of it)*
The `_Generic` macro plays a key role in reducing direct need of the user to wrangle with mangled definition identifiers of 'templated' containers or for type coercion to map distinct data types to a common code path.
Because of its lack of use in many C11 libraries.. and, of those that do; they usually end up obfuscating it with excessive preprocessor abuse; Effort was put into minimizing how much of these macros are handled by the preprocessor vs gencpp itself.
The usual presentation (done bare) is the following:
```c
#define macro_that_selects_typeof_arg(arg, y) \
_Generic( (arg), \
int : some expression, \
double : some other expression, \
struct Whatnot : something else again, \
default : fallback expression \
)
```
Where `_Generic` can be considered the follwoing (psuedo-C):
```c
#define type_expr_pair(type, expr) type: expr
C_Expression _Generic( selector_arg, a_type_expr_pair, ... ) {
switch( typeof(selector_arg)) {
case a_type_expr_pair:
return a_type_expr_pari.expr;
...
default:
return default.expr;
}
}
```
The first `arg` of _Generic behaves as the "controlling expression" or the expression that resolves to a type which will dictate which of the following expressions provided after to `_Generic` will be resolved as the one used inline for the implemenation.
For this library's purposes we'll be using the functional macro equivalent *(if there is an excpetion I'll link it at the end fo the section)*:
```c
#define macro_that_uses_selector_arg_for_resolving_a_fucntion( selecting_exp) \
_Generic( (arg), \
int : func_use_int, \
double : func_use_double, \
struct Whatnot : func_use_Whatnot, \
default : struct SIGNALS_FAILURE \
) (selecting_exp)
```
In this case, we directly added `(selecting_exp)` to the end there.. as we want to directly have the macro resolve to calling a resolved procedure. A default has been set to a struct as that leads to a neat compiler message that would otherwise be impossible beause static_assert is a statement and thus cannot be used within a slot.
Now, even with gencpp generating this type-expression table, we still need wrapper macros to achieve function 'overloading' for the templated containers as _Generic has a [significant drawback](https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/):
> Discarded expressions still have to be semantically valid.
The only way to absolve this issue [(without resorting to nasty preprocessor hacks)](https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md) is with wrapping expressions in 'slot' resolving macros that do not expand if the slot is not defined:
```c
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__function_sig )
```
`GENERIC_SLOT_1__function_sig` is our warpper of a "`int, func_use_int`" pair. The `GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT` is a verbse named macro to indicate that that pair will be expanded ***ONLY IF*** its defined.
So for any given templated container interface. Expect the follwoing (taken straight from generation, and just cleaned up formatting):
```c
#define gen_array_append( selector_arg, ... ) _Generic( \
(selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_1__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_2__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_3__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_4__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_5__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_6__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_7__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_8__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_9__array_append ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_10__array_append ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( &selector_arg, __VA_ARGS__ )
```
*Note(Ed): Unfortunately I cannot get clang-format to output these macros sanely like the above..*
*Eventually I'll add some basic builtin formatting but if the user has suggestions for something better I'm open ears...*
`GEN_RESOLVED_FUNCTION_CALL` is an empty define, its just to indicate that its intended to expand to a function call.
To see the thea actual macro definitions used: [generic_macros.h](./components/generic_macros.h) has them. They'll be injected right after the usual macros are positioned in the header file.

View File

@ -1126,6 +1126,9 @@ R"(#define <interface_name>( code ) _Generic( (code), \
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_interface, interface );
if (found) break;
found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP"), entry, parsed_interface, interface);
if (found) break;
interface.append(entry);
}
break;
@ -1136,13 +1139,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
CodeFn fn = cast(CodeFn, entry);
Code prev = entry->Prev;
if (prev && prev->Name.is_equal(entry->Name)) {
// rename second definition so there isn't a symbol conflict
StrBuilder postfix_arr = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "%S_arr", entry->Name);
entry->Name = cache_str(postfix_arr.to_str());
postfix_arr.free();
}
b32 handled= false;
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
{
@ -1368,15 +1364,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
{
CodeFn fn = cast(CodeFn, entry);
Code prev = entry->Prev;
for ( CodeParams arr_param : fn->Params )
{
b32 repeat_register_macros = fn->Name.is_equal(txt("register_macros")) && arr_param->Name.is_equal(txt("num")) && ! arr_param->Next->Name.is_equal(txt("..."));
if ( repeat_register_macros ) {
// rename second definition so there isn't a symbol conflict
StrBuilder postfix_arr = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "%S_arr", fn->Name);
fn->Name = cache_str(postfix_arr.to_str());
}
}
src_interface.append(fn);
}
break;
@ -1443,16 +1430,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
{
CodeFn fn = cast(CodeFn, entry);
Code prev = entry->Prev;
for ( CodeParams arr_param : fn->Params )
{
b32 repeat_def_array = fn->Name.starts_with(txt("def_")) && arr_param->Name.is_equal(txt("num")) && ! arr_param->Next->Name.is_equal(txt("..."));
if ( repeat_def_array ) {
// rename second definition so there isn't a symbol conflict
StrBuilder postfix_arr = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "%S_arr", fn->Name);
fn->Name = cache_str(postfix_arr.to_str());
}
}
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
{
// The frontend names are warapped in macros so we need to give it the intenral symbol name

View File

@ -408,6 +408,8 @@ namespace var_, gen_var_
// Gen Interface
word _ctx, gen__ctx
word init, gen_init
word deinit, gen_deinit
word reset, gen_reset

View File

@ -238,10 +238,10 @@ CodeBody gen_array( Str type, Str array_name )
GEN_ASSERT(begin <= end);
ArrayHeader* header = array_get_header( self );
if ( begin < 0 || end >= header->Num )
if ( begin < 0 || end > header->Num )
return false;
for ( ssize idx = begin; idx < end; idx ++ )
for ( ssize idx = (ssize)begin; idx < (ssize)end; idx ++ )
self[ idx ] = value;
return true;

View File

@ -13,7 +13,7 @@
| \_____|\___}_l |_|\___} .__/| .__/ {_____/ \__\__/_l\__. |\___/\__,_l \____}{_____}{_____} |
| | | | | __} | |
| l_l l_l {___/ |
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
! ============================================================================================= |
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |

View File

@ -15,7 +15,7 @@
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
| Singleheader | | | | __} | |
| l_l l_l {___/ |
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
! ============================================================================================ |
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |

View File

@ -16,7 +16,7 @@
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
| Unreal Engine | | | | __} | |
| l_l l_l {___/ |
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
! ============================================================================================ |
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |

View File

@ -4,3 +4,4 @@ COREUOBJECT_API, COREUOBJECT_API
ENGINE_API, ENGINE_API
GAMEPLAYABILITIES_API, GAMEPLAYABILITIES_API
UMG_API, UMG_API
GASA_API, GASA_API
1 API_Export GEN_API_Export_Code
4 ENGINE_API ENGINE_API
5 GAMEPLAYABILITIES_API GAMEPLAYABILITIES_API
6 UMG_API UMG_API
7 GASA_API GASA_API

View File

@ -100,7 +100,8 @@ int gen_main()
(Macro { txt("GEN_PARAM_DEFAULT"), MT_Expression, MF_Null }),
(Macro { txt("struct_init"), MT_Expression, MF_Functional }),
(Macro { txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"), MT_Statement, MF_Null }),
(Macro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null })
(Macro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null }),
(Macro { txt("src_line_str"), MT_Expression, MF_Null })
));
// gen_dep.hpp

View File

@ -15,11 +15,13 @@ Its main uage is the [c_library generation](../gen_c_library/).
Remove any generated content from the repository.
**`build.ps1`**
Build c_library, segmented, singleheader, unreal. Supports msvc or clang, release or debug.
Build c library (segmented, singleheader, static, or dynamic), cpp library (segmented, singleheader, or unreal). Supports msvc or clang, release or debug.
```
```erlang
args:
c_library
c_lib : Build c11 library (singleheader & segmented)
c_lib_static : Build static c11 library
c_lib_dyn : Buidl dyanmic c11
segemented
singleheader
unreal

View File

@ -325,18 +325,23 @@ if ( $unreal )
. $refactor_unreal
}
if ( $test )
# C Library testing
if ( $test -and $false )
{
$path_test_c_lib = join-path $path_test c_library
$path_build = join-path $path_test_c_lib build
$path_test_c = join-path $path_test c_library
$path_build = join-path $path_test_c build
$path_gen = join-path $path_test_c gen
if ( -not(Test-Path($path_build) )) {
New-Item -ItemType Directory -Path $path_build
}
if ( -not(Test-Path($path_gen) )) {
New-Item -ItemType Directory -Path $path_gen
}
$includes = @( $path_c_library )
$unit = join-path $path_test_c_lib "gen.c"
$executable = join-path $path_build "gen_c_library_test.exe"
$path_singleheader_include = join-path $path_c_library gen
$includes = @( $path_singleheader_include )
$unit = join-path $path_test_c "test.c"
$executable = join-path $path_build "test.exe"
$compiler_args = @()
$compiler_args += ( $flag_define + 'GEN_TIME' )
@ -350,7 +355,7 @@ if ( $test )
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
Push-Location $path_test_c_lib
Push-Location $path_test_c
if ( Test-Path( $executable ) ) {
write-host "`nRunning c_library test"
$time_taken = Measure-Command { & $executable
@ -362,6 +367,45 @@ if ( $test )
}
Pop-Location
}
if ($test -and $true)
{
$path_test_cpp = join-path $path_test cpp_library
$path_build = join-path $path_test_cpp build
$path_gen = join-path $path_test_cpp gen
if ( -not(Test-Path($path_build) )) {
New-Item -ItemType Directory -Path $path_build
}
if ( -not(Test-Path($path_gen) )) {
New-Item -ItemType Directory -Path $path_gen
}
$path_singleheader_include = join-path $path_singleheader gen
$includes = @( $path_singleheader_include )
$unit = join-path $path_test_cpp "test.cpp"
$executable = join-path $path_build "test.exe"
$compiler_args = @()
$compiler_args += ( $flag_define + 'GEN_TIME' )
$linker_args = @(
$flag_link_win_subsystem_console
)
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
Push-Location $path_test_cpp
if ( Test-Path( $executable ) ) {
write-host "`nRunning cpp_library test"
$time_taken = Measure-Command { & $executable
| ForEach-Object {
write-host `t $_ -ForegroundColor Green
}
}
write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms"
}
Pop-Location
}
#endregion Building
Pop-Location # $path_root

View File

@ -1,9 +0,0 @@
#define GEN_IMPLEMENTATION
#include "gen/gen_singleheader.h"
int gen_main()
{
// init();
__debugbreak();
return 0;
}

32
test/c_library/test.c Normal file
View File

@ -0,0 +1,32 @@
#define GEN_IMPLEMENTATION
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#include "gen_singleheader.h"
#define gen_iterator( Type, container, iter ) \
gen_begin_ ## Type(container); \
iter != gen_end_ ## Type(container); \
code = gen_next_ ## Type(container, iter)
int main()
{
gen_Context ctx = {0};
gen_init(& ctx);
gen_Builder src_hello = gen_builder_open("gen/hello.c");
gen_CodeVar hello_var = gen_parse_variable(code(
char const* hello_gencpp_str = "HELLO GENCPP C11 !";
));
gen_builder_print( & src_hello, (gen_Code)hello_var );
gen_builder_write(& src_hello);
gen_CodeBody body = gen_parse_file("gen/hello.c");
for (gen_Code code = gen_iterator(CodeBody, body, code)) switch (code->Type) {
case CT_Variable:
gen_CodeVar var = (gen_CodeVar) code;
gen_log_fmt("%S", var->Value);
break;
}
gen_deinit(& ctx);
return 0;
}

29
test/cpp_library/test.cpp Normal file
View File

@ -0,0 +1,29 @@
#define GEN_IMPLEMENTATION
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#include "gen.hpp"
int main()
{
using namespace gen;
Context ctx = {};
gen::init( & ctx);
Builder src_hello = builder_open("gen/hello.cpp");
CodeVar hello_var = parse_variable( code(
constexpr char const* hello_gencpp_str = "HELLO GENCPP !";
));
src_hello.print(hello_var);
src_hello.write();
CodeBody body = parse_file("gen/hello.cpp");
for ( Code code : body ) switch (code->Type) {
case CT_Variable:
CodeVar var = cast(CodeVar, code);
log_fmt("%S", var->Value);
break;
}
gen::deinit(& ctx);
return 0;
}