Compare commits

..

No commits in common. "cb898595b09d276592aeb788c7b7586b952c1d9f" and "401f85f673212e1eae359485913df08171d5ad00" have entirely different histories.

33 changed files with 373 additions and 433 deletions

View File

@ -10,16 +10,18 @@ Its not meant to be a black box metaprogramming utility, it should be easy to in
## 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/): C11 library variant generation (single header and segmeented).
* [gen_segmented](./gen_segmented/): Segemented C++ (`gen.<hpp/cpp>`, `gen.dep.<hpp/cpp>`) generation
* [gen_singleheader](./gen_singleheader/): Singlehader C++ generation `gen.hpp`
* [gen_unreal_engine](./gen_unreal_engine/): Unreal Engine thirdparty code generation.
* [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

View File

@ -31,6 +31,8 @@ Standard formats:
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:
@ -69,11 +71,7 @@ This library was written in a subset of C++ where the following are not used at
* 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.
Member function support or free-functions with reference object passing are wrapped in `! GEN_C_LIKE CPP` preprocess conditionals.
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
@ -119,7 +117,7 @@ The vast majority of macros should be single-line subsitutions that either add:
There are ***five*** header files which are automatically generated using [base_codegen.hpp](./helpers/base_codegen.hpp) by [base.cpp](./base.cpp). They are all located in [components/gen](./components/gen/).
* [`ecodetypes.hpp`](./components/gen/ecode.hpp): `CodeType` enum definition and related implementaiton. Generation is based off of [`ECodeType.csv](./enums/ECodeTypes.csv).
* [`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:
@ -137,7 +135,7 @@ Currently unsupported. I want the library to be *stable* and *correct*, with the
This library is relatively very small (for parsing C++), and can be extended without much hassle.
The convention you'll see used throughout the upfront interface of the library is as follows:
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`.
@ -148,7 +146,7 @@ Names or Content fields are interned strings and thus showed be cached using `ge
`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`](../docs/Parsing.md) and [`docs/Parser_Algo.md`](../docs/Parser_Algo.md). Extending it is more serious.
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

View File

@ -43,7 +43,7 @@ int gen_main()
CodeBody especifier = gen_especifier( "enums/ESpecifier.csv" );
CodeBody ast_inlines = gen_ast_inlines();
Builder header_ecode = builder_open( "components/gen/ecodetypes.hpp" );
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);

View File

@ -497,7 +497,7 @@ void code_to_string_ptr( Code self, String* result )
break;
case CT_Parameters:
params_to_string_ref(cast(CodeParams, self), result );
params_to_string_ref(cast(CodeParam, self), result );
break;
case CT_Preprocess_Define:

View File

@ -37,7 +37,7 @@ struct AST_Module;
struct AST_NS;
struct AST_Operator;
struct AST_OpCast;
struct AST_Params;
struct AST_Param;
struct AST_Pragma;
struct AST_PreprocessCond;
struct AST_Specifiers;
@ -109,7 +109,7 @@ typedef AST_Module* CodeModule;
typedef AST_NS* CodeNS;
typedef AST_Operator* CodeOperator;
typedef AST_OpCast* CodeOpCast;
typedef AST_Params* CodeParams;
typedef AST_Param* CodeParam;
typedef AST_PreprocessCond* CodePreprocessCond;
typedef AST_Pragma* CodePragma;
typedef AST_Specifiers* CodeSpecifiers;
@ -131,7 +131,7 @@ struct CodeModule;
struct CodeNS;
struct CodeOperator;
struct CodeOpCast;
struct CodeParams;
struct CodeParam;
struct CodePreprocessCond;
struct CodePragma;
struct CodeSpecifiers;
@ -209,7 +209,6 @@ struct CodeStmt_Switch;
struct CodeStmt_While;
#endif
// GEN_EXECUTION_EXPRESSION_SUPPORT
#endif
#if GEN_COMPILER_C
@ -230,6 +229,8 @@ struct CodeUsing;
struct CodeVar;
#endif
#undef Define_Code
GEN_NS_PARSER_BEGIN
struct Token;
@ -342,7 +343,7 @@ struct Code
operator CodeNS() const;
operator CodeOperator() const;
operator CodeOpCast() const;
operator CodeParams() const;
operator CodeParam() const;
operator CodePragma() const;
operator CodePreprocessCond() const;
operator CodeSpecifiers() const;
@ -422,7 +423,7 @@ struct AST
union {
Code NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value )
Code SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed )
Code PostNameMacro; // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal)
Code PostNameMacro; // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal)
};
};
StringCached Content; // Attributes, Comment, Execution, Include
@ -455,7 +456,7 @@ struct AST
Operator Op;
AccessSpec ParentAccess;
s32 NumEntries;
s32 VarParenthesizedInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression.
s32 VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression.
};
};
static_assert( sizeof(AST) == AST_POD_Size, "ERROR: AST is not size of AST_POD_Size" );

View File

@ -127,7 +127,7 @@ struct AST_Constructor
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
CodeSpecifiers Specs;
Code InitializerList;
CodeParams Params;
CodeParam Params;
Code Body;
char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ];
};
@ -550,7 +550,7 @@ struct AST_Fn
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeTypename ReturnType;
CodeParams Params;
CodeParam Params;
CodeBody Body;
char _PAD_PROPERTIES_ [ sizeof(AST*) ];
};
@ -613,7 +613,7 @@ struct AST_Operator
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeTypename ReturnType;
CodeParams Params;
CodeParam Params;
CodeBody Body;
char _PAD_PROPERTIES_ [ sizeof(AST*) ];
};
@ -639,9 +639,9 @@ struct AST_OpCast
char _PAD_PROPERTIES_[ sizeof(AST*) ];
CodeSpecifiers Specs;
CodeTypename ValueType;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
CodeBody Body;
char _PAD_PROPERTIES_3_[ sizeof(AST*) ];
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
CodeBody Body;
char _PAD_PROPERTIES_3_[ sizeof(AST*) ];
};
};
StringCached Name;
@ -654,7 +654,7 @@ struct AST_OpCast
};
static_assert( sizeof(AST_OpCast) == sizeof(AST), "ERROR: AST_OpCast is not the same size as AST");
struct AST_Params
struct AST_Param
{
union {
char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ];
@ -669,15 +669,15 @@ struct AST_Params
};
};
StringCached Name;
CodeParams Last;
CodeParams Next;
CodeParam Last;
CodeParam Next;
Token* Tok;
Code Parent;
CodeType Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
s32 NumEntries;
};
static_assert( sizeof(AST_Params) == sizeof(AST), "ERROR: AST_Params is not the same size as AST");
static_assert( sizeof(AST_Param) == sizeof(AST), "ERROR: AST_Param is not the same size as AST");
struct AST_Pragma
{
@ -971,7 +971,7 @@ struct AST_Template
struct
{
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
CodeParams Params;
CodeParam Params;
Code Declaration;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
@ -1000,7 +1000,7 @@ struct AST_Type
CodeSpecifiers Specs;
Code QualifierID;
// CodeTypename ReturnType; // Only used for function signatures
// CodeParams Params; // Only used for function signatures
// CodeParam Params; // Only used for function signatures
Code ArrExpr;
// CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
};
@ -1017,6 +1017,7 @@ struct AST_Type
static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same size as AST");
#endif
// TODO(Ed): Add support for preserving the typename's keyword qualifier (struct, class, enum, etc), mostly needed for C.
struct AST_Typename
{
union {
@ -1027,7 +1028,7 @@ struct AST_Typename
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeTypename ReturnType; // Only used for function signatures
CodeParams Params; // Only used for function signatures
CodeParam Params; // Only used for function signatures
Code ArrExpr;
CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
};
@ -1139,7 +1140,7 @@ struct AST_Var
Code Parent;
CodeType Type;
ModuleFlag ModuleFlags;
s32 VarParenthesizedInit;
s32 VarConstructorInit;
};
static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST");

View File

@ -197,7 +197,7 @@ void class_to_string_def( CodeClass self, String* result )
while ( interface )
{
string_append_fmt( result, ", public %S", typename_to_string(interface) );
string_append_fmt( result, ", %S", typename_to_string(interface) );
interface = interface->Next ? cast(CodeTypename, interface->Next) : NullCode;
}
}
@ -863,7 +863,7 @@ void opcast_to_string_fwd(CodeOpCast self, String* result )
string_append_fmt( result, "operator %S();\n", typename_to_string(self->ValueType) );
}
String params_to_string(CodeParams self)
String params_to_string(CodeParam self)
{
GEN_ASSERT(self);
GEN_ASSERT(self);
@ -872,7 +872,7 @@ String params_to_string(CodeParams self)
return result;
}
void params_to_string_ref( CodeParams self, String* result )
void params_to_string_ref( CodeParam self, String* result )
{
GEN_ASSERT(self);
GEN_ASSERT(result);
@ -904,7 +904,7 @@ void params_to_string_ref( CodeParams self, String* result )
if ( self->NumEntries - 1 > 0 )
{
for ( CodeParams param = begin_CodeParams(self->Next); param != end_CodeParams(self->Next); param = next_CodeParams(self->Next, param) )
for ( CodeParam param = begin_CodeParam(self->Next); param != end_CodeParam(self->Next); param = next_CodeParam(self->Next, param) )
{
string_append_fmt( result, ", %S", params_to_string(param) );
}
@ -1385,7 +1385,7 @@ void var_to_string_ref(CodeVar self, String* result )
if ( self->Value )
{
if ( self->VarParenthesizedInit )
if ( self->VarConstructorInit )
string_append_fmt( result, "( %S ", code_to_string(self->Value) );
else
string_append_fmt( result, " = %S", code_to_string(self->Value) );
@ -1395,7 +1395,7 @@ void var_to_string_ref(CodeVar self, String* result )
if ( self->NextVar )
string_append_fmt( result, ", %S", var_to_string(self->NextVar) );
if ( self->VarParenthesizedInit )
if ( self->VarConstructorInit )
string_append_strc( result, txt(" )"));
return;
@ -1431,7 +1431,7 @@ void var_to_string_ref(CodeVar self, String* result )
if ( self->Value )
{
if ( self->VarParenthesizedInit )
if ( self->VarConstructorInit )
string_append_fmt( result, "( %S ", code_to_string(self->Value) );
else
string_append_fmt( result, " = %S", code_to_string(self->Value) );
@ -1440,7 +1440,7 @@ void var_to_string_ref(CodeVar self, String* result )
if ( self->NextVar )
string_append_fmt( result, ", %S", var_to_string(self->NextVar) );
if ( self->VarParenthesizedInit )
if ( self->VarConstructorInit )
string_append_strc( result, txt(" )"));
if ( self->InlineCmt )
@ -1471,7 +1471,7 @@ void var_to_string_ref(CodeVar self, String* result )
if ( self->Value )
{
if ( self->VarParenthesizedInit )
if ( self->VarConstructorInit )
string_append_fmt( result, "( %S ", code_to_string(self->Value) );
else
string_append_fmt( result, " = %S", code_to_string(self->Value) );
@ -1480,7 +1480,7 @@ void var_to_string_ref(CodeVar self, String* result )
if ( self->NextVar )
string_append_fmt( result, ", %S", var_to_string( self->NextVar) );
if ( self->VarParenthesizedInit )
if ( self->VarConstructorInit )
string_append_strc( result, txt(" )"));
string_append_strc( result, txt(";") );

View File

@ -32,15 +32,15 @@ String class_to_string ( CodeClass self );
void class_to_string_def( CodeClass self, String* result );
void class_to_string_fwd( CodeClass self, String* result );
void params_append (CodeParams params, CodeParams param );
CodeParams params_get (CodeParams params, s32 idx);
bool params_has_entries (CodeParams params );
String params_to_string (CodeParams params );
void params_to_string_ref(CodeParams params, String* result );
void params_append (CodeParam params, CodeParam param );
CodeParam params_get (CodeParam params, s32 idx);
bool params_has_entries (CodeParam params );
String params_to_string (CodeParam params );
void params_to_string_ref(CodeParam params, String* result );
CodeParams begin_CodeParams(CodeParams params);
CodeParams end_CodeParams (CodeParams params);
CodeParams next_CodeParams (CodeParams params, CodeParams entry_iter);
CodeParam begin_CodeParam(CodeParam params);
CodeParam end_CodeParam (CodeParam params);
CodeParam next_CodeParam (CodeParam params, CodeParam entry_iter);
bool specifiers_append (CodeSpecifiers specifiers, Specifier spec);
s32 specifiers_has (CodeSpecifiers specifiers, Specifier spec);
@ -188,28 +188,28 @@ struct CodeClass
AST_Class* ast;
};
struct CodeParams
struct CodeParam
{
#if ! GEN_C_LIKE_CPP
Using_Code( CodeParams );
forceinline void append( CodeParams other );
forceinline CodeParams get( s32 idx );
Using_Code( CodeParam );
forceinline void append( CodeParam other );
forceinline CodeParam get( s32 idx );
forceinline bool has_entries();
forceinline String to_string();
forceinline void to_string( String& result );
forceinline CodeParams begin() { return begin_CodeParams(* this); }
forceinline CodeParams end() { return end_CodeParams(* this); }
forceinline CodeParam begin() { return begin_CodeParam(* this); }
forceinline CodeParam end() { return end_CodeParam(* this); }
#endif
Using_CodeOps( CodeParams );
Using_CodeOps( CodeParam );
forceinline operator Code() { return { (AST*)ast }; }
forceinline CodeParams operator*() { return * this; }
forceinline AST_Params* operator->() {
forceinline CodeParam operator*() { return * this; }
forceinline AST_Param* operator->() {
GEN_ASSERT(ast);
return ast;
}
CodeParams& operator++();
AST_Params* ast;
CodeParam& operator++();
AST_Param* ast;
};
struct CodeSpecifiers
@ -951,7 +951,7 @@ struct InvalidCode_ImplictCaster
operator CodeNS () const { return cast(CodeNS, Code_Invalid); }
operator CodeOperator () const { return cast(CodeOperator, Code_Invalid); }
operator CodeOpCast () const { return cast(CodeOpCast, Code_Invalid); }
operator CodeParams () const { return cast(CodeParams, Code_Invalid); }
operator CodeParam () const { return cast(CodeParam, Code_Invalid); }
operator CodePragma () const { return cast(CodePragma, Code_Invalid); }
operator CodePreprocessCond() const { return cast(CodePreprocessCond, Code_Invalid); }
operator CodeSpecifiers () const { return cast(CodeSpecifiers, Code_Invalid); }
@ -984,7 +984,7 @@ struct NullCode_ImplicitCaster
operator CodeNS () const { return {nullptr}; }
operator CodeOperator () const { return {nullptr}; }
operator CodeOpCast () const { return {nullptr}; }
operator CodeParams () const { return {nullptr}; }
operator CodeParam () const { return {nullptr}; }
operator CodePragma () const { return {nullptr}; }
operator CodePreprocessCond() const { return {nullptr}; }
operator CodeSpecifiers () const { return {nullptr}; }
@ -1011,19 +1011,19 @@ forceinline Code end ( CodeBody body ) { return end_CodeBody(b
forceinline Code next ( CodeBody body, Code entry_iter ) { return next_CodeBody(body, entry_iter); }
forceinline void add_interface( CodeClass self, CodeTypename interface ) { return class_add_interface(self, interface); }
forceinline String to_string ( CodeClass self ) { return class_to_string(self); }
forceinline void to_string_def( CodeClass self, String& result ) { return class_to_string_def(self, & result); }
forceinline void to_string_fwd( CodeClass self, String& result ) { return class_to_string_fwd(self, & result); }
forceinline String to_string ( CodeClass self ) { return class_to_string(self); }
forceinline void to_string_def( CodeClass self, String& result ) { return class_to_string_def(self, & result); }
forceinline void to_string_fwd( CodeClass self, String& result ) { return class_to_string_fwd(self, & result); }
forceinline void append (CodeParams params, CodeParams param ) { return params_append(params, param); }
forceinline CodeParams get (CodeParams params, s32 idx) { return params_get(params, idx); }
forceinline bool has_entries(CodeParams params ) { return params_has_entries(params); }
forceinline String to_string (CodeParams params ) { return params_to_string(params); }
forceinline void to_string (CodeParams params, String& result ) { return params_to_string_ref(params, & result); }
forceinline void append (CodeParam params, CodeParam param ) { return params_append(params, param); }
forceinline CodeParam get (CodeParam params, s32 idx) { return params_get(params, idx); }
forceinline bool has_entries(CodeParam params ) { return params_has_entries(params); }
forceinline String to_string (CodeParam params ) { return params_to_string(params); }
forceinline void to_string (CodeParam params, String& result ) { return params_to_string_ref(params, & result); }
forceinline CodeParams begin(CodeParams params) { return begin_CodeParams(params); }
forceinline CodeParams end (CodeParams params) { return end_CodeParams(params); }
forceinline CodeParams next (CodeParams params, CodeParams entry_iter) { return next_CodeParams(params, entry_iter); }
forceinline CodeParam begin(CodeParam params) { return begin_CodeParam(params); }
forceinline CodeParam end (CodeParam params) { return end_CodeParam(params); }
forceinline CodeParam next (CodeParam params, CodeParam entry_iter) { return next_CodeParam(params, entry_iter); }
forceinline bool append (CodeSpecifiers specifiers, Specifier spec) { return specifiers_append(specifiers, spec); }
forceinline s32 has (CodeSpecifiers specifiers, Specifier spec) { return specifiers_has(specifiers, spec); }

View File

@ -520,7 +520,7 @@ inline AST_OpCast* CodeOpCast::operator->()
return ast;
}
inline CodeParams& CodeParams::operator=( Code other )
inline CodeParam& CodeParam::operator=( Code other )
{
if ( other.ast != nullptr && other->Parent != nullptr )
{
@ -531,7 +531,7 @@ inline CodeParams& CodeParams::operator=( Code other )
return *this;
}
inline CodeParams::operator bool()
inline CodeParam::operator bool()
{
return ast != nullptr;
}
@ -906,9 +906,9 @@ forceinline Code::operator CodeOpCast() const
return { (AST_OpCast*)ast };
}
forceinline Code::operator CodeParams() const
forceinline Code::operator CodeParam() const
{
return { (AST_Params*)ast };
return { (AST_Param*)ast };
}
forceinline Code::operator CodePragma() const

View File

@ -53,8 +53,6 @@ constexpr s32 MaxUntypedStrLength = GEN_MAX_UNTYPED_STR_LENGTH;
constexpr s32 LexAllocator_Size = GEN_LEX_ALLOCATOR_SIZE;
constexpr s32 Builder_StrBufferReserve = GEN_BUILDER_STR_BUFFER_RESERVE;
extern StrC enum_underlying_sig;
extern Code access_public;
extern Code access_protected;
extern Code access_private;
@ -69,7 +67,7 @@ extern Code fmt_newline;
extern CodePragma pragma_once;
extern CodeParams param_varadic;
extern CodeParam param_varadic;
extern CodePreprocessCond preprocess_else;
extern CodePreprocessCond preprocess_endif;

View File

@ -178,9 +178,9 @@ void class_add_interface( CodeClass self, CodeTypename type )
}
#pragma endregion CodeClass
#pragma region CodeParams
#pragma region CodeParam
inline
void params_append( CodeParams appendee, CodeParams other )
void params_append( CodeParam appendee, CodeParam other )
{
GEN_ASSERT(appendee);
GEN_ASSERT(other);
@ -206,37 +206,37 @@ void params_append( CodeParams appendee, CodeParams other )
self->NumEntries++;
}
inline
CodeParams params_get(CodeParams self, s32 idx )
CodeParam params_get(CodeParam self, s32 idx )
{
GEN_ASSERT(self);
CodeParams param = self;
CodeParam param = self;
do
{
if ( ++ param != nullptr )
return NullCode;
param = cast(CodeParams, cast(Code, param)->Next);
param = cast(CodeParam, cast(Code, param)->Next);
}
while ( --idx );
return param;
}
forceinline
bool params_has_entries(CodeParams self)
bool params_has_entries(CodeParam self)
{
GEN_ASSERT(self);
return self->NumEntries > 0;
}
#if GEN_COMPILER_CPP
forceinline
CodeParams& CodeParams::operator ++()
CodeParam& CodeParam::operator ++()
{
* this = ast->Next;
return * this;
}
#endif
forceinline
CodeParams begin_CodeParams(CodeParams params)
CodeParam begin_CodeParam(CodeParam params)
{
if ( params != nullptr )
return params;
@ -244,18 +244,18 @@ CodeParams begin_CodeParams(CodeParams params)
return NullCode;
}
forceinline
CodeParams end_CodeParams(CodeParams params)
CodeParam end_CodeParam(CodeParam params)
{
// return { (AST_Params*) rcast( AST*, ast)->Last };
// return { (AST_Param*) rcast( AST*, ast)->Last };
return NullCode;
}
forceinline
CodeParams next_CodeParams(CodeParams params, CodeParams param_iter)
CodeParam next_CodeParam(CodeParam params, CodeParam param_iter)
{
GEN_ASSERT(param_iter);
return param_iter->Next;
}
#pragma endregion CodeParams
#pragma endregion CodeParam
#pragma region CodeSpecifiers
inline

View File

@ -131,7 +131,7 @@ void define_constants()
pragma_once->Content = pragma_once->Name;
code_set_global((Code)pragma_once);
param_varadic = (CodeParams) make_code();
param_varadic = (CodeParam) make_code();
param_varadic->Type = CT_Parameters;
param_varadic->Name = get_cached_string( txt("...") );
param_varadic->ValueType = t_empty;
@ -183,6 +183,7 @@ void define_constants()
#endif
# undef def_constant_code_type
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 ));;
@ -211,10 +212,9 @@ void define_constants()
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
code_set_global(cast(Code, spec_local_persist));
if (enum_underlying_sig.Len == 0) {
enum_underlying_sig = txt("enum_underlying(");
}
array_append(PreprocessorDefines, enum_underlying_sig);
# pragma push_macro("enum_underlying")
array_append(PreprocessorDefines, txt("enum_underlying("));
# pragma pop_macro("enum_underlying")
# undef def_constant_spec
}

View File

@ -63,7 +63,7 @@ struct Opts_def_struct {
CodeClass def_class( StrC name, Opts_def_struct opts GEN_PARAM_DEFAULT );
struct Opts_def_constructor {
CodeParams params;
CodeParam params;
Code initializer_list;
Code body;
};
@ -86,7 +86,6 @@ struct Opts_def_enum {
EnumT specifier;
CodeAttributes attributes;
ModuleFlag mflags;
Code type_macro;
};
CodeEnum def_enum( StrC name, Opts_def_enum opts GEN_PARAM_DEFAULT );
@ -95,7 +94,7 @@ CodeExtern def_extern_link( StrC name, CodeBody body );
CodeFriend def_friend ( Code symbol );
struct Opts_def_function {
CodeParams params;
CodeParam params;
CodeTypename ret_type;
CodeBody body;
CodeSpecifiers specs;
@ -112,7 +111,7 @@ CodeModule def_module ( StrC name, Opts_def_module opts GEN
CodeNS def_namespace( StrC name, CodeBody body, Opts_def_namespace opts GEN_PARAM_DEFAULT );
struct Opts_def_operator {
CodeParams params;
CodeParam params;
CodeTypename ret_type;
CodeBody body;
CodeSpecifiers specifiers;
@ -128,7 +127,7 @@ struct Opts_def_operator_cast {
CodeOpCast def_operator_cast( CodeTypename type, Opts_def_operator_cast opts GEN_PARAM_DEFAULT );
struct Opts_def_param { Code value; };
CodeParams def_param ( CodeTypename type, StrC name, Opts_def_param opts GEN_PARAM_DEFAULT );
CodeParam def_param ( CodeTypename type, StrC name, Opts_def_param opts GEN_PARAM_DEFAULT );
CodePragma def_pragma( StrC directive );
CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC content );
@ -138,7 +137,7 @@ CodeSpecifiers def_specifier( Specifier specifier );
CodeStruct def_struct( StrC name, Opts_def_struct opts GEN_PARAM_DEFAULT );
struct Opts_def_template { ModuleFlag mflags; };
CodeTemplate def_template( CodeParams params, Code definition, Opts_def_template opts GEN_PARAM_DEFAULT );
CodeTemplate def_template( CodeParam params, Code definition, Opts_def_template opts GEN_PARAM_DEFAULT );
struct Opts_def_type {
ETypenameTag type_tag;
@ -197,8 +196,8 @@ CodeBody def_global_body ( s32 num, ... );
CodeBody def_global_body ( s32 num, Code* codes );
CodeBody def_namespace_body ( s32 num, ... );
CodeBody def_namespace_body ( s32 num, Code* codes );
CodeParams def_params ( s32 num, ... );
CodeParams def_params ( s32 num, CodeParams* params );
CodeParam def_params ( s32 num, ... );
CodeParam def_params ( s32 num, CodeParam* params );
CodeSpecifiers def_specifiers ( s32 num, ... );
CodeSpecifiers def_specifiers ( s32 num, Specifier* specs );
CodeBody def_struct_body ( s32 num, ... );

View File

@ -13,7 +13,7 @@ enum OpValidateResult : u32
};
internal neverinline
OpValidateResult operator__validate( Operator op, CodeParams params_code, CodeTypename ret_type, CodeSpecifiers specifier )
OpValidateResult operator__validate( Operator op, CodeParam params_code, CodeTypename ret_type, CodeSpecifiers specifier )
{
if ( op == Op_Invalid )
{
@ -497,7 +497,7 @@ CodeComment def_comment( StrC content )
CodeConstructor def_constructor( Opts_def_constructor p )
{
CodeParams params = p.params;
CodeParam params = p.params;
Code initializer_list = p.initializer_list;
Code body = p.body;
@ -700,7 +700,6 @@ CodeEnum def_enum( StrC name, Opts_def_enum p )
EnumT specifier = p.specifier;
CodeAttributes attributes = p.attributes;
ModuleFlag mflags = p.mflags;
Code type_macro = p.type_macro;
name_check( def_enum, name );
@ -752,10 +751,6 @@ CodeEnum def_enum( StrC name, Opts_def_enum p )
{
result->UnderlyingType = type;
}
else if ( type_macro )
{
result->UnderlyingTypeMacro = type_macro;
}
else if ( result->Type != CT_Enum_Class_Fwd && result->Type != CT_Enum_Fwd )
{
log_failure( "gen::def_enum: enum forward declaration must have an underlying type" );
@ -834,7 +829,7 @@ CodeFriend def_friend( Code declaration )
CodeFn def_function( StrC name, Opts_def_function p )
{
CodeParams params = p.params;
CodeParam params = p.params;
CodeTypename ret_type = p.ret_type;
CodeBody body = p.body;
CodeSpecifiers specifiers = p.specs;
@ -974,7 +969,7 @@ CodeNS def_namespace( StrC name, CodeBody body, Opts_def_namespace p )
CodeOperator def_operator( Operator op, StrC nspace, Opts_def_operator p )
{
CodeParams params_code = p.params;
CodeParam params_code = p.params;
CodeTypename ret_type = p.ret_type;
CodeBody body = p.body;
CodeSpecifiers specifiers = p.specifiers;
@ -1098,7 +1093,7 @@ CodeOpCast def_operator_cast( CodeTypename type, Opts_def_operator_cast p )
return result;
}
CodeParams def_param( CodeTypename type, StrC name, Opts_def_param p )
CodeParam def_param( CodeTypename type, StrC name, Opts_def_param p )
{
name_check( def_param, name );
null_check( def_param, type );
@ -1115,8 +1110,8 @@ CodeParams def_param( CodeTypename type, StrC name, Opts_def_param p )
return InvalidCode;
}
CodeParams
result = (CodeParams) make_code();
CodeParam
result = (CodeParam) make_code();
result->Type = CT_Parameters;
result->Name = get_cached_string( name );
@ -1252,7 +1247,7 @@ CodeStruct def_struct( StrC name, Opts_def_struct p )
return result;
}
CodeTemplate def_template( CodeParams params, Code declaration, Opts_def_template p )
CodeTemplate def_template( CodeParam params, Code declaration, Opts_def_template p )
{
null_check( def_template, declaration );
@ -2069,7 +2064,7 @@ CodeBody def_namespace_body( s32 num, Code* codes )
return result;
}
CodeParams def_params( s32 num, ... )
CodeParam def_params( s32 num, ... )
{
def_body_start( def_params );
@ -2077,7 +2072,7 @@ CodeParams def_params( s32 num, ... )
va_start(va, num);
Code_POD pod = va_arg(va, Code_POD);
CodeParams param = pcast( CodeParams, pod );
CodeParam param = pcast( CodeParam, pod );
null_check( def_params, param );
@ -2087,12 +2082,12 @@ CodeParams def_params( s32 num, ... )
return InvalidCode;
}
CodeParams result = (CodeParams) code_duplicate(param);
CodeParam result = (CodeParam) code_duplicate(param);
while ( -- num )
{
pod = va_arg(va, Code_POD);
param = pcast( CodeParams, pod );
param = pcast( CodeParam, pod );
if ( param->Type != CT_Parameters )
{
@ -2107,7 +2102,7 @@ CodeParams def_params( s32 num, ... )
return result;
}
CodeParams def_params( s32 num, CodeParams* codes )
CodeParam def_params( s32 num, CodeParam* codes )
{
def_body_code_array_start( def_params );
@ -2124,11 +2119,11 @@ CodeParams def_params( s32 num, CodeParams* codes )
return InvalidCode; \
}
CodeParams current = (CodeParams)code_duplicate(* codes);
CodeParam current = (CodeParam)code_duplicate(* codes);
check_current(current);
CodeParams
result = (CodeParams) make_code();
CodeParam
result = (CodeParam) make_code();
result->Name = current->Name;
result->Type = current->Type;
result->ValueType = current->ValueType;

View File

@ -663,10 +663,6 @@ TokArray lex( StrC content )
switch ( current )
{
if (array_back(Lexer_Tokens)->Length > 100 ) {
__debugbreak();
}
case '#':
{
s32 result = lex_preprocessor_directive( ctx );

View File

@ -225,7 +225,7 @@ internal CodeInclude parse_include ();
internal CodeOperator parse_operator_after_ret_type ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type );
internal Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers );
internal CodePragma parse_pragma ();
internal CodeParams parse_params ( bool use_template_capture );
internal CodeParam parse_params ( bool use_template_capture );
internal CodePreprocessCond parse_preprocess_cond ();
internal Code parse_simple_preprocess ( TokType which, bool dont_consume_braces );
internal Code parse_static_assert ();
@ -797,10 +797,11 @@ Code parse_class_struct( TokType which, bool inplace_def )
}
if ( which == Tok_Decl_Class )
result = cast(Code, def_class( tok_to_str(name), def_assign( body, parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
result = cast(Code, def_class( tok_to_str(name), def_assign( body, parent, access, attributes, nullptr, 0, mflags ) ));
else
result = cast(Code, def_struct( tok_to_str(name), def_assign( body, (CodeTypename)parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
result = cast(Code, def_struct( tok_to_str(name), def_assign( body, (CodeTypename)parent, access, attributes, nullptr, 0, mflags ) ));
if ( inline_cmt )
result->InlineCmt = cast(Code, inline_cmt);
@ -1478,7 +1479,7 @@ CodeFn parse_function_after_name(
)
{
push_scope();
CodeParams params = parse_params(parser_use_parenthesis);
CodeParam params = parse_params(parser_use_parenthesis);
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Parameters> )
// TODO(Ed), Review old comment : These have to be kept separate from the return type's specifiers.
@ -2515,7 +2516,7 @@ CodeOperator parse_operator_after_ret_type(
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op>
// Parse Params
CodeParams params = parse_params(parser_use_parenthesis);
CodeParam params = parse_params(parser_use_parenthesis);
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op> ( <Parameters> )
if ( params == nullptr && op == Op_Multiply )
@ -2693,7 +2694,7 @@ CodePragma parse_pragma()
}
internal inline
CodeParams parse_params( bool use_template_capture )
CodeParam parse_params( bool use_template_capture )
{
push_scope();
@ -2822,7 +2823,7 @@ CodeParams parse_params( bool use_template_capture )
}
}
CodeParams result = ( CodeParams )make_code();
CodeParam result = ( CodeParam )make_code();
result->Type = CT_Parameters;
result->Macro = macro;
@ -2939,7 +2940,7 @@ CodeParams parse_params( bool use_template_capture )
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, ..
}
CodeParams param = ( CodeParams )make_code();
CodeParam param = ( CodeParam )make_code();
param->Type = CT_Parameters;
param->Macro = macro;
@ -3371,7 +3372,7 @@ CodeVar parse_variable_after_name(
result->NextVar->Parent = cast(Code, result);
}
result->VarParenthesizedInit = using_constructor_initializer;
result->VarConstructorInit = using_constructor_initializer;
parser_pop(& Context);
return result;
@ -3475,7 +3476,7 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
push_scope();
Token identifier = parse_identifier(nullptr);
CodeParams params = parse_params(parser_not_from_template);
CodeParam params = parse_params(parser_not_from_template);
// <Name> ( <Parameters> )
Code initializer_list = NullCode;
@ -3730,7 +3731,8 @@ CodeEnum parser_parse_enum( bool inplace_def )
else if ( currtok.Type == Tok_Preprocess_Macro )
{
// We'll support the enum_underlying macro
if ( strc_contains( tok_to_str(currtok), enum_underlying_sig) )
StrC sig = txt("enum_underlying(");
if ( strc_contains( tok_to_str(currtok), sig) )
{
use_macro_underlying = true;
underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro, parser_dont_consume_braces );
@ -4038,7 +4040,7 @@ CodeFriend parser_parse_friend()
function = parse_function_after_name( ModuleFlag_None, NullCode, specifiers, type, name );
// Parameter list
// CodeParams params = parse_params();
// CodeParam params = parse_params();
// friend <ReturnType> <Name> ( <Parameters> )
// function = make_code();
@ -4408,7 +4410,7 @@ CodeTemplate parser_parse_template()
eat( Tok_Decl_Template );
// <export> template
CodeParams params = parse_params( UseTemplateCapture );
CodeParam params = parse_params( UseTemplateCapture );
if ( cast(Code, params) == Code_Invalid )
{
parser_pop(& Context);
@ -4773,10 +4775,10 @@ else if ( currtok.Type == Tok_DeclType )
// For function type signatures
CodeTypename return_type = NullCode;
CodeParams params = NullCode;
CodeParam params = NullCode;
#ifdef GEN_USE_NEW_TYPENAME_PARSING
CodeParams params_nested = NullCode;
CodeParam params_nested = NullCode;
#endif
bool is_function_typename = false;
@ -5581,12 +5583,6 @@ CodeVar parser_parse_variable()
}
internal
CodeTypename parser_parse_type_alt( bool from_template, bool* typedef_is_functon )
{
}
GEN_NS_PARSER_END
#ifdef CHECK_WAS_DEFINED

View File

@ -28,8 +28,6 @@ global AllocatorInfo Allocator_TypeTable = {0};
#pragma region Constants
global StrC enum_underlying_sig;
global Code access_public;
global Code access_protected;
global Code access_private;
@ -42,7 +40,7 @@ global Code module_private_fragment;
global Code fmt_newline;
global CodeParams param_varadic;
global CodeParam param_varadic;
global CodePragma pragma_once;

View File

@ -284,4 +284,121 @@
# define GEN_OPITMIZE_MAPPINGS_END
#endif
#if GEN_COMPILER_C
// ____ _ ______ _ _ ____ _ __ _
// / ___} (_) | ____} | | (_) / __ \ | | | |(_)
// | | ___ ___ _ __ ___ _ __ _ ___ | |__ _ _ _ __ ___| |_ _ ___ _ __ | | | |_ _____ _ __ | | ___ __ _ __| | _ _ __ __ _
// | |{__ |/ _ \ '_ \ / _ \ '__} |/ __| | __} | | | '_ \ / __} __} |/ _ \| '_ \ | | | \ \ / / _ \ '_ \| |/ _ \ / _` |/ _` || | '_ \ / _` |
// | |__j | __/ | | | __/ | | | (__ | | | |_| | | | | (__| l_| | (_) | | | | | l__| |\ V / __/ | | | | (_) | (_| | (_| || | | | | (_| |
// \____/ \___}_l l_l\___}_l l_l\___| l_l \__,_l_l l_l\___}\__}_l\___/l_l l_l \____/ \_/ \___}_l l_l_l\___/ \__,_l\__,_l|_|_| |_|\__, |
// This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in: __| |
// https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md {___/
// Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible.
#define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly.
// Helper macros for argument selection
#define GEN_SELECT_ARG_1( _1, ... ) _1 // <-- Of all th args passed pick _1.
#define GEN_SELECT_ARG_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2.
#define GEN_SELECT_ARG_3( _1, _2, _3, ... ) _3 // etc..
#define GEN_GENERIC_SEL_ENTRY_TYPE GEN_SELECT_ARG_1 // Use the arg expansion macro to select arg 1 which should have the type.
#define GEN_GENERIC_SEL_ENTRY_FUNCTION GEN_SELECT_ARG_2 // Use the arg expansion macro to select arg 2 which should have the function.
#define GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER GEN_SELECT_ARG_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','.
#define GEN_RESOLVED_FUNCTION_CALL // Just used to indicate where the call "occurs"
// ----------------------------------------------------------------------------------------------------------------------------------
// GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( macro ) includes a _Generic slot only if the specified macro is defined (as type, function_name).
// It takes advantage of the fact that if the macro is defined, then the expanded text will contain a comma.
// Expands to ',' if it can find (type): (function) <comma_operator: ',' >
// Where GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER is specifically looking for that <comma> ,
#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , )
// ^ Selects the comma ^ is the type ^ is the function ^ Insert a comma
// The slot won't exist if that comma is not found. |
// For the occastion where an expression didn't resolve to a selection option the "default: <value>" will be set to:
typedef struct GENCPP_NO_RESOLVED_GENERIC_SELECTION GENCPP_NO_RESOLVED_GENERIC_SELECTION;
struct GENCPP_NO_RESOLVED_GENERIC_SELECTION {
void* _THE_VOID_SLOT_;
};
GENCPP_NO_RESOLVED_GENERIC_SELECTION const gen_generic_selection_fail = {0};
// Which will provide the message: error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer
// ----------------------------------------------------------------------------------------------------------------------------------
// Below are generated on demand for an overlaod depdendent on a type:
// ----------------------------------------------------------------------------------------------------------------------------------
#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( \
(selector_arg), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg )
// ----------------------------------------------------------------------------------------------------------------------------------
// Then each definiton of a function has an associated define:
#// #define GENERIC_SLOT_<#>_<generic identifier> <typename>, <function_to_resolve>
// Then somehwere later on
// <etc> <return_type> <function_id> ( <arguments> ) { <implementation> }
// Concrete example:
// To add support for long:
#define GENERIC_SLOT_1_gen_example_hash long, gen_example_hash__P_long
size_t gen_example_hash__P_long( long val ) { return val * 2654435761ull; }
// To add support for long long:
#define GENERIC_SLOT_2_gen_example_hash long long, gen_example_hash__P_long_long
size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761ull; }
// 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 gen_hash_example( function_arguments ) _Generic( \
(function_arguments), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_8 ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( function_arguments )
// Additional Variations:
// If the function takes more than one argument the following is used:
#define GEN_FUNCTION_GENERIC_EXAMPLE_VARADIC( selector_arg, ... ) _Generic( \
(selector_arg), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
/* ... */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ )
// If the function does not take the arugment as a parameter:
#define GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( selector_arg ) _Generic( \
( GEN_TYPE_TO_EXP(selector_arg) ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
/* ... */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL()
// Used to keep the _Generic keyword happy as bare types are not considered "expressions"
#define GEN_TYPE_TO_EXP(type) (* (type*)NULL)
// Instead of using this macro, you'll see it directly expanded by the code generation.
// typedef void* GEN_GenericExampleType;
// GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType );
// END OF ------------------------ _Generic function overloading ----------------------------------------- END OF
#endif
#pragma endregion Macros

View File

@ -17,7 +17,7 @@
GEN_NS_BEGIN
#include "components/types.hpp"
#include "components/gen/ecodetypes.hpp"
#include "components/gen/ecode.hpp"
#include "components/gen/eoperator.hpp"
#include "components/gen/especifier.hpp"

View File

@ -536,7 +536,7 @@ CodeBody gen_ast_inlines()
CodeBody impl_code_ns = parse_global_body( token_fmt( "typename", StrC name(CodeNS), code_impl_tmpl ));
CodeBody impl_code_op = parse_global_body( token_fmt( "typename", StrC name(CodeOperator), code_impl_tmpl ));
CodeBody impl_code_opcast = parse_global_body( token_fmt( "typename", StrC name(CodeOpCast), code_impl_tmpl ));
CodeBody impl_code_params = parse_global_body( token_fmt( "typename", StrC name(CodeParams), code_impl_tmpl ));
CodeBody impl_code_param = parse_global_body( token_fmt( "typename", StrC name(CodeParam), code_impl_tmpl ));
CodeBody impl_code_pragma = parse_global_body( token_fmt( "typename", StrC name(CodePragma), code_impl_tmpl ));
CodeBody impl_code_precond = parse_global_body( token_fmt( "typename", StrC name(CodePreprocessCond), code_impl_tmpl ));
CodeBody impl_code_specs = parse_global_body( token_fmt( "typename", StrC name(CodeSpecifiers), code_impl_tmpl ));
@ -599,7 +599,7 @@ CodeBody gen_ast_inlines()
CodeBody impl_cast_ns = parse_global_body( token_fmt( "typename", StrC name(NS), cast_tmpl ));
CodeBody impl_cast_op = parse_global_body( token_fmt( "typename", StrC name(Operator), cast_tmpl ));
CodeBody impl_cast_opcast = parse_global_body( token_fmt( "typename", StrC name(OpCast), cast_tmpl ));
CodeBody impl_cast_params = parse_global_body( token_fmt( "typename", StrC name(Params), cast_tmpl ));
CodeBody impl_cast_param = parse_global_body( token_fmt( "typename", StrC name(Param), cast_tmpl ));
CodeBody impl_cast_pragma = parse_global_body( token_fmt( "typename", StrC name(Pragma), cast_tmpl ));
CodeBody impl_cast_precond = parse_global_body( token_fmt( "typename", StrC name(PreprocessCond), cast_tmpl ));
CodeBody impl_cast_specs = parse_global_body( token_fmt( "typename", StrC name(Specifiers), cast_tmpl ));
@ -632,7 +632,7 @@ CodeBody gen_ast_inlines()
impl_code_ns,
impl_code_op,
impl_code_opcast,
impl_code_params,
impl_code_param,
impl_code_pragma,
impl_code_precond,
impl_code_specs,
@ -666,7 +666,7 @@ CodeBody gen_ast_inlines()
impl_cast_ns,
impl_cast_op,
impl_cast_opcast,
impl_cast_params,
impl_cast_param,
impl_cast_pragma,
impl_cast_precond,
impl_cast_specs,

View File

@ -39,8 +39,6 @@ The full definitions of all asts are within:
* [`ast_types.hpp`](../base/components/ast_types.hpp)
* [`code_types.hpp`](../base/components/ast_types.hpp)
The C/C++ interface procedures are located with `ast.hpp` (for the Code type), and `code_types.hpp` for all others.
## Serialization
All code types can either serialize using a function of the pattern:
@ -54,5 +52,7 @@ String <prefix>_to_string(Code code);
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 serializing.
gencpp's serialization does not provide coherent formatting of the code. The user should use a formatter after.

View File

@ -25,11 +25,11 @@ These are containers representing a scope body of a definition that can be of th
Fields:
```cpp
StringCached Name;
Code Front;
Code Back;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
s32 NumEntries;
```
@ -37,15 +37,14 @@ s32 NumEntries;
The `Front` member represents the start of the link list and `Back` the end.
NumEntries is the number of entries in the body.
Parent should have a compatible CodeType type for the type of defintion used.
Parent should have a compatible ECode type for the type of defintion used.
Serialization:
Will output only the entries, the braces are handled by the parent.
```cpp
<Front>
...
<Front>...
<Back>
```
@ -57,11 +56,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -81,11 +80,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -109,11 +108,11 @@ CodeComment InlineCmt; // Only supported by forward declarations
CodeAttributes Attributes;
CodeType ParentType;
CodeBody Body;
StringCached Name;
CodeType Prev;
CodeType Next;
Token* Tok;
CodeType Prev; // Used to store references to interfaces
CodeType Next; // Used to store references to interfaces
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
@ -132,7 +131,7 @@ Serialization:
};
```
You'll notice that only one parent type is supported only with parent access. This library only supports single inheritance, the rest are assumed to be interfaces and are given public acess specifiers.
You'll notice that only one parent type is supported only with parent access. This library only supports single inheritance, the rest must be done through interfaces.
## Constructor
@ -141,13 +140,13 @@ Fields:
```cpp
CodeComment InlineCmt; // Only supported by forward declarations
Code InitializerList;
CodeParams Params;
CodeParam Params;
Code Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -179,11 +178,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -201,11 +200,11 @@ Fields:
CodeComment InlineCmt;
CodeSpecifiers Specs;
Code Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -236,28 +235,24 @@ Fields:
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeType UnderlyingType;
Code UnderlyingTypeMacro;
CodeBody Body;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
UnderlyingTypeMacro is a macro the library natively supports: `enum_underlying(type)` that is meant to behave as a wrapper for underlying type assignment.
The `enum_underlying_sig` is a `StrC` global var that can be set which will be defined within `PreprocessorDefines` and used in `parser_parse_enum` to identify a valid macro.
Serialization:
```cpp
// Enum_Fwd
<ModuleFlags> enum class <Name> : <UnderlyingType> or <UnderlyingTypeMacro> ; <InlineCmt>
<ModuleFlags> enum class <Name> : <UnderlyingType>; <InlineCmt>
// Enum
<ModuleFlags> <enum or enum class> <Name> : <UnderlyingType> or <UnderlyingTypeMacro>
<ModuleFlags> <enum or enum class> <Name> : <UnderlyingType>
{
<Body>
};
@ -272,11 +267,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -292,11 +287,11 @@ Fields:
```cpp
CodeBody Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -315,11 +310,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Code Parent;
Token* Tok;
parser::Token* Tok;
StringCached Name;
CodeT Type;
```
@ -338,11 +333,11 @@ Fields:
```cpp
CodeComment InlineCmt;
Code Declaration;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -361,13 +356,13 @@ CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParams Params;
CodeParam Params;
CodeBody Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
@ -390,11 +385,11 @@ Serialization:
Fields:
```cpp
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
@ -411,11 +406,11 @@ Fields:
```cpp
CodeBody Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
@ -429,7 +424,7 @@ Serialization:
}
```
## Operator Overload (Operator)
## Operator Overload
Fields:
@ -438,13 +433,13 @@ CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParams Params;
CodeParam Params;
CodeBody Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
OperatorT Op;
@ -463,7 +458,7 @@ Serialization:
}
```
## Operator Cast Overload ( User-Defined Type Conversion, OpCast )
## Operator Cast Overload ( User-Defined Type Conversion )
Fields:
@ -472,11 +467,11 @@ CodeComment InlineCmt;
CodeSpecifiers Specs;
CodeType ValueType;
CodeBody Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -493,7 +488,7 @@ Serialization:
}
```
## Parameters (AST_Params)
## Parameters (AST_Param)
Fields:
@ -501,12 +496,11 @@ Fields:
CodeType ValueType;
Code Macro;
Code Value;
Code PostNameMacro;
StringCached Name;
CodeParams Last;
CodeParams Next;
Token* Tok;
CodeParam Last;
CodeParam Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
s32 NumEntries;
```
@ -516,7 +510,7 @@ Serialization:
```cpp
<Macro>, <Next> ... <Last>
<Macro> <ValueType> <Name> <PostNameMacro> = <Value>, <Next>... <Last>
<Macro> <ValueType> <Name>, <Next>... <Last>
```
## Pragma
@ -525,11 +519,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -545,11 +539,11 @@ Fields:
```cpp
StringCached Content;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
paser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
@ -566,11 +560,11 @@ Fields:
```cpp
SpecifierT ArrSpecs[ AST_ArrSpecs_Cap ];
CodeSpecifiers NextSpecs;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
s32 NumEntries;
```
@ -586,13 +580,13 @@ Serialization:
Fields:
```cpp
CodeParams Params;
CodeParam Params;
Code Declaration;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
@ -615,30 +609,23 @@ Fields:
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeReturnType ReturnType;
CodeParams Params;
CodeParam Params;
Code ArrExpr;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
b32 IsParamPack;
ETypenameTag TypeTag;
```
Serialization:
```cpp
<Attributes> <TypeTag> <Name> <Specs> <IsParamPack ?: ...>
// Function
<Attributes> <ReturnType> <Name> <Params> <Specs>
<Attributes> <Name> <Specs> <IsParamPack ?: ...>
```
`<Name>` currently has the full serialization of anything with
*Note: ArrExpr is not used in serialization by `typename_to_string_ref` its instead handled by a parent AST's serailization (variable, typedef, using).*
## Typedef
Behave as usual except function or macro typedefs.
@ -649,11 +636,11 @@ Fields:
```cpp
CodeComment InlineCmt;
Code UnderlyingType;
StringCached Name;
Code Prev;
Code Next;
Token* Tok
parse::Token* Tok
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
b32 IsFunction;
@ -663,16 +650,11 @@ Serialization:
```cpp
// Regular
<ModuleFlags> typedef <UnderlyingType> <Name> <UnderlyingType-ArrExpr>; <InlineCmt>
<ModuleFlags> typedef <UnderlyingType> <Name>; <InlineCmt>
// Functions
// Currently:
<ModuleFlags> typedef <UnderlyingType (Serialized expression)>; <InlineCmt>
// Desired: Not handled yet
<ModuleFlags> typedef <UnderlyingType->ReturnType> UnderlyingType->Name> <UnderlyingType-ArrExpr> ( <UnderlyingType->Parameters> ); <InlineCmt>
<ModuleFlags> typedef <UnderlyingType->ReturnType> ( <Name->Namespace> for<Specs->has(Spec_Ptr) ?: *> <UnderlyingType->Name> <UnderlyingType-ArrExpr> ) ( <UnderlyingType->Parameters> ); <InlineCmt>
<ModuleFlags> typedef <ReturnType> <Name>( <Parameters> ); <InlineCmt>
<ModuleFlags> typedef <ReturnType> ( <Expression that yeilds an Identifier signature> )( <Parameters> ); <InlineCmt>
```
## Union
@ -682,11 +664,11 @@ Fields:
```cpp
CodeAttributes Attributes;
CodeBody Body;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
@ -708,11 +690,11 @@ Fields:
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeType UnderlyingType;
StringCached Name;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
@ -740,15 +722,14 @@ CodeSpecifiers Specs;
CodeType ValueType;
Code BitfieldSize;
Code Value;
StringCached Name;
CodeVar NextVar;
Code Prev;
Code Next;
Token* Tok;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
s32 VarParenthesizedInit;
```
Serialization:
@ -759,7 +740,4 @@ Serialization:
// Bitfield
<ModuleFlags> <Attributes> <Specs> <ValueType> <Name> : <BitfieldSize> = <Value>, NextVar ...; <InlineCmt>
// VarParenthesizedInit
<Attributes> <Specs> <ValueType> <Name>( <Value>, NextVar ... ); <InlineCmt>
```

View File

@ -8,7 +8,7 @@
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 ~7000 loc. I hope to keep it under 10k loc worst case.
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 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.

View File

@ -128,7 +128,7 @@ The following CodeTypes are used which the user may optionally use strong typing
* CodeNS
* CodeOperator
* CodeOpCast
* CodeParams : 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.
@ -412,8 +412,4 @@ There are two provided auxillary interfaces:
### Scanner Auxillary Interface
* The purpose is to scan or parse files
* Some with two basic functions to convert a fil to code: `scan_file` and `parse_file`
* `scan_file`: Merely grabs the file and stores it in an untyped Code.
* `parse_file`: Will parse the file using `parse_global_body` and return a `CodeBody`.
* Two basic functions for grabbing columns from a CSV: `parse_csv_one_column` and `parse_csv_two_columns`

View File

@ -85,14 +85,13 @@ int gen_main()
// Header Content: Reflection and Generation
#pragma region Resolve Dependencies
Code header_platform = scan_file( path_base "dependencies/platform.hpp" );
Code header_macros = scan_file( path_base "dependencies/macros.hpp" );
Code header_generic_macros = scan_file( "components/generic_macros.hpp" );
Code header_basic_types = scan_file( path_base "dependencies/basic_types.hpp" );
Code header_debug = scan_file( path_base "dependencies/debug.hpp" );
Code header_string_ops = scan_file( path_base "dependencies/string_ops.hpp" );
Code header_hashing = scan_file( path_base "dependencies/hashing.hpp" );
Code header_timing = scan_file( path_base "dependencies/timing.hpp" );
Code header_platform = scan_file( path_base "dependencies/platform.hpp" );
Code header_macros = scan_file( path_base "dependencies/macros.hpp" );
Code header_basic_types = scan_file( path_base "dependencies/basic_types.hpp" );
Code header_debug = scan_file( path_base "dependencies/debug.hpp" );
Code header_string_ops = scan_file( path_base "dependencies/string_ops.hpp" );
Code header_hashing = scan_file( path_base "dependencies/hashing.hpp" );
Code header_timing = scan_file( path_base "dependencies/timing.hpp" );
CodeBody parsed_header_memory = parse_file( path_base "dependencies/memory.hpp" );
CodeBody header_memory = def_body(CT_Global_Body);
@ -749,7 +748,7 @@ R"(#define AST_ArrSpecs_Cap \
txt("CodeOperator"),
txt("CodeOpCast"),
txt("CodePragma"),
txt("CodeParams"),
txt("CodeParam"),
txt("CodePreprocessCond"),
txt("CodeSpecifiers"),
txt("CodeTemplate"),
@ -801,7 +800,7 @@ R"(#define AST_ArrSpecs_Cap \
// Resolve generic's arguments
b32 has_args = fn->Params->NumEntries > 1;
String params_str = String::make_reserve(GlobalAllocator, 32);
for (CodeParams param = fn->Params->Next; param != fn->Params.end(); ++ param) {
for (CodeParam param = fn->Params->Next; param != fn->Params.end(); ++ param) {
// We skip the first parameter as its always going to be the code for selection
if (param->Next == nullptr) {
params_str.append_fmt( "%SC", param->Name );
@ -936,7 +935,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
}
b32 handled= false;
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
for ( CodeParam opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
{
// Convert the definition to use a default struct: https://vxtwitter.com/vkrajacic/status/1749816169736073295
StrC prefix = txt("def_");
@ -946,7 +945,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
// Resolve define's arguments
b32 has_args = fn->Params->NumEntries > 1;
String params_str = String::make_reserve(GlobalAllocator, 32);
for (CodeParams other_param = fn->Params; other_param != opt_param; ++ other_param) {
for (CodeParam other_param = fn->Params; other_param != opt_param; ++ other_param) {
if ( other_param == opt_param ) {
params_str.append_fmt( "%SC", other_param->Name );
break;
@ -1211,7 +1210,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
CodeFn fn = cast(CodeFn, entry);
Code prev = entry->Prev;
for ( CodeParams arr_param : fn->Params )
for ( CodeParam arr_param : fn->Params )
if ( fn->Name.starts_with(txt("def_"))
&& ( (arr_param->ValueType->Name.starts_with(txt("Specifier")) && fn->Params->NumEntries > 1)
|| arr_param->ValueType->Name.starts_with(txt("Code")) )
@ -1223,7 +1222,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
postfix_arr.free();
}
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
for ( CodeParam opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
{
StrC prefix = txt("def_");
StrC actual_name = { fn->Name.Len - prefix.Len, fn->Name.Ptr + prefix.Len };
@ -1482,7 +1481,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print_fmt( "\nGEN_NS_BEGIN\n" );
header.print( r_header_macros );
header.print( header_generic_macros );
header.print( r_header_basic_types );
header.print( r_header_debug );
header.print( rf_header_memory );
@ -1619,7 +1617,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
header.print_fmt( "\nGEN_NS_BEGIN\n" );
header.print( r_header_macros );
header.print( header_generic_macros );
header.print( r_header_basic_types );
header.print( r_header_debug );
header.print( rf_header_memory );

View File

@ -337,7 +337,7 @@ word CodeNS, gen_CodeNS
word CodeOperator, gen_CodeOperator
word CodeOpCast, gen_CodeOpCast
word CodePragma, gen_CodePragma
word CodeParams, gen_CodeParams
word CodeParam, gen_CodeParam
word CodePreprocessCo, gen_CodePreprocessCo
word CodeSpecifiers, gen_CodeSpecifiers
word CodeTemplate, gen_CodeTemplate

View File

@ -1,115 +0,0 @@
#pragma region _Generic Macros
// ____ _ ______ _ _ ____ _ __ _
// / ___} (_) | ____} | | (_) / __ \ | | | |(_)
// | | ___ ___ _ __ ___ _ __ _ ___ | |__ _ _ _ __ ___| |_ _ ___ _ __ | | | |_ _____ _ __ | | ___ __ _ __| | _ _ __ __ _
// | |{__ |/ _ \ '_ \ / _ \ '__} |/ __| | __} | | | '_ \ / __} __} |/ _ \| '_ \ | | | \ \ / / _ \ '_ \| |/ _ \ / _` |/ _` || | '_ \ / _` |
// | |__j | __/ | | | __/ | | | (__ | | | |_| | | | | (__| l_| | (_) | | | | | l__| |\ V / __/ | | | | (_) | (_| | (_| || | | | | (_| |
// \____/ \___}_l l_l\___}_l l_l\___| l_l \__,_l_l l_l\___}\__}_l\___/l_l l_l \____/ \_/ \___}_l l_l_l\___/ \__,_l\__,_l|_|_| |_|\__, |
// This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in: __| |
// https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md {___/
// Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible.
#define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly.
// Helper macros for argument selection
#define GEN_SELECT_ARG_1( _1, ... ) _1 // <-- Of all th args passed pick _1.
#define GEN_SELECT_ARG_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2.
#define GEN_SELECT_ARG_3( _1, _2, _3, ... ) _3 // etc..
#define GEN_GENERIC_SEL_ENTRY_TYPE GEN_SELECT_ARG_1 // Use the arg expansion macro to select arg 1 which should have the type.
#define GEN_GENERIC_SEL_ENTRY_FUNCTION GEN_SELECT_ARG_2 // Use the arg expansion macro to select arg 2 which should have the function.
#define GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER GEN_SELECT_ARG_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','.
#define GEN_RESOLVED_FUNCTION_CALL // Just used to indicate where the call "occurs"
// ----------------------------------------------------------------------------------------------------------------------------------
// GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( macro ) includes a _Generic slot only if the specified macro is defined (as type, function_name).
// It takes advantage of the fact that if the macro is defined, then the expanded text will contain a comma.
// Expands to ',' if it can find (type): (function) <comma_operator: ',' >
// Where GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER is specifically looking for that <comma> ,
#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , )
// ^ Selects the comma ^ is the type ^ is the function ^ Insert a comma
// The slot won't exist if that comma is not found. |
// For the occastion where an expression didn't resolve to a selection option the "default: <value>" will be set to:
typedef struct GENCPP_NO_RESOLVED_GENERIC_SELECTION GENCPP_NO_RESOLVED_GENERIC_SELECTION;
struct GENCPP_NO_RESOLVED_GENERIC_SELECTION {
void* _THE_VOID_SLOT_;
};
GENCPP_NO_RESOLVED_GENERIC_SELECTION const gen_generic_selection_fail = {0};
// Which will provide the message: error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer
// ----------------------------------------------------------------------------------------------------------------------------------
// Below are generated on demand for an overlaod depdendent on a type:
// ----------------------------------------------------------------------------------------------------------------------------------
#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( \
(selector_arg), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg )
// ----------------------------------------------------------------------------------------------------------------------------------
// Then each definiton of a function has an associated define:
#// #define GENERIC_SLOT_<#>_<generic identifier> <typename>, <function_to_resolve>
// Then somehwere later on
// <etc> <return_type> <function_id> ( <arguments> ) { <implementation> }
// Concrete example:
// To add support for long:
#define GENERIC_SLOT_1_gen_example_hash long, gen_example_hash__P_long
size_t gen_example_hash__P_long( long val ) { return val * 2654435761ull; }
// To add support for long long:
#define GENERIC_SLOT_2_gen_example_hash long long, gen_example_hash__P_long_long
size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761ull; }
// 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 gen_hash_example( function_arguments ) _Generic( \
(function_arguments), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_8 ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( function_arguments )
// Additional Variations:
// If the function takes more than one argument the following is used:
#define GEN_FUNCTION_GENERIC_EXAMPLE_VARADIC( selector_arg, ... ) _Generic( \
(selector_arg), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
/* ... */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ )
// If the function does not take the arugment as a parameter:
#define GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( selector_arg ) _Generic( \
( GEN_TYPE_TO_EXP(selector_arg) ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
/* ... */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL()
// Used to keep the _Generic keyword happy as bare types are not considered "expressions"
#define GEN_TYPE_TO_EXP(type) (* (type*)NULL)
// Instead of using this macro, you'll see it directly expanded by the code generation.
// typedef void* GEN_GenericExampleType;
// GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType );
#pragma endregion _Generic Macros

View File

@ -174,7 +174,7 @@ CodeFn rename_function_to_unique_symbol(CodeFn fn, StrC optional_prefix = txt(""
// Add parameter types to create a unique signature
bool first_param = true;
for (CodeParams param = fn->Params; param.ast; param = param->Next)
for (CodeParam param = fn->Params; param.ast; param = param->Next)
{
if (param->ValueType)
{

View File

@ -173,7 +173,7 @@ int gen_main()
// gen.hpp
{
Code header_start = scan_file( "components/header_start.hpp" );
Code header_start = scan_file( "components/header_start.hpp" );
Code types = scan_file( path_base "components/types.hpp" );
Code ast = scan_file( path_base "components/ast.hpp" );
Code ast_types = scan_file( path_base "components/ast_types.hpp" );

View File

@ -266,7 +266,7 @@
</Expand>
</Type>
<Type Name="gen::AST_Params">
<Type Name="gen::AST_Param">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ValueType">ValueType</Item>
@ -553,7 +553,7 @@
</Expand>
</Type>
<Type Name="gen::CodeParams">
<Type Name="gen::CodeParam">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>

View File

@ -30,32 +30,15 @@ struct AnotherTemplate {
T value;
};
typedef decltype(nullptr) ( MyClass:: * InsaneComplexTypeDef )
typedef decltype(nullptr) (MyClass::*InsaneComplexTypeDef)
(
decltype( (MyEnum::VAL1 == MyEnum::VAL2) ? 1 : 2.0 )
( TemplateStruct< decltype(OuterStruct().unionInstance.inner), 5> :: * ptr ) [5] [ alignof(double) ],
std::function<
void *
(
TemplateStruct<int, 10> &&,
void ( MyClass:: * memFnPtr )(
TemplateStruct<
decltype(OuterStruct().unionInstance.inner)
>
)
)
>,
int ( MyClass :: * & refToMemFnPtr )( TemplateStruct<int, 10> ) ,
int ( TemplateStruct<int, 10>:: * memberPointer) [10],
typename std::tuple_element<
0,
std::tuple<
AnotherTemplate<
TemplateStruct< decltype(OuterStruct().unionInstance), 3 >
>
>
> :: type :: * complexMember,
template<typename U> typename AnotherTemplate<U> :: * templateMember
decltype((MyEnum::VAL1 == MyEnum::VAL2) ? 1 : 2.0)(TemplateStruct<decltype(OuterStruct().unionInstance.inner), 5>::*ptr)[5][alignof(double)],
std::function<void *(TemplateStruct<int, 10>&&, void (MyClass::*memFnPtr)(TemplateStruct<decltype(OuterStruct().unionInstance.inner)>))>,
int (MyClass::*&refToMemFnPtr)(TemplateStruct<int, 10>),
int (TemplateStruct<int, 10>::*memberPointer)[10],
typename std::tuple_element<0, std::tuple<AnotherTemplate<TemplateStruct<decltype(OuterStruct().unionInstance), 3>>>>::type::*complexMember,
template<typename U> typename AnotherTemplate<U>::*templateMember
char&&...,
)
volatile const && noexcept;