mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 07:44:45 -08:00
Compare commits
3 Commits
401f85f673
...
cb898595b0
Author | SHA1 | Date | |
---|---|---|---|
cb898595b0 | |||
9b86d84dd6 | |||
4dfb9031d7 |
10
Readme.md
10
Readme.md
@ -10,18 +10,16 @@ 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/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.
|
||||
* [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.
|
||||
|
||||
## Notes
|
||||
|
||||
|
@ -31,8 +31,6 @@ 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:
|
||||
@ -71,7 +69,11 @@ 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 (WIP).
|
||||
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.
|
||||
|
||||
|
||||
|
||||
## C++ template usage
|
||||
|
||||
@ -117,7 +119,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/).
|
||||
|
||||
* [`ecode.hpp`](./components/gen/ecode.hpp): `CodeType` enum definition and related implementaiton. Generation is based off of [`ECodeType.csv](./enums/ECodeTypes.csv).
|
||||
* [`ecodetypes.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:
|
||||
@ -135,7 +137,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 interface of the library is as follows:
|
||||
The convention you'll see used throughout the upfront 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`.
|
||||
@ -146,7 +148,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` and `docs/Parser_Algo.md`. Extending it is more serious, but resolution of a parse for a given internal parse procedure is well documented.
|
||||
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.
|
||||
|
||||
## A note on compilation and runtime generation speed
|
||||
|
||||
|
@ -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/ecode.hpp" );
|
||||
Builder header_ecode = builder_open( "components/gen/ecodetypes.hpp" );
|
||||
builder_print( & header_ecode, gen_component_header );
|
||||
builder_print( & header_ecode, format(ecode) );
|
||||
builder_write( & header_ecode);
|
||||
|
@ -497,7 +497,7 @@ void code_to_string_ptr( Code self, String* result )
|
||||
break;
|
||||
|
||||
case CT_Parameters:
|
||||
params_to_string_ref(cast(CodeParam, self), result );
|
||||
params_to_string_ref(cast(CodeParams, self), result );
|
||||
break;
|
||||
|
||||
case CT_Preprocess_Define:
|
||||
|
@ -37,7 +37,7 @@ struct AST_Module;
|
||||
struct AST_NS;
|
||||
struct AST_Operator;
|
||||
struct AST_OpCast;
|
||||
struct AST_Param;
|
||||
struct AST_Params;
|
||||
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_Param* CodeParam;
|
||||
typedef AST_Params* CodeParams;
|
||||
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 CodeParam;
|
||||
struct CodeParams;
|
||||
struct CodePreprocessCond;
|
||||
struct CodePragma;
|
||||
struct CodeSpecifiers;
|
||||
@ -209,6 +209,7 @@ struct CodeStmt_Switch;
|
||||
struct CodeStmt_While;
|
||||
#endif
|
||||
|
||||
// GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||
#endif
|
||||
|
||||
#if GEN_COMPILER_C
|
||||
@ -229,8 +230,6 @@ struct CodeUsing;
|
||||
struct CodeVar;
|
||||
#endif
|
||||
|
||||
#undef Define_Code
|
||||
|
||||
GEN_NS_PARSER_BEGIN
|
||||
|
||||
struct Token;
|
||||
@ -343,7 +342,7 @@ struct Code
|
||||
operator CodeNS() const;
|
||||
operator CodeOperator() const;
|
||||
operator CodeOpCast() const;
|
||||
operator CodeParam() const;
|
||||
operator CodeParams() const;
|
||||
operator CodePragma() const;
|
||||
operator CodePreprocessCond() const;
|
||||
operator CodeSpecifiers() const;
|
||||
@ -423,7 +422,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
|
||||
@ -456,7 +455,7 @@ struct AST
|
||||
Operator Op;
|
||||
AccessSpec ParentAccess;
|
||||
s32 NumEntries;
|
||||
s32 VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression.
|
||||
s32 VarParenthesizedInit; // 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" );
|
||||
|
@ -127,7 +127,7 @@ struct AST_Constructor
|
||||
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
|
||||
CodeSpecifiers Specs;
|
||||
Code InitializerList;
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
Code Body;
|
||||
char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ];
|
||||
};
|
||||
@ -550,7 +550,7 @@ struct AST_Fn
|
||||
CodeAttributes Attributes;
|
||||
CodeSpecifiers Specs;
|
||||
CodeTypename ReturnType;
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
CodeBody Body;
|
||||
char _PAD_PROPERTIES_ [ sizeof(AST*) ];
|
||||
};
|
||||
@ -613,7 +613,7 @@ struct AST_Operator
|
||||
CodeAttributes Attributes;
|
||||
CodeSpecifiers Specs;
|
||||
CodeTypename ReturnType;
|
||||
CodeParam Params;
|
||||
CodeParams 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_Param
|
||||
struct AST_Params
|
||||
{
|
||||
union {
|
||||
char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ];
|
||||
@ -669,15 +669,15 @@ struct AST_Param
|
||||
};
|
||||
};
|
||||
StringCached Name;
|
||||
CodeParam Last;
|
||||
CodeParam Next;
|
||||
CodeParams Last;
|
||||
CodeParams Next;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
CodeType Type;
|
||||
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
|
||||
s32 NumEntries;
|
||||
};
|
||||
static_assert( sizeof(AST_Param) == sizeof(AST), "ERROR: AST_Param is not the same size as AST");
|
||||
static_assert( sizeof(AST_Params) == sizeof(AST), "ERROR: AST_Params is not the same size as AST");
|
||||
|
||||
struct AST_Pragma
|
||||
{
|
||||
@ -971,7 +971,7 @@ struct AST_Template
|
||||
struct
|
||||
{
|
||||
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
|
||||
CodeParam Params;
|
||||
CodeParams 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
|
||||
// CodeParam Params; // Only used for function signatures
|
||||
// CodeParams Params; // Only used for function signatures
|
||||
Code ArrExpr;
|
||||
// CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
|
||||
};
|
||||
@ -1017,7 +1017,6 @@ 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 {
|
||||
@ -1028,7 +1027,7 @@ struct AST_Typename
|
||||
CodeAttributes Attributes;
|
||||
CodeSpecifiers Specs;
|
||||
CodeTypename ReturnType; // Only used for function signatures
|
||||
CodeParam Params; // Only used for function signatures
|
||||
CodeParams Params; // Only used for function signatures
|
||||
Code ArrExpr;
|
||||
CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
|
||||
};
|
||||
@ -1140,7 +1139,7 @@ struct AST_Var
|
||||
Code Parent;
|
||||
CodeType Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
s32 VarConstructorInit;
|
||||
s32 VarParenthesizedInit;
|
||||
};
|
||||
static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST");
|
||||
|
||||
|
@ -197,7 +197,7 @@ void class_to_string_def( CodeClass self, String* result )
|
||||
|
||||
while ( interface )
|
||||
{
|
||||
string_append_fmt( result, ", %S", typename_to_string(interface) );
|
||||
string_append_fmt( result, ", public %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(CodeParam self)
|
||||
String params_to_string(CodeParams self)
|
||||
{
|
||||
GEN_ASSERT(self);
|
||||
GEN_ASSERT(self);
|
||||
@ -872,7 +872,7 @@ String params_to_string(CodeParam self)
|
||||
return result;
|
||||
}
|
||||
|
||||
void params_to_string_ref( CodeParam self, String* result )
|
||||
void params_to_string_ref( CodeParams self, String* result )
|
||||
{
|
||||
GEN_ASSERT(self);
|
||||
GEN_ASSERT(result);
|
||||
@ -904,7 +904,7 @@ void params_to_string_ref( CodeParam self, String* result )
|
||||
|
||||
if ( self->NumEntries - 1 > 0 )
|
||||
{
|
||||
for ( CodeParam param = begin_CodeParam(self->Next); param != end_CodeParam(self->Next); param = next_CodeParam(self->Next, param) )
|
||||
for ( CodeParams param = begin_CodeParams(self->Next); param != end_CodeParams(self->Next); param = next_CodeParams(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->VarConstructorInit )
|
||||
if ( self->VarParenthesizedInit )
|
||||
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->VarConstructorInit )
|
||||
if ( self->VarParenthesizedInit )
|
||||
string_append_strc( result, txt(" )"));
|
||||
|
||||
return;
|
||||
@ -1431,7 +1431,7 @@ void var_to_string_ref(CodeVar self, String* result )
|
||||
|
||||
if ( self->Value )
|
||||
{
|
||||
if ( self->VarConstructorInit )
|
||||
if ( self->VarParenthesizedInit )
|
||||
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->VarConstructorInit )
|
||||
if ( self->VarParenthesizedInit )
|
||||
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->VarConstructorInit )
|
||||
if ( self->VarParenthesizedInit )
|
||||
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->VarConstructorInit )
|
||||
if ( self->VarParenthesizedInit )
|
||||
string_append_strc( result, txt(" )"));
|
||||
|
||||
string_append_strc( result, txt(";") );
|
||||
|
@ -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 (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 );
|
||||
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 );
|
||||
|
||||
CodeParam begin_CodeParam(CodeParam params);
|
||||
CodeParam end_CodeParam (CodeParam params);
|
||||
CodeParam next_CodeParam (CodeParam params, CodeParam entry_iter);
|
||||
CodeParams begin_CodeParams(CodeParams params);
|
||||
CodeParams end_CodeParams (CodeParams params);
|
||||
CodeParams next_CodeParams (CodeParams params, CodeParams 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 CodeParam
|
||||
struct CodeParams
|
||||
{
|
||||
#if ! GEN_C_LIKE_CPP
|
||||
Using_Code( CodeParam );
|
||||
forceinline void append( CodeParam other );
|
||||
forceinline CodeParam get( s32 idx );
|
||||
Using_Code( CodeParams );
|
||||
forceinline void append( CodeParams other );
|
||||
forceinline CodeParams get( s32 idx );
|
||||
forceinline bool has_entries();
|
||||
forceinline String to_string();
|
||||
forceinline void to_string( String& result );
|
||||
|
||||
forceinline CodeParam begin() { return begin_CodeParam(* this); }
|
||||
forceinline CodeParam end() { return end_CodeParam(* this); }
|
||||
forceinline CodeParams begin() { return begin_CodeParams(* this); }
|
||||
forceinline CodeParams end() { return end_CodeParams(* this); }
|
||||
#endif
|
||||
Using_CodeOps( CodeParam );
|
||||
Using_CodeOps( CodeParams );
|
||||
forceinline operator Code() { return { (AST*)ast }; }
|
||||
forceinline CodeParam operator*() { return * this; }
|
||||
forceinline AST_Param* operator->() {
|
||||
forceinline CodeParams operator*() { return * this; }
|
||||
forceinline AST_Params* operator->() {
|
||||
GEN_ASSERT(ast);
|
||||
return ast;
|
||||
}
|
||||
CodeParam& operator++();
|
||||
AST_Param* ast;
|
||||
CodeParams& operator++();
|
||||
AST_Params* 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 CodeParam () const { return cast(CodeParam, Code_Invalid); }
|
||||
operator CodeParams () const { return cast(CodeParams, 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 CodeParam () const { return {nullptr}; }
|
||||
operator CodeParams () 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 (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 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 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 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 bool append (CodeSpecifiers specifiers, Specifier spec) { return specifiers_append(specifiers, spec); }
|
||||
forceinline s32 has (CodeSpecifiers specifiers, Specifier spec) { return specifiers_has(specifiers, spec); }
|
||||
|
@ -520,7 +520,7 @@ inline AST_OpCast* CodeOpCast::operator->()
|
||||
return ast;
|
||||
}
|
||||
|
||||
inline CodeParam& CodeParam::operator=( Code other )
|
||||
inline CodeParams& CodeParams::operator=( Code other )
|
||||
{
|
||||
if ( other.ast != nullptr && other->Parent != nullptr )
|
||||
{
|
||||
@ -531,7 +531,7 @@ inline CodeParam& CodeParam::operator=( Code other )
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CodeParam::operator bool()
|
||||
inline CodeParams::operator bool()
|
||||
{
|
||||
return ast != nullptr;
|
||||
}
|
||||
@ -906,9 +906,9 @@ forceinline Code::operator CodeOpCast() const
|
||||
return { (AST_OpCast*)ast };
|
||||
}
|
||||
|
||||
forceinline Code::operator CodeParam() const
|
||||
forceinline Code::operator CodeParams() const
|
||||
{
|
||||
return { (AST_Param*)ast };
|
||||
return { (AST_Params*)ast };
|
||||
}
|
||||
|
||||
forceinline Code::operator CodePragma() const
|
||||
|
@ -53,6 +53,8 @@ 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;
|
||||
@ -67,7 +69,7 @@ extern Code fmt_newline;
|
||||
|
||||
extern CodePragma pragma_once;
|
||||
|
||||
extern CodeParam param_varadic;
|
||||
extern CodeParams param_varadic;
|
||||
|
||||
extern CodePreprocessCond preprocess_else;
|
||||
extern CodePreprocessCond preprocess_endif;
|
||||
|
@ -178,9 +178,9 @@ void class_add_interface( CodeClass self, CodeTypename type )
|
||||
}
|
||||
#pragma endregion CodeClass
|
||||
|
||||
#pragma region CodeParam
|
||||
#pragma region CodeParams
|
||||
inline
|
||||
void params_append( CodeParam appendee, CodeParam other )
|
||||
void params_append( CodeParams appendee, CodeParams other )
|
||||
{
|
||||
GEN_ASSERT(appendee);
|
||||
GEN_ASSERT(other);
|
||||
@ -206,37 +206,37 @@ void params_append( CodeParam appendee, CodeParam other )
|
||||
self->NumEntries++;
|
||||
}
|
||||
inline
|
||||
CodeParam params_get(CodeParam self, s32 idx )
|
||||
CodeParams params_get(CodeParams self, s32 idx )
|
||||
{
|
||||
GEN_ASSERT(self);
|
||||
CodeParam param = self;
|
||||
CodeParams param = self;
|
||||
do
|
||||
{
|
||||
if ( ++ param != nullptr )
|
||||
return NullCode;
|
||||
|
||||
param = cast(CodeParam, cast(Code, param)->Next);
|
||||
param = cast(CodeParams, cast(Code, param)->Next);
|
||||
}
|
||||
while ( --idx );
|
||||
|
||||
return param;
|
||||
}
|
||||
forceinline
|
||||
bool params_has_entries(CodeParam self)
|
||||
bool params_has_entries(CodeParams self)
|
||||
{
|
||||
GEN_ASSERT(self);
|
||||
return self->NumEntries > 0;
|
||||
}
|
||||
#if GEN_COMPILER_CPP
|
||||
forceinline
|
||||
CodeParam& CodeParam::operator ++()
|
||||
CodeParams& CodeParams::operator ++()
|
||||
{
|
||||
* this = ast->Next;
|
||||
return * this;
|
||||
}
|
||||
#endif
|
||||
forceinline
|
||||
CodeParam begin_CodeParam(CodeParam params)
|
||||
CodeParams begin_CodeParams(CodeParams params)
|
||||
{
|
||||
if ( params != nullptr )
|
||||
return params;
|
||||
@ -244,18 +244,18 @@ CodeParam begin_CodeParam(CodeParam params)
|
||||
return NullCode;
|
||||
}
|
||||
forceinline
|
||||
CodeParam end_CodeParam(CodeParam params)
|
||||
CodeParams end_CodeParams(CodeParams params)
|
||||
{
|
||||
// return { (AST_Param*) rcast( AST*, ast)->Last };
|
||||
// return { (AST_Params*) rcast( AST*, ast)->Last };
|
||||
return NullCode;
|
||||
}
|
||||
forceinline
|
||||
CodeParam next_CodeParam(CodeParam params, CodeParam param_iter)
|
||||
CodeParams next_CodeParams(CodeParams params, CodeParams param_iter)
|
||||
{
|
||||
GEN_ASSERT(param_iter);
|
||||
return param_iter->Next;
|
||||
}
|
||||
#pragma endregion CodeParam
|
||||
#pragma endregion CodeParams
|
||||
|
||||
#pragma region CodeSpecifiers
|
||||
inline
|
||||
|
@ -131,7 +131,7 @@ void define_constants()
|
||||
pragma_once->Content = pragma_once->Name;
|
||||
code_set_global((Code)pragma_once);
|
||||
|
||||
param_varadic = (CodeParam) make_code();
|
||||
param_varadic = (CodeParams) make_code();
|
||||
param_varadic->Type = CT_Parameters;
|
||||
param_varadic->Name = get_cached_string( txt("...") );
|
||||
param_varadic->ValueType = t_empty;
|
||||
@ -183,7 +183,6 @@ 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 ));;
|
||||
@ -212,9 +211,10 @@ void define_constants()
|
||||
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
|
||||
code_set_global(cast(Code, spec_local_persist));
|
||||
|
||||
# pragma push_macro("enum_underlying")
|
||||
array_append(PreprocessorDefines, txt("enum_underlying("));
|
||||
# pragma pop_macro("enum_underlying")
|
||||
if (enum_underlying_sig.Len == 0) {
|
||||
enum_underlying_sig = txt("enum_underlying(");
|
||||
}
|
||||
array_append(PreprocessorDefines, enum_underlying_sig);
|
||||
|
||||
# undef def_constant_spec
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ struct Opts_def_struct {
|
||||
CodeClass def_class( StrC name, Opts_def_struct opts GEN_PARAM_DEFAULT );
|
||||
|
||||
struct Opts_def_constructor {
|
||||
CodeParam params;
|
||||
CodeParams params;
|
||||
Code initializer_list;
|
||||
Code body;
|
||||
};
|
||||
@ -86,6 +86,7 @@ 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 );
|
||||
|
||||
@ -94,7 +95,7 @@ CodeExtern def_extern_link( StrC name, CodeBody body );
|
||||
CodeFriend def_friend ( Code symbol );
|
||||
|
||||
struct Opts_def_function {
|
||||
CodeParam params;
|
||||
CodeParams params;
|
||||
CodeTypename ret_type;
|
||||
CodeBody body;
|
||||
CodeSpecifiers specs;
|
||||
@ -111,7 +112,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 {
|
||||
CodeParam params;
|
||||
CodeParams params;
|
||||
CodeTypename ret_type;
|
||||
CodeBody body;
|
||||
CodeSpecifiers specifiers;
|
||||
@ -127,7 +128,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; };
|
||||
CodeParam def_param ( CodeTypename type, StrC name, Opts_def_param opts GEN_PARAM_DEFAULT );
|
||||
CodeParams 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 );
|
||||
@ -137,7 +138,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( CodeParam params, Code definition, Opts_def_template opts GEN_PARAM_DEFAULT );
|
||||
CodeTemplate def_template( CodeParams params, Code definition, Opts_def_template opts GEN_PARAM_DEFAULT );
|
||||
|
||||
struct Opts_def_type {
|
||||
ETypenameTag type_tag;
|
||||
@ -196,8 +197,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 );
|
||||
CodeParam def_params ( s32 num, ... );
|
||||
CodeParam def_params ( s32 num, CodeParam* params );
|
||||
CodeParams def_params ( s32 num, ... );
|
||||
CodeParams def_params ( s32 num, CodeParams* params );
|
||||
CodeSpecifiers def_specifiers ( s32 num, ... );
|
||||
CodeSpecifiers def_specifiers ( s32 num, Specifier* specs );
|
||||
CodeBody def_struct_body ( s32 num, ... );
|
||||
|
@ -13,7 +13,7 @@ enum OpValidateResult : u32
|
||||
};
|
||||
|
||||
internal neverinline
|
||||
OpValidateResult operator__validate( Operator op, CodeParam params_code, CodeTypename ret_type, CodeSpecifiers specifier )
|
||||
OpValidateResult operator__validate( Operator op, CodeParams 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 )
|
||||
{
|
||||
CodeParam params = p.params;
|
||||
CodeParams params = p.params;
|
||||
Code initializer_list = p.initializer_list;
|
||||
Code body = p.body;
|
||||
|
||||
@ -700,6 +700,7 @@ 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 );
|
||||
|
||||
@ -751,6 +752,10 @@ 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" );
|
||||
@ -829,7 +834,7 @@ CodeFriend def_friend( Code declaration )
|
||||
|
||||
CodeFn def_function( StrC name, Opts_def_function p )
|
||||
{
|
||||
CodeParam params = p.params;
|
||||
CodeParams params = p.params;
|
||||
CodeTypename ret_type = p.ret_type;
|
||||
CodeBody body = p.body;
|
||||
CodeSpecifiers specifiers = p.specs;
|
||||
@ -969,7 +974,7 @@ CodeNS def_namespace( StrC name, CodeBody body, Opts_def_namespace p )
|
||||
|
||||
CodeOperator def_operator( Operator op, StrC nspace, Opts_def_operator p )
|
||||
{
|
||||
CodeParam params_code = p.params;
|
||||
CodeParams params_code = p.params;
|
||||
CodeTypename ret_type = p.ret_type;
|
||||
CodeBody body = p.body;
|
||||
CodeSpecifiers specifiers = p.specifiers;
|
||||
@ -1093,7 +1098,7 @@ CodeOpCast def_operator_cast( CodeTypename type, Opts_def_operator_cast p )
|
||||
return result;
|
||||
}
|
||||
|
||||
CodeParam def_param( CodeTypename type, StrC name, Opts_def_param p )
|
||||
CodeParams def_param( CodeTypename type, StrC name, Opts_def_param p )
|
||||
{
|
||||
name_check( def_param, name );
|
||||
null_check( def_param, type );
|
||||
@ -1110,8 +1115,8 @@ CodeParam def_param( CodeTypename type, StrC name, Opts_def_param p )
|
||||
return InvalidCode;
|
||||
}
|
||||
|
||||
CodeParam
|
||||
result = (CodeParam) make_code();
|
||||
CodeParams
|
||||
result = (CodeParams) make_code();
|
||||
result->Type = CT_Parameters;
|
||||
result->Name = get_cached_string( name );
|
||||
|
||||
@ -1247,7 +1252,7 @@ CodeStruct def_struct( StrC name, Opts_def_struct p )
|
||||
return result;
|
||||
}
|
||||
|
||||
CodeTemplate def_template( CodeParam params, Code declaration, Opts_def_template p )
|
||||
CodeTemplate def_template( CodeParams params, Code declaration, Opts_def_template p )
|
||||
{
|
||||
null_check( def_template, declaration );
|
||||
|
||||
@ -2064,7 +2069,7 @@ CodeBody def_namespace_body( s32 num, Code* codes )
|
||||
return result;
|
||||
}
|
||||
|
||||
CodeParam def_params( s32 num, ... )
|
||||
CodeParams def_params( s32 num, ... )
|
||||
{
|
||||
def_body_start( def_params );
|
||||
|
||||
@ -2072,7 +2077,7 @@ CodeParam def_params( s32 num, ... )
|
||||
va_start(va, num);
|
||||
|
||||
Code_POD pod = va_arg(va, Code_POD);
|
||||
CodeParam param = pcast( CodeParam, pod );
|
||||
CodeParams param = pcast( CodeParams, pod );
|
||||
|
||||
null_check( def_params, param );
|
||||
|
||||
@ -2082,12 +2087,12 @@ CodeParam def_params( s32 num, ... )
|
||||
return InvalidCode;
|
||||
}
|
||||
|
||||
CodeParam result = (CodeParam) code_duplicate(param);
|
||||
CodeParams result = (CodeParams) code_duplicate(param);
|
||||
|
||||
while ( -- num )
|
||||
{
|
||||
pod = va_arg(va, Code_POD);
|
||||
param = pcast( CodeParam, pod );
|
||||
param = pcast( CodeParams, pod );
|
||||
|
||||
if ( param->Type != CT_Parameters )
|
||||
{
|
||||
@ -2102,7 +2107,7 @@ CodeParam def_params( s32 num, ... )
|
||||
return result;
|
||||
}
|
||||
|
||||
CodeParam def_params( s32 num, CodeParam* codes )
|
||||
CodeParams def_params( s32 num, CodeParams* codes )
|
||||
{
|
||||
def_body_code_array_start( def_params );
|
||||
|
||||
@ -2119,11 +2124,11 @@ CodeParam def_params( s32 num, CodeParam* codes )
|
||||
return InvalidCode; \
|
||||
}
|
||||
|
||||
CodeParam current = (CodeParam)code_duplicate(* codes);
|
||||
CodeParams current = (CodeParams)code_duplicate(* codes);
|
||||
check_current(current);
|
||||
|
||||
CodeParam
|
||||
result = (CodeParam) make_code();
|
||||
CodeParams
|
||||
result = (CodeParams) make_code();
|
||||
result->Name = current->Name;
|
||||
result->Type = current->Type;
|
||||
result->ValueType = current->ValueType;
|
||||
|
@ -663,6 +663,10 @@ TokArray lex( StrC content )
|
||||
|
||||
switch ( current )
|
||||
{
|
||||
if (array_back(Lexer_Tokens)->Length > 100 ) {
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
case '#':
|
||||
{
|
||||
s32 result = lex_preprocessor_directive( ctx );
|
||||
|
@ -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 CodeParam parse_params ( bool use_template_capture );
|
||||
internal CodeParams 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,11 +797,10 @@ 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, nullptr, 0, mflags ) ));
|
||||
result = cast(Code, def_class( tok_to_str(name), def_assign( body, parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
|
||||
|
||||
else
|
||||
result = cast(Code, def_struct( tok_to_str(name), def_assign( body, (CodeTypename)parent, access, attributes, nullptr, 0, mflags ) ));
|
||||
|
||||
result = cast(Code, def_struct( tok_to_str(name), def_assign( body, (CodeTypename)parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
|
||||
|
||||
if ( inline_cmt )
|
||||
result->InlineCmt = cast(Code, inline_cmt);
|
||||
@ -1479,7 +1478,7 @@ CodeFn parse_function_after_name(
|
||||
)
|
||||
{
|
||||
push_scope();
|
||||
CodeParam params = parse_params(parser_use_parenthesis);
|
||||
CodeParams 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.
|
||||
@ -2516,7 +2515,7 @@ CodeOperator parse_operator_after_ret_type(
|
||||
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op>
|
||||
|
||||
// Parse Params
|
||||
CodeParam params = parse_params(parser_use_parenthesis);
|
||||
CodeParams params = parse_params(parser_use_parenthesis);
|
||||
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op> ( <Parameters> )
|
||||
|
||||
if ( params == nullptr && op == Op_Multiply )
|
||||
@ -2694,7 +2693,7 @@ CodePragma parse_pragma()
|
||||
}
|
||||
|
||||
internal inline
|
||||
CodeParam parse_params( bool use_template_capture )
|
||||
CodeParams parse_params( bool use_template_capture )
|
||||
{
|
||||
push_scope();
|
||||
|
||||
@ -2823,7 +2822,7 @@ CodeParam parse_params( bool use_template_capture )
|
||||
}
|
||||
}
|
||||
|
||||
CodeParam result = ( CodeParam )make_code();
|
||||
CodeParams result = ( CodeParams )make_code();
|
||||
result->Type = CT_Parameters;
|
||||
|
||||
result->Macro = macro;
|
||||
@ -2940,7 +2939,7 @@ CodeParam parse_params( bool use_template_capture )
|
||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, ..
|
||||
}
|
||||
|
||||
CodeParam param = ( CodeParam )make_code();
|
||||
CodeParams param = ( CodeParams )make_code();
|
||||
param->Type = CT_Parameters;
|
||||
|
||||
param->Macro = macro;
|
||||
@ -3372,7 +3371,7 @@ CodeVar parse_variable_after_name(
|
||||
result->NextVar->Parent = cast(Code, result);
|
||||
}
|
||||
|
||||
result->VarConstructorInit = using_constructor_initializer;
|
||||
result->VarParenthesizedInit = using_constructor_initializer;
|
||||
|
||||
parser_pop(& Context);
|
||||
return result;
|
||||
@ -3476,7 +3475,7 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
|
||||
push_scope();
|
||||
|
||||
Token identifier = parse_identifier(nullptr);
|
||||
CodeParam params = parse_params(parser_not_from_template);
|
||||
CodeParams params = parse_params(parser_not_from_template);
|
||||
// <Name> ( <Parameters> )
|
||||
|
||||
Code initializer_list = NullCode;
|
||||
@ -3731,8 +3730,7 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
||||
else if ( currtok.Type == Tok_Preprocess_Macro )
|
||||
{
|
||||
// We'll support the enum_underlying macro
|
||||
StrC sig = txt("enum_underlying(");
|
||||
if ( strc_contains( tok_to_str(currtok), sig) )
|
||||
if ( strc_contains( tok_to_str(currtok), enum_underlying_sig) )
|
||||
{
|
||||
use_macro_underlying = true;
|
||||
underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro, parser_dont_consume_braces );
|
||||
@ -4040,7 +4038,7 @@ CodeFriend parser_parse_friend()
|
||||
function = parse_function_after_name( ModuleFlag_None, NullCode, specifiers, type, name );
|
||||
|
||||
// Parameter list
|
||||
// CodeParam params = parse_params();
|
||||
// CodeParams params = parse_params();
|
||||
// friend <ReturnType> <Name> ( <Parameters> )
|
||||
|
||||
// function = make_code();
|
||||
@ -4410,7 +4408,7 @@ CodeTemplate parser_parse_template()
|
||||
eat( Tok_Decl_Template );
|
||||
// <export> template
|
||||
|
||||
CodeParam params = parse_params( UseTemplateCapture );
|
||||
CodeParams params = parse_params( UseTemplateCapture );
|
||||
if ( cast(Code, params) == Code_Invalid )
|
||||
{
|
||||
parser_pop(& Context);
|
||||
@ -4775,10 +4773,10 @@ else if ( currtok.Type == Tok_DeclType )
|
||||
|
||||
// For function type signatures
|
||||
CodeTypename return_type = NullCode;
|
||||
CodeParam params = NullCode;
|
||||
CodeParams params = NullCode;
|
||||
|
||||
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
||||
CodeParam params_nested = NullCode;
|
||||
CodeParams params_nested = NullCode;
|
||||
#endif
|
||||
|
||||
bool is_function_typename = false;
|
||||
@ -5583,6 +5581,12 @@ 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
|
||||
|
@ -28,6 +28,8 @@ 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;
|
||||
@ -40,7 +42,7 @@ global Code module_private_fragment;
|
||||
|
||||
global Code fmt_newline;
|
||||
|
||||
global CodeParam param_varadic;
|
||||
global CodeParams param_varadic;
|
||||
|
||||
global CodePragma pragma_once;
|
||||
|
||||
|
@ -284,121 +284,4 @@
|
||||
# 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
|
||||
|
@ -17,7 +17,7 @@
|
||||
GEN_NS_BEGIN
|
||||
|
||||
#include "components/types.hpp"
|
||||
#include "components/gen/ecode.hpp"
|
||||
#include "components/gen/ecodetypes.hpp"
|
||||
#include "components/gen/eoperator.hpp"
|
||||
#include "components/gen/especifier.hpp"
|
||||
|
||||
|
@ -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_param = parse_global_body( token_fmt( "typename", StrC name(CodeParam), code_impl_tmpl ));
|
||||
CodeBody impl_code_params = parse_global_body( token_fmt( "typename", StrC name(CodeParams), 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_param = parse_global_body( token_fmt( "typename", StrC name(Param), cast_tmpl ));
|
||||
CodeBody impl_cast_params = parse_global_body( token_fmt( "typename", StrC name(Params), 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_param,
|
||||
impl_code_params,
|
||||
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_param,
|
||||
impl_cast_params,
|
||||
impl_cast_pragma,
|
||||
impl_cast_precond,
|
||||
impl_cast_specs,
|
||||
|
@ -39,6 +39,8 @@ 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:
|
||||
@ -52,7 +54,5 @@ 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.
|
||||
Gencpp's serialization does not provide coherent formatting of the code. The user should use a formatter after serializing.
|
||||
|
@ -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;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
s32 NumEntries;
|
||||
```
|
||||
@ -37,14 +37,15 @@ 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 ECode type for the type of defintion used.
|
||||
Parent should have a compatible CodeType type for the type of defintion used.
|
||||
|
||||
Serialization:
|
||||
|
||||
Will output only the entries, the braces are handled by the parent.
|
||||
|
||||
```cpp
|
||||
<Front>...
|
||||
<Front>
|
||||
...
|
||||
<Back>
|
||||
```
|
||||
|
||||
@ -56,11 +57,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -80,11 +81,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -108,11 +109,11 @@ CodeComment InlineCmt; // Only supported by forward declarations
|
||||
CodeAttributes Attributes;
|
||||
CodeType ParentType;
|
||||
CodeBody Body;
|
||||
CodeType Prev; // Used to store references to interfaces
|
||||
CodeType Next; // Used to store references to interfaces
|
||||
parser::Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeType Prev;
|
||||
CodeType Next;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
AccessSpec ParentAccess;
|
||||
@ -131,7 +132,7 @@ Serialization:
|
||||
};
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Constructor
|
||||
|
||||
@ -140,13 +141,13 @@ Fields:
|
||||
```cpp
|
||||
CodeComment InlineCmt; // Only supported by forward declarations
|
||||
Code InitializerList;
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
Code Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -178,11 +179,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -200,11 +201,11 @@ Fields:
|
||||
CodeComment InlineCmt;
|
||||
CodeSpecifiers Specs;
|
||||
Code Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -235,24 +236,28 @@ Fields:
|
||||
CodeComment InlineCmt;
|
||||
CodeAttributes Attributes;
|
||||
CodeType UnderlyingType;
|
||||
Code UnderlyingTypeMacro;
|
||||
CodeBody Body;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
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>; <InlineCmt>
|
||||
<ModuleFlags> enum class <Name> : <UnderlyingType> or <UnderlyingTypeMacro> ; <InlineCmt>
|
||||
|
||||
// Enum
|
||||
<ModuleFlags> <enum or enum class> <Name> : <UnderlyingType>
|
||||
<ModuleFlags> <enum or enum class> <Name> : <UnderlyingType> or <UnderlyingTypeMacro>
|
||||
{
|
||||
<Body>
|
||||
};
|
||||
@ -267,11 +272,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -287,11 +292,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
CodeBody Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -310,11 +315,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
Code Parent;
|
||||
parser::Token* Tok;
|
||||
StringCached Name;
|
||||
Token* Tok;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -333,11 +338,11 @@ Fields:
|
||||
```cpp
|
||||
CodeComment InlineCmt;
|
||||
Code Declaration;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -356,13 +361,13 @@ CodeComment InlineCmt;
|
||||
CodeAttributes Attributes;
|
||||
CodeSpecifiers Specs;
|
||||
CodeType ReturnType;
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
CodeBody Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
```
|
||||
@ -385,11 +390,11 @@ Serialization:
|
||||
Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
```
|
||||
@ -406,11 +411,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
CodeBody Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
```
|
||||
@ -424,7 +429,7 @@ Serialization:
|
||||
}
|
||||
```
|
||||
|
||||
## Operator Overload
|
||||
## Operator Overload (Operator)
|
||||
|
||||
Fields:
|
||||
|
||||
@ -433,13 +438,13 @@ CodeComment InlineCmt;
|
||||
CodeAttributes Attributes;
|
||||
CodeSpecifiers Specs;
|
||||
CodeType ReturnType;
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
CodeBody Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
OperatorT Op;
|
||||
@ -458,7 +463,7 @@ Serialization:
|
||||
}
|
||||
```
|
||||
|
||||
## Operator Cast Overload ( User-Defined Type Conversion )
|
||||
## Operator Cast Overload ( User-Defined Type Conversion, OpCast )
|
||||
|
||||
Fields:
|
||||
|
||||
@ -467,11 +472,11 @@ CodeComment InlineCmt;
|
||||
CodeSpecifiers Specs;
|
||||
CodeType ValueType;
|
||||
CodeBody Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -488,7 +493,7 @@ Serialization:
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters (AST_Param)
|
||||
## Parameters (AST_Params)
|
||||
|
||||
Fields:
|
||||
|
||||
@ -496,11 +501,12 @@ Fields:
|
||||
CodeType ValueType;
|
||||
Code Macro;
|
||||
Code Value;
|
||||
CodeParam Last;
|
||||
CodeParam Next;
|
||||
parser::Token* Tok;
|
||||
Code Parent;
|
||||
Code PostNameMacro;
|
||||
StringCached Name;
|
||||
CodeParams Last;
|
||||
CodeParams Next;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
CodeT Type;
|
||||
s32 NumEntries;
|
||||
```
|
||||
@ -510,7 +516,7 @@ Serialization:
|
||||
```cpp
|
||||
<Macro>, <Next> ... <Last>
|
||||
|
||||
<Macro> <ValueType> <Name>, <Next>... <Last>
|
||||
<Macro> <ValueType> <Name> <PostNameMacro> = <Value>, <Next>... <Last>
|
||||
```
|
||||
|
||||
## Pragma
|
||||
@ -519,11 +525,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -539,11 +545,11 @@ Fields:
|
||||
|
||||
```cpp
|
||||
StringCached Content;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
paser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
```
|
||||
|
||||
@ -560,11 +566,11 @@ Fields:
|
||||
```cpp
|
||||
SpecifierT ArrSpecs[ AST_ArrSpecs_Cap ];
|
||||
CodeSpecifiers NextSpecs;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
s32 NumEntries;
|
||||
```
|
||||
@ -580,13 +586,13 @@ Serialization:
|
||||
Fields:
|
||||
|
||||
```cpp
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
Code Declaration;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
```
|
||||
@ -609,23 +615,30 @@ Fields:
|
||||
CodeAttributes Attributes;
|
||||
CodeSpecifiers Specs;
|
||||
CodeReturnType ReturnType;
|
||||
CodeParam Params;
|
||||
CodeParams Params;
|
||||
Code ArrExpr;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
b32 IsParamPack;
|
||||
ETypenameTag TypeTag;
|
||||
```
|
||||
|
||||
Serialization:
|
||||
|
||||
```cpp
|
||||
<Attributes> <Name> <Specs> <IsParamPack ?: ...>
|
||||
<Attributes> <TypeTag> <Name> <Specs> <IsParamPack ?: ...>
|
||||
// Function
|
||||
<Attributes> <ReturnType> <Name> <Params> <Specs>
|
||||
```
|
||||
|
||||
`<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.
|
||||
@ -636,11 +649,11 @@ Fields:
|
||||
```cpp
|
||||
CodeComment InlineCmt;
|
||||
Code UnderlyingType;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parse::Token* Tok
|
||||
Token* Tok
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
b32 IsFunction;
|
||||
@ -650,11 +663,16 @@ Serialization:
|
||||
|
||||
```cpp
|
||||
// Regular
|
||||
<ModuleFlags> typedef <UnderlyingType> <Name>; <InlineCmt>
|
||||
<ModuleFlags> typedef <UnderlyingType> <Name> <UnderlyingType-ArrExpr>; <InlineCmt>
|
||||
|
||||
// Functions
|
||||
<ModuleFlags> typedef <ReturnType> <Name>( <Parameters> ); <InlineCmt>
|
||||
<ModuleFlags> typedef <ReturnType> ( <Expression that yeilds an Identifier signature> )( <Parameters> ); <InlineCmt>
|
||||
|
||||
// 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>
|
||||
```
|
||||
|
||||
## Union
|
||||
@ -664,11 +682,11 @@ Fields:
|
||||
```cpp
|
||||
CodeAttributes Attributes;
|
||||
CodeBody Body;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
```
|
||||
@ -690,11 +708,11 @@ Fields:
|
||||
CodeComment InlineCmt;
|
||||
CodeAttributes Attributes;
|
||||
CodeType UnderlyingType;
|
||||
StringCached Name;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
```
|
||||
@ -722,14 +740,15 @@ CodeSpecifiers Specs;
|
||||
CodeType ValueType;
|
||||
Code BitfieldSize;
|
||||
Code Value;
|
||||
StringCached Name;
|
||||
CodeVar NextVar;
|
||||
Code Prev;
|
||||
Code Next;
|
||||
parser::Token* Tok;
|
||||
Token* Tok;
|
||||
Code Parent;
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
s32 VarParenthesizedInit;
|
||||
```
|
||||
|
||||
Serialization:
|
||||
@ -740,4 +759,7 @@ Serialization:
|
||||
|
||||
// Bitfield
|
||||
<ModuleFlags> <Attributes> <Specs> <ValueType> <Name> : <BitfieldSize> = <Value>, NextVar ...; <InlineCmt>
|
||||
|
||||
// VarParenthesizedInit
|
||||
<Attributes> <Specs> <ValueType> <Name>( <Value>, NextVar ... ); <InlineCmt>
|
||||
```
|
||||
|
@ -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 ~5600 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 ~7000 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.
|
||||
|
||||
|
@ -128,7 +128,7 @@ The following CodeTypes are used which the user may optionally use strong typing
|
||||
* CodeNS
|
||||
* CodeOperator
|
||||
* CodeOpCast
|
||||
* CodeParam : Has support for `for : range` iterating across parameters.
|
||||
* CodeParams : Has support for `for : range` iterating across parameters.
|
||||
* CodePreprocessCond
|
||||
* CodePragma
|
||||
* CodeSpecifiers : Has support for `for : range` iterating across specifiers.
|
||||
@ -412,4 +412,8 @@ 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`
|
||||
|
@ -85,13 +85,14 @@ 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_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_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" );
|
||||
|
||||
CodeBody parsed_header_memory = parse_file( path_base "dependencies/memory.hpp" );
|
||||
CodeBody header_memory = def_body(CT_Global_Body);
|
||||
@ -748,7 +749,7 @@ R"(#define AST_ArrSpecs_Cap \
|
||||
txt("CodeOperator"),
|
||||
txt("CodeOpCast"),
|
||||
txt("CodePragma"),
|
||||
txt("CodeParam"),
|
||||
txt("CodeParams"),
|
||||
txt("CodePreprocessCond"),
|
||||
txt("CodeSpecifiers"),
|
||||
txt("CodeTemplate"),
|
||||
@ -800,7 +801,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 (CodeParam param = fn->Params->Next; param != fn->Params.end(); ++ param) {
|
||||
for (CodeParams 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 );
|
||||
@ -935,7 +936,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
||||
}
|
||||
|
||||
b32 handled= false;
|
||||
for ( CodeParam opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
|
||||
for ( CodeParams 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_");
|
||||
@ -945,7 +946,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 (CodeParam other_param = fn->Params; other_param != opt_param; ++ other_param) {
|
||||
for (CodeParams other_param = fn->Params; other_param != opt_param; ++ other_param) {
|
||||
if ( other_param == opt_param ) {
|
||||
params_str.append_fmt( "%SC", other_param->Name );
|
||||
break;
|
||||
@ -1210,7 +1211,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
||||
CodeFn fn = cast(CodeFn, entry);
|
||||
Code prev = entry->Prev;
|
||||
|
||||
for ( CodeParam arr_param : fn->Params )
|
||||
for ( CodeParams 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")) )
|
||||
@ -1222,7 +1223,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
||||
postfix_arr.free();
|
||||
}
|
||||
|
||||
for ( CodeParam opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
|
||||
for ( CodeParams 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 };
|
||||
@ -1481,6 +1482,7 @@ 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 );
|
||||
@ -1617,6 +1619,7 @@ 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 );
|
||||
|
@ -337,7 +337,7 @@ word CodeNS, gen_CodeNS
|
||||
word CodeOperator, gen_CodeOperator
|
||||
word CodeOpCast, gen_CodeOpCast
|
||||
word CodePragma, gen_CodePragma
|
||||
word CodeParam, gen_CodeParam
|
||||
word CodeParams, gen_CodeParams
|
||||
word CodePreprocessCo, gen_CodePreprocessCo
|
||||
word CodeSpecifiers, gen_CodeSpecifiers
|
||||
word CodeTemplate, gen_CodeTemplate
|
||||
|
115
gen_c_library/components/generic_macros.hpp
Normal file
115
gen_c_library/components/generic_macros.hpp
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
#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
|
@ -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 (CodeParam param = fn->Params; param.ast; param = param->Next)
|
||||
for (CodeParams param = fn->Params; param.ast; param = param->Next)
|
||||
{
|
||||
if (param->ValueType)
|
||||
{
|
||||
|
@ -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" );
|
||||
|
@ -266,7 +266,7 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="gen::AST_Param">
|
||||
<Type Name="gen::AST_Params">
|
||||
<DisplayString>{Name} Type: {Type}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="ValueType">ValueType</Item>
|
||||
@ -553,7 +553,7 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="gen::CodeParam">
|
||||
<Type Name="gen::CodeParams">
|
||||
<DisplayString Condition="ast == nullptr">Null</DisplayString>
|
||||
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
|
||||
<Expand>
|
||||
|
@ -30,15 +30,32 @@ 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;
|
||||
|
Loading…
Reference in New Issue
Block a user