mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 15:54:45 -08:00
Updated readme, added def_body and AST::validate_body
Fixed meson first setup error with missing thirdparty dir (removed it since its no longer used) Improved SOA test to use newly added funtions.
This commit is contained in:
parent
128b0e17fe
commit
4e61fefc55
@ -21,7 +21,7 @@ These build up a code AST to then serialize with a file builder.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
The project has reached a sort of *alpha* state, all the current functionality works however there is some kinks with the design to iterate on.
|
The project has reached a sort of *alpha* state, all the current functionality works for the test cases but it will most likely break in many other cases.
|
||||||
|
|
||||||
The project has no external dependencies beyond:
|
The project has no external dependencies beyond:
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ u8 _Align_Pad[3];
|
|||||||
*`CodeT` is a typedef for `ECode::Type` which has an underlying type of `u32`*
|
*`CodeT` is a typedef for `ECode::Type` which has an underlying type of `u32`*
|
||||||
*`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`*
|
*`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`*
|
||||||
*`StringCahced` is a typedef for `String const`, to denote it is an interned string*
|
*`StringCahced` is a typedef for `String const`, to denote it is an interned string*
|
||||||
*`String` is the dynamically allocated string type for the library.
|
*`String` is the dynamically allocated string type for the library*
|
||||||
|
|
||||||
AST widths are setup to be AST_POD_Size.
|
AST widths are setup to be AST_POD_Size.
|
||||||
The width dictates how much the static array can hold before it must give way to using an allocated array:
|
The width dictates how much the static array can hold before it must give way to using an allocated array:
|
||||||
@ -322,6 +322,8 @@ Bodies:
|
|||||||
* def_struct_body
|
* def_struct_body
|
||||||
* def_union_body
|
* def_union_body
|
||||||
|
|
||||||
|
* def_body
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@ -343,6 +345,9 @@ def_global_body( args( ht_entry, array_ht_entry, hashtable ));
|
|||||||
def_global_body( 3, ht_entry, array_ht_entry, hashtable );
|
def_global_body( 3, ht_entry, array_ht_entry, hashtable );
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If a more incremental approach is desired for the body ASTs, `Code def_body( CodeT type )` can be used to create an empty body.
|
||||||
|
When the members have been populated use: `AST::validate_body` to verify that the members are valid entires for that type.
|
||||||
|
|
||||||
### Parse construction
|
### Parse construction
|
||||||
|
|
||||||
A string provided to the API is parsed for the intended language construct.
|
A string provided to the API is parsed for the intended language construct.
|
||||||
|
@ -8,24 +8,6 @@ All dependencies are currently held within `Bloat.hpp` and `Bloat.cpp`
|
|||||||
|
|
||||||
All the library code is contained in two files: `gen.hpp` and `gen.cpp`
|
All the library code is contained in two files: `gen.hpp` and `gen.cpp`
|
||||||
|
|
||||||
|
|
||||||
## Bloat.hpp/cpp
|
|
||||||
|
|
||||||
Currently acts as the isolation header for thridparty dependencies along with code not directly related to the library.
|
|
||||||
|
|
||||||
Organization:
|
|
||||||
|
|
||||||
* ZPL inclusion and selective symbol exposure to global scope.
|
|
||||||
* Utility macro definitions used throughout the library.
|
|
||||||
* Global memory arena definition
|
|
||||||
* StrC and String definitions
|
|
||||||
* Token string formatter
|
|
||||||
* Formatted and Fatal Logs
|
|
||||||
|
|
||||||
The cpp contains the implementation of the global memory arena and the token formmatter.
|
|
||||||
|
|
||||||
Any global symbol pollution will be removed when dependencies are intergrated properly into the library.
|
|
||||||
|
|
||||||
## gen.hpp
|
## gen.hpp
|
||||||
|
|
||||||
While getting fleshed out, all feature macros are defined on the top of the header.
|
While getting fleshed out, all feature macros are defined on the top of the header.
|
||||||
|
122
project/gen.cpp
122
project/gen.cpp
@ -2795,6 +2795,114 @@ namespace gen
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AST::validate_body()
|
||||||
|
{
|
||||||
|
using namespace ECode;
|
||||||
|
#define CheckBodyType( BodyType ) \
|
||||||
|
if ( Type != BodyType ) \
|
||||||
|
{ \
|
||||||
|
log_failure( "AST::validate_body: Invalid body type %s", debug_str() ); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CheckEntries( Unallowed_Types ) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
for ( s32 idx = 0; idx < num_entries(); idx++ ) \
|
||||||
|
{ \
|
||||||
|
AST* elem = entry( idx ); \
|
||||||
|
\
|
||||||
|
switch ( elem->Type ) \
|
||||||
|
{ \
|
||||||
|
Unallowed_Types \
|
||||||
|
log_failure( "AST::validate_body: Invalid entry in body %s", elem->debug_str() ); \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0);
|
||||||
|
|
||||||
|
switch ( Type )
|
||||||
|
{
|
||||||
|
case Class_Body:
|
||||||
|
CheckBodyType( Class_Body );
|
||||||
|
CheckEntries( AST_BODY_CLASS_UNALLOWED_TYPES );
|
||||||
|
break;
|
||||||
|
case Enum_Body:
|
||||||
|
CheckBodyType( Enum_Body );
|
||||||
|
for ( s32 idx = 0; idx < body()->num_entries(); idx++ )
|
||||||
|
{
|
||||||
|
AST* elem = entry( idx );
|
||||||
|
|
||||||
|
if ( elem->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure( "AST::validate_body: Invalid entry in enum body (needs to be untyped or comment) %s", elem->debug_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Export_Body:
|
||||||
|
for ( s32 idx = 0; idx < num_entries(); idx++ )
|
||||||
|
{
|
||||||
|
AST* elem = entry( idx );
|
||||||
|
|
||||||
|
if ( elem->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure( "AST::validate_body: Invalid entry in export body %s", elem->debug_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Extern_Linkage:
|
||||||
|
CheckBodyType( Extern_Linkage );
|
||||||
|
CheckEntries( AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES );
|
||||||
|
break;
|
||||||
|
case Function_Body:
|
||||||
|
CheckBodyType( Function_Body );
|
||||||
|
CheckEntries( AST_BODY_FUNCTION_UNALLOWED_TYPES );
|
||||||
|
break;
|
||||||
|
case Global_Body:
|
||||||
|
for ( s32 idx = 0; idx < num_entries(); idx++ )
|
||||||
|
{
|
||||||
|
AST* elem = entry( idx );
|
||||||
|
|
||||||
|
if ( elem->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure( "AST::validate_body: Invalid entry in global body %s", elem->debug_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Namespace_Body:
|
||||||
|
CheckBodyType( Namespace_Body );
|
||||||
|
CheckEntries( AST_BODY_NAMESPACE_UNALLOWED_TYPES );
|
||||||
|
break;
|
||||||
|
case Struct_Body:
|
||||||
|
CheckBodyType( Struct_Body );
|
||||||
|
CheckEntries( AST_BODY_STRUCT_UNALLOWED_TYPES );
|
||||||
|
break;
|
||||||
|
case Union_Body:
|
||||||
|
CheckBodyType( Union_Body );
|
||||||
|
for ( s32 idx = 0; idx < body()->num_entries(); idx++ )
|
||||||
|
{
|
||||||
|
AST* elem = entry( idx );
|
||||||
|
|
||||||
|
if ( elem->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure( "AST::validate_body: Invalid entry in union body (needs to be untyped or comment) %s", elem->debug_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_failure( "AST::validate_body: Invalid this AST does not have a body %s", debug_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#pragma endregion AST
|
#pragma endregion AST
|
||||||
|
|
||||||
#pragma region Gen Interface
|
#pragma region Gen Interface
|
||||||
@ -4404,7 +4512,7 @@ namespace gen
|
|||||||
\
|
\
|
||||||
if ( codes == nullptr ) \
|
if ( codes == nullptr ) \
|
||||||
{ \
|
{ \
|
||||||
log_failure("gen::def_class_body: Provided a null array of codes"); \
|
log_failure("gen::" stringize(Name_)" : Provided a null array of codes"); \
|
||||||
return Code::Invalid; \
|
return Code::Invalid; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4504,9 +4612,9 @@ namespace gen
|
|||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( entry->Type != Untyped )
|
if ( entry->Type != Untyped && entry->Type != Comment )
|
||||||
{
|
{
|
||||||
log_failure("gen::def_enum_body: Entry type is not allowed - %s. Must be of untyped type.", entry->debug_str() ); \
|
log_failure("gen::def_enum_body: Entry type is not allowed - %s. Must be of untyped or comment type.", entry->debug_str() ); \
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4536,7 +4644,7 @@ namespace gen
|
|||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( entry->Type != Untyped )
|
if ( entry->Type != Untyped && entry->Type != Comment )
|
||||||
{
|
{
|
||||||
log_failure("gen::def_enum_body: Entry type is not allowed: %s", entry->debug_str() ); \
|
log_failure("gen::def_enum_body: Entry type is not allowed: %s", entry->debug_str() ); \
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
@ -4906,7 +5014,7 @@ namespace gen
|
|||||||
|
|
||||||
if ( entry->Type != Untyped && entry->Type != Comment )
|
if ( entry->Type != Untyped && entry->Type != Comment )
|
||||||
{
|
{
|
||||||
log_failure("gen::def_union_body: Entry type is not allowed - %s. Must be of untyped type.", entry->debug_str() ); \
|
log_failure("gen::def_union_body: Entry type is not allowed - %s. Must be of untyped or comment type.", entry->debug_str() ); \
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4936,7 +5044,7 @@ namespace gen
|
|||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( entry->Type != Untyped )
|
if ( entry->Type != Untyped && entry->Type != Comment )
|
||||||
{
|
{
|
||||||
log_failure("gen::def_union_body: Entry type is not allowed: %s", entry->debug_str() ); \
|
log_failure("gen::def_union_body: Entry type is not allowed: %s", entry->debug_str() ); \
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
@ -8099,7 +8207,7 @@ namespace gen
|
|||||||
#pragma region Builder
|
#pragma region Builder
|
||||||
void Builder::print( Code code )
|
void Builder::print( Code code )
|
||||||
{
|
{
|
||||||
Buffer.append_fmt( "%s\n", code.to_string() );
|
Buffer.append_fmt( "%s\n", code->to_string() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::print_fmt( char const* fmt, ... )
|
void Builder::print_fmt( char const* fmt, ... )
|
||||||
|
266
project/gen.hpp
266
project/gen.hpp
@ -2666,6 +2666,61 @@ namespace gen
|
|||||||
// Desired width of the AST data structure.
|
// Desired width of the AST data structure.
|
||||||
constexpr u32 AST_POD_Size = 256;
|
constexpr u32 AST_POD_Size = 256;
|
||||||
|
|
||||||
|
struct AST;
|
||||||
|
|
||||||
|
/*
|
||||||
|
AST* typedef as to not constantly have to add the '*' as this is written often..
|
||||||
|
*/
|
||||||
|
struct Code
|
||||||
|
{
|
||||||
|
# pragma region Statics
|
||||||
|
// Used to identify ASTs that should always be duplicated. (Global constant ASTs)
|
||||||
|
static Code Global;
|
||||||
|
|
||||||
|
// Used to identify invalid generated code.
|
||||||
|
static Code Invalid;
|
||||||
|
# pragma endregion Statics
|
||||||
|
|
||||||
|
# pragma region Member Functions
|
||||||
|
void set_global();
|
||||||
|
|
||||||
|
bool is_valid();
|
||||||
|
|
||||||
|
bool operator ==( Code other )
|
||||||
|
{
|
||||||
|
return ast == other.ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !=( Code other )
|
||||||
|
{
|
||||||
|
return ast != other.ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator AST*()
|
||||||
|
{
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
AST* operator->()
|
||||||
|
{
|
||||||
|
if ( ast == nullptr )
|
||||||
|
{
|
||||||
|
log_failure("Attempt to dereference a nullptr!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
# pragma endregion Member Functions
|
||||||
|
|
||||||
|
AST* ast;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Code_POD
|
||||||
|
{
|
||||||
|
AST* ast;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: If perf needs it, convert layout an SOA format.
|
// TODO: If perf needs it, convert layout an SOA format.
|
||||||
/*
|
/*
|
||||||
Simple AST POD with functionality to seralize into C++ syntax.
|
Simple AST POD with functionality to seralize into C++ syntax.
|
||||||
@ -2679,6 +2734,9 @@ namespace gen
|
|||||||
struct AST
|
struct AST
|
||||||
{
|
{
|
||||||
# pragma region Member Functions
|
# pragma region Member Functions
|
||||||
|
// add_entry with validation
|
||||||
|
void add( AST* other );
|
||||||
|
|
||||||
void add_entry( AST* other );
|
void add_entry( AST* other );
|
||||||
|
|
||||||
AST* body()
|
AST* body()
|
||||||
@ -2688,7 +2746,7 @@ namespace gen
|
|||||||
|
|
||||||
AST* duplicate();
|
AST* duplicate();
|
||||||
|
|
||||||
AST*& entry( u32 idx )
|
AST* entry( u32 idx )
|
||||||
{
|
{
|
||||||
return DynamicEntries ? ArrDyn[ idx ] : ArrStatic[ idx ];
|
return DynamicEntries ? ArrDyn[ idx ] : ArrStatic[ idx ];
|
||||||
}
|
}
|
||||||
@ -2698,11 +2756,6 @@ namespace gen
|
|||||||
return num_entries();
|
return num_entries();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_invalid()
|
|
||||||
{
|
|
||||||
return Type != ECode::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_equal( AST* other );
|
bool is_equal( AST* other );
|
||||||
|
|
||||||
s32 num_entries()
|
s32 num_entries()
|
||||||
@ -2799,12 +2852,16 @@ namespace gen
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String to_string();
|
||||||
|
|
||||||
char const* type_str()
|
char const* type_str()
|
||||||
{
|
{
|
||||||
return ECode::to_str( Type );
|
return ECode::to_str( Type );
|
||||||
}
|
}
|
||||||
|
|
||||||
String to_string();
|
bool validate_body();
|
||||||
|
|
||||||
|
operator Code();
|
||||||
# pragma endregion Member Functions
|
# pragma endregion Member Functions
|
||||||
|
|
||||||
constexpr static
|
constexpr static
|
||||||
@ -2852,106 +2909,10 @@ namespace gen
|
|||||||
|
|
||||||
// Its intended for the AST to have equivalent size to its POD.
|
// Its intended for the AST to have equivalent size to its POD.
|
||||||
// All extra functionality within the AST namespace should just be syntatic sugar.
|
// All extra functionality within the AST namespace should just be syntatic sugar.
|
||||||
|
static_assert( sizeof(Code) == sizeof(Code_POD), "ERROR: Code is not POD" );
|
||||||
static_assert( sizeof(AST) == sizeof(AST_POD), "ERROR: AST IS NOT POD" );
|
static_assert( sizeof(AST) == sizeof(AST_POD), "ERROR: AST IS NOT POD" );
|
||||||
static_assert( sizeof(AST_POD) == AST_POD_Size, "ERROR: AST POD is not size of AST_POD_Size" );
|
static_assert( sizeof(AST_POD) == AST_POD_Size, "ERROR: AST POD is not size of AST_POD_Size" );
|
||||||
|
|
||||||
/*
|
|
||||||
AST* typedef as to not constantly have to add the '*' as this is written often..
|
|
||||||
*/
|
|
||||||
struct Code
|
|
||||||
{
|
|
||||||
# pragma region Statics
|
|
||||||
// Used to identify ASTs that should always be duplicated. (Global constant ASTs)
|
|
||||||
static Code Global;
|
|
||||||
|
|
||||||
// Used to identify invalid generated code.
|
|
||||||
static Code Invalid;
|
|
||||||
# pragma endregion Statics
|
|
||||||
|
|
||||||
# pragma region Member Functions
|
|
||||||
Code body()
|
|
||||||
{
|
|
||||||
if ( ast == nullptr )
|
|
||||||
{
|
|
||||||
log_failure("Code::body: AST is null!");
|
|
||||||
return Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ast->Type == ECode::Invalid )
|
|
||||||
{
|
|
||||||
log_failure("Code::body: Type is invalid, cannot get");
|
|
||||||
return Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ast->body() };
|
|
||||||
}
|
|
||||||
|
|
||||||
String to_string() const
|
|
||||||
{
|
|
||||||
return ast->to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_global()
|
|
||||||
{
|
|
||||||
if ( ast == nullptr )
|
|
||||||
{
|
|
||||||
log_failure("Code::set_global: Cannot set code as global, AST is null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ast->Parent = Global.ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_valid()
|
|
||||||
{
|
|
||||||
// Originally intended to use operator bool(), however for some reason
|
|
||||||
// The C++ standard has operator Type*() with higher precedence than operator bool().
|
|
||||||
// Even when directly casting to bool. Amazing.
|
|
||||||
return ast != nullptr && ast->Type != ECode::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return ast != nullptr && ast->Type != ECode::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ==( Code other )
|
|
||||||
{
|
|
||||||
return ast == other.ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator !=( Code other )
|
|
||||||
{
|
|
||||||
return ast != other.ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator AST*()
|
|
||||||
{
|
|
||||||
return ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
AST* operator->()
|
|
||||||
{
|
|
||||||
if ( ast == nullptr )
|
|
||||||
{
|
|
||||||
log_failure("Attempt to dereference a nullptr!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ast;
|
|
||||||
}
|
|
||||||
# pragma endregion Member Functions
|
|
||||||
|
|
||||||
AST* ast;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Code_POD
|
|
||||||
{
|
|
||||||
AST_POD* ast;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert( sizeof(Code) == sizeof(Code_POD), "ERROR: Code is not POD" );
|
|
||||||
|
|
||||||
// Used when the its desired when omission is allowed in a definition.
|
// Used when the its desired when omission is allowed in a definition.
|
||||||
constexpr Code NoCode = { nullptr };
|
constexpr Code NoCode = { nullptr };
|
||||||
#pragma endregion Data Structures
|
#pragma endregion Data Structures
|
||||||
@ -3051,8 +3012,11 @@ namespace gen
|
|||||||
, Code specifiers = NoCode, Code attributes = NoCode
|
, Code specifiers = NoCode, Code attributes = NoCode
|
||||||
, ModuleFlag mflags = ModuleFlag::None );
|
, ModuleFlag mflags = ModuleFlag::None );
|
||||||
|
|
||||||
Code def_class_body ( s32 num, ... );
|
// There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num,
|
||||||
Code def_class_body ( s32 num, Code* codes );
|
/// or provide as an array of Code objects.
|
||||||
|
|
||||||
|
Code def_class_body ( s32 num, ... );
|
||||||
|
Code def_class_body ( s32 num, Code* codes );
|
||||||
Code def_enum_body ( s32 num, ... );
|
Code def_enum_body ( s32 num, ... );
|
||||||
Code def_enum_body ( s32 num, Code* codes );
|
Code def_enum_body ( s32 num, Code* codes );
|
||||||
Code def_export_body ( s32 num, ... );
|
Code def_export_body ( s32 num, ... );
|
||||||
@ -3073,6 +3037,9 @@ namespace gen
|
|||||||
Code def_struct_body ( s32 num, Code* codes );
|
Code def_struct_body ( s32 num, Code* codes );
|
||||||
Code def_union_body ( s32 num, ... );
|
Code def_union_body ( s32 num, ... );
|
||||||
Code def_union_body ( s32 num, Code* codes );
|
Code def_union_body ( s32 num, Code* codes );
|
||||||
|
|
||||||
|
// Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries.
|
||||||
|
Code def_body( CodeT type );
|
||||||
# pragma endregion Upfront
|
# pragma endregion Upfront
|
||||||
|
|
||||||
# pragma region Parsing
|
# pragma region Parsing
|
||||||
@ -3098,24 +3065,8 @@ namespace gen
|
|||||||
# pragma endregion Parsing
|
# pragma endregion Parsing
|
||||||
|
|
||||||
# pragma region Untyped text
|
# pragma region Untyped text
|
||||||
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va );
|
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va );
|
||||||
|
StrC token_fmt_impl( sw, ... );
|
||||||
//! Do not use directly. Use the token_fmt macro instead.
|
|
||||||
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
|
|
||||||
inline
|
|
||||||
StrC token_fmt_impl( sw num, ... )
|
|
||||||
{
|
|
||||||
local_persist thread_local
|
|
||||||
char buf[GEN_PRINTF_MAXLEN] = { 0 };
|
|
||||||
mem_set( buf, 0, GEN_PRINTF_MAXLEN );
|
|
||||||
|
|
||||||
va_list va;
|
|
||||||
va_start(va, num );
|
|
||||||
sw result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va);
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
return { result, buf };
|
|
||||||
}
|
|
||||||
|
|
||||||
Code untyped_str ( StrC content);
|
Code untyped_str ( StrC content);
|
||||||
Code untyped_fmt ( char const* fmt, ... );
|
Code untyped_fmt ( char const* fmt, ... );
|
||||||
@ -3383,6 +3334,73 @@ namespace gen
|
|||||||
|
|
||||||
to_add->Parent = this;
|
to_add->Parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void Code::set_global()
|
||||||
|
{
|
||||||
|
if ( ast == nullptr )
|
||||||
|
{
|
||||||
|
log_failure("Code::set_global: Cannot set code as global, AST is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast->Parent = Global.ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool Code::is_valid()
|
||||||
|
{
|
||||||
|
return ast != nullptr && ast->Type != CodeT::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
AST::operator gen::Code()
|
||||||
|
{
|
||||||
|
return { this };
|
||||||
|
}
|
||||||
|
|
||||||
|
Code def_body( CodeT type )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
using namespace ECode;
|
||||||
|
case Class_Body:
|
||||||
|
case Enum_Body:
|
||||||
|
case Export_Body:
|
||||||
|
case Extern_Linkage:
|
||||||
|
case Function_Body:
|
||||||
|
case Global_Body:
|
||||||
|
case Namespace_Body:
|
||||||
|
case Struct_Body:
|
||||||
|
case Union_Body:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_failure( "def_body: Invalid type %s", (char const*)ECode::to_str(type) );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = type;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Do not use directly. Use the token_fmt macro instead.
|
||||||
|
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
|
||||||
|
inline
|
||||||
|
StrC token_fmt_impl( sw num, ... )
|
||||||
|
{
|
||||||
|
local_persist thread_local
|
||||||
|
char buf[GEN_PRINTF_MAXLEN] = { 0 };
|
||||||
|
mem_set( buf, 0, GEN_PRINTF_MAXLEN );
|
||||||
|
|
||||||
|
va_list va;
|
||||||
|
va_start(va, num );
|
||||||
|
sw result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
return { result, buf };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#pragma endregion Inlines
|
#pragma endregion Inlines
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ u32 gen_sanity()
|
|||||||
{};
|
{};
|
||||||
));
|
));
|
||||||
|
|
||||||
empty_body.body()->add_entry( def_comment( txt_StrC("Empty class body") ) );
|
empty_body->body()->add_entry( def_comment( txt_StrC("Empty class body") ) );
|
||||||
|
|
||||||
gen_sanity_file.print(fwd);
|
gen_sanity_file.print(fwd);
|
||||||
gen_sanity_file.print(empty_body);
|
gen_sanity_file.print(empty_body);
|
||||||
@ -80,7 +80,7 @@ u32 gen_sanity()
|
|||||||
};
|
};
|
||||||
));
|
));
|
||||||
|
|
||||||
c_extern.body()->add_entry( empty_comment );
|
c_extern->body()->add_entry( empty_comment );
|
||||||
|
|
||||||
gen_sanity_file.print(c_extern);
|
gen_sanity_file.print(c_extern);
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ u32 gen_sanity()
|
|||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
def.body()->add_entry( def_comment( txt_StrC("Empty function body") ) );
|
def->body()->add_entry( def_comment( txt_StrC("Empty function body") ) );
|
||||||
|
|
||||||
gen_sanity_file.print(fwd);
|
gen_sanity_file.print(fwd);
|
||||||
gen_sanity_file.print(def);
|
gen_sanity_file.print(def);
|
||||||
@ -134,7 +134,7 @@ u32 gen_sanity()
|
|||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
def.body()->add_entry( def_comment( txt_StrC("Empty namespace body") ) );
|
def->body()->add_entry( def_comment( txt_StrC("Empty namespace body") ) );
|
||||||
|
|
||||||
gen_sanity_file.print(def);
|
gen_sanity_file.print(def);
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ u32 gen_sanity()
|
|||||||
};
|
};
|
||||||
));
|
));
|
||||||
|
|
||||||
class_def.body()->add_entry( op_ptr );
|
class_def->body()->add_entry( op_ptr );
|
||||||
|
|
||||||
gen_sanity_file.print(class_def);
|
gen_sanity_file.print(class_def);
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ u32 gen_sanity()
|
|||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
def.body()->add_entry( def_comment( txt_StrC("Empty function body") ) );
|
def->body()->add_entry( def_comment( txt_StrC("Empty function body") ) );
|
||||||
|
|
||||||
gen_sanity_file.print(fwd);
|
gen_sanity_file.print(fwd);
|
||||||
gen_sanity_file.print(def);
|
gen_sanity_file.print(def);
|
||||||
@ -237,7 +237,7 @@ u32 gen_sanity()
|
|||||||
{};
|
{};
|
||||||
));
|
));
|
||||||
|
|
||||||
empty_body.body()->add_entry( def_comment( txt_StrC("Empty struct body") ) );
|
empty_body->body()->add_entry( def_comment( txt_StrC("Empty struct body") ) );
|
||||||
|
|
||||||
gen_sanity_file.print(fwd);
|
gen_sanity_file.print(fwd);
|
||||||
gen_sanity_file.print(empty_body);
|
gen_sanity_file.print(empty_body);
|
||||||
@ -253,7 +253,7 @@ u32 gen_sanity()
|
|||||||
};
|
};
|
||||||
));
|
));
|
||||||
|
|
||||||
empty.body()->add_entry( def_comment( txt_StrC("Empty union body") ) );
|
empty->body()->add_entry( def_comment( txt_StrC("Empty union body") ) );
|
||||||
|
|
||||||
gen_sanity_file.print( parse_typedef( code( typedef unsigned short u16; )) );
|
gen_sanity_file.print( parse_typedef( code( typedef unsigned short u16; )) );
|
||||||
gen_sanity_file.print( parse_typedef( code( typedef unsigned long u32; )) );
|
gen_sanity_file.print( parse_typedef( code( typedef unsigned long u32; )) );
|
||||||
|
49
test/SOA.hpp
49
test/SOA.hpp
@ -4,21 +4,29 @@
|
|||||||
#include "gen.hpp"
|
#include "gen.hpp"
|
||||||
using namespace gen;
|
using namespace gen;
|
||||||
|
|
||||||
Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
Code gen_SOA( Code struct_def, s32 num_entries = 0 )
|
||||||
{
|
{
|
||||||
StrC name;
|
StringCached name = get_cached_string( token_fmt( "name", (StrC)struct_def->Name,
|
||||||
name.Ptr = str_fmt_buf( "SOA_%s", (char const*) struct_def->Name );
|
stringize( SOA_<name> )
|
||||||
name.Len = str_len( name );
|
));
|
||||||
|
|
||||||
Code
|
Code
|
||||||
soa_entry = { struct_def->duplicate() };
|
soa_entry = { struct_def->duplicate() };
|
||||||
soa_entry->Name = get_cached_string( name(Entry) );
|
soa_entry->Name = get_cached_string( name(Entry) );
|
||||||
|
|
||||||
Array<Code> vars = Array<Code>::init( Memory::GlobalAllocator );;
|
constexpr s32 Num_Vars_Cap = 128;
|
||||||
|
|
||||||
Code soa = def_struct( name, def_struct_body( 1, soa_entry ) );
|
local_persist Code var_memory[Num_Vars_Cap];
|
||||||
|
local_persist Arena var_arena;
|
||||||
|
do_once_start
|
||||||
|
var_arena = Arena::init_from_memory( var_memory, kilobytes(Num_Vars_Cap) );
|
||||||
|
do_once_end
|
||||||
|
|
||||||
|
Array<Code> vars = Array<Code>::init( var_arena );;
|
||||||
|
|
||||||
|
Code soa = def_struct( name, def_body( ECode::Struct_Body ));
|
||||||
{
|
{
|
||||||
Code body = struct_def.body();
|
Code body = *struct_def->body();
|
||||||
for ( s32 idx = 0; idx < body->num_entries(); idx++ )
|
for ( s32 idx = 0; idx < body->num_entries(); idx++ )
|
||||||
{
|
{
|
||||||
Code struct_mem = { body->entry( idx ) };
|
Code struct_mem = { body->entry( idx ) };
|
||||||
@ -27,8 +35,10 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
|||||||
{
|
{
|
||||||
Code var_type = { struct_mem->entry(0) };
|
Code var_type = { struct_mem->entry(0) };
|
||||||
|
|
||||||
|
StrC num_entries_str = to_StrC( str_fmt_buf( "%d", num_entries ) );
|
||||||
|
|
||||||
Code entry_arr = { nullptr };
|
Code entry_arr = { nullptr };
|
||||||
if ( use_dynamic)
|
if ( ! num_entries)
|
||||||
{
|
{
|
||||||
entry_arr = parse_variable( token_fmt( "type", (StrC)var_type->Name, "name", (StrC)struct_mem->Name,
|
entry_arr = parse_variable( token_fmt( "type", (StrC)var_type->Name, "name", (StrC)struct_mem->Name,
|
||||||
stringize( Array<<type>> <name>; )
|
stringize( Array<<type>> <name>; )
|
||||||
@ -36,20 +46,20 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entry_arr = parse_variable( token_fmt( "type", (StrC)var_type->Name, "name", (StrC)struct_mem->Name,
|
entry_arr = parse_variable( token_fmt( "type", (StrC)var_type->Name, "name", (StrC)struct_mem->Name, "num", num_entries_str,
|
||||||
stringize( <type> <name>[100]; )
|
stringize( <type> <name>[<num>]; )
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.append( entry_arr );
|
vars.append( entry_arr );
|
||||||
soa.body()->add_entry( entry_arr );
|
soa->body()->add_entry( entry_arr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Code make;
|
Code make;
|
||||||
{
|
{
|
||||||
make = parse_function( token_fmt("SOA_Type", name,
|
make = parse_function( token_fmt("SOA_Type", (StrC)name,
|
||||||
stringize(
|
stringize(
|
||||||
static
|
static
|
||||||
<SOA_Type> make( AllocatorInfo allocator )
|
<SOA_Type> make( AllocatorInfo allocator )
|
||||||
@ -59,7 +69,7 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
|||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
if ( use_dynamic )
|
if ( ! num_entries )
|
||||||
{
|
{
|
||||||
for ( s32 idx = 0; idx < vars.num(); idx++ )
|
for ( s32 idx = 0; idx < vars.num(); idx++ )
|
||||||
{
|
{
|
||||||
@ -69,11 +79,11 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
|||||||
stringize( soa.<var_name> = <var_type>::init( allocator ); )
|
stringize( soa.<var_name> = <var_type>::init( allocator ); )
|
||||||
));
|
));
|
||||||
|
|
||||||
make.body()->add_entry( arr_init );
|
make->body()->add_entry( arr_init );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
make.body()->add_entry( def_execution( code( return soa; ) ));
|
make->body()->add_entry( def_execution( code( return soa; ) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
Code get;
|
Code get;
|
||||||
@ -99,11 +109,14 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
|||||||
|
|
||||||
Code ret = def_execution( content );
|
Code ret = def_execution( content );
|
||||||
|
|
||||||
get.body()->add_entry( ret );
|
get->body()->add_entry( ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
soa.body()->add_entry( make );
|
soa->body()->add_entry( make );
|
||||||
soa.body()->add_entry( get );
|
soa->body()->add_entry( get );
|
||||||
|
soa->body()->validate_body();
|
||||||
|
vars.free();
|
||||||
|
|
||||||
return soa;
|
return soa;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,7 +51,7 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
Code init;
|
Code init;
|
||||||
{
|
{
|
||||||
Code params = def_params( args(
|
Code params = def_params( args(
|
||||||
, def_param( t_allocator_info, name(allocator))
|
def_param( t_allocator_info, name(allocator))
|
||||||
, def_param( t_sw, name(capacity))
|
, def_param( t_sw, name(capacity))
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ Code gen__hashtable( StrC type )
|
|||||||
char const* tmpl = stringize(
|
char const* tmpl = stringize(
|
||||||
void (*) ( u64 key, <type> value )
|
void (*) ( u64 key, <type> value )
|
||||||
);
|
);
|
||||||
Code value = untyped_str( token_fmt( "type", (StrC)t_type.to_string(), tmpl ) );
|
Code value = untyped_str( token_fmt( "type", (StrC)t_type->to_string(), tmpl ) );
|
||||||
|
|
||||||
using_map_proc = def_using ( name(MapProc), value);
|
using_map_proc = def_using ( name(MapProc), value);
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ Code gen__hashtable( StrC type )
|
|||||||
char const* tmpl = stringize(
|
char const* tmpl = stringize(
|
||||||
void (*) ( u64 key, <type> value )
|
void (*) ( u64 key, <type> value )
|
||||||
);
|
);
|
||||||
Code value = untyped_str( token_fmt( "type", (StrC)t_type_ptr.to_string(), tmpl ) );
|
Code value = untyped_str( token_fmt( "type", (StrC)t_type_ptr->to_string(), tmpl ) );
|
||||||
|
|
||||||
using_map_mut_proc = def_using ( name(MapMutProc), value);
|
using_map_mut_proc = def_using ( name(MapMutProc), value);
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ Code gen__hashtable( StrC type )
|
|||||||
);
|
);
|
||||||
|
|
||||||
hashtable = def_struct( name, def_struct_body( args(
|
hashtable = def_struct( name, def_struct_body( args(
|
||||||
, using_entry
|
using_entry
|
||||||
, using_array_entry
|
, using_array_entry
|
||||||
, using_find_result
|
, using_find_result
|
||||||
, using_map_proc
|
, using_map_proc
|
||||||
|
@ -46,7 +46,7 @@ Code gen__ring( StrC type )
|
|||||||
Code init;
|
Code init;
|
||||||
{
|
{
|
||||||
Code params = def_params( args(
|
Code params = def_params( args(
|
||||||
, def_param( t_allocator_info, name(allocator) )
|
def_param( t_allocator_info, name(allocator) )
|
||||||
, def_param( t_uw, name(max_size) )
|
, def_param( t_uw, name(max_size) )
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using namespace gen;
|
using namespace gen;
|
||||||
|
|
||||||
u32 gen_sanity()
|
u32 gen_sanity_upfront()
|
||||||
{
|
{
|
||||||
Builder
|
Builder
|
||||||
gen_sanity_file;
|
gen_sanity_file;
|
||||||
@ -27,7 +27,8 @@ u32 gen_sanity()
|
|||||||
Code empty_body;
|
Code empty_body;
|
||||||
{
|
{
|
||||||
Code cmt = def_comment( txt_StrC("Empty class body") );
|
Code cmt = def_comment( txt_StrC("Empty class body") );
|
||||||
Code body = def_class_body( 1, cmt );
|
|
||||||
|
Code body = def_class_body( args( cmt ) );
|
||||||
|
|
||||||
empty_body = def_class( name(TestEmptyClass), body );
|
empty_body = def_class( name(TestEmptyClass), body );
|
||||||
}
|
}
|
||||||
@ -87,9 +88,7 @@ u32 gen_sanity()
|
|||||||
// Friend
|
// Friend
|
||||||
{
|
{
|
||||||
Code fwd = def_class( name(TestFriendFwd));
|
Code fwd = def_class( name(TestFriendFwd));
|
||||||
Code body = def_class_body( 1
|
Code body = def_class_body( args( def_friend( fwd ) ) );
|
||||||
, def_friend( fwd )
|
|
||||||
);
|
|
||||||
|
|
||||||
gen_sanity_file.print( def_class( name(TestFriend), body ) );
|
gen_sanity_file.print( def_class( name(TestFriend), body ) );
|
||||||
}
|
}
|
||||||
@ -196,7 +195,7 @@ u32 gen_sanity()
|
|||||||
|
|
||||||
Code op_ptr = def_operator_cast( t_u8_ptr, __ );
|
Code op_ptr = def_operator_cast( t_u8_ptr, __ );
|
||||||
|
|
||||||
Code op_class = def_class( name(TestOperatorCast), def_class_body( 1, op_ptr ) );
|
Code op_class = def_class( name(TestOperatorCast), def_class_body( args( op_ptr) ) );
|
||||||
|
|
||||||
gen_sanity_file.print(op_class);
|
gen_sanity_file.print(op_class);
|
||||||
}
|
}
|
||||||
@ -245,7 +244,7 @@ u32 gen_sanity()
|
|||||||
{
|
{
|
||||||
Code fwd_fn = def_function( name(test_function_specifiers), __, __, __, spec_inline );
|
Code fwd_fn = def_function( name(test_function_specifiers), __, __, __, spec_inline );
|
||||||
|
|
||||||
// TODO: Need an op overload here
|
// TODO : Need an op overload here
|
||||||
|
|
||||||
Code u8_ptr = def_type( name(u8), __, spec_ptr );
|
Code u8_ptr = def_type( name(u8), __, spec_ptr );
|
||||||
Code typedef_u8_ptr = def_typedef( name(ConstExprTest), u8_ptr );
|
Code typedef_u8_ptr = def_typedef( name(ConstExprTest), u8_ptr );
|
||||||
@ -262,7 +261,7 @@ u32 gen_sanity()
|
|||||||
Code empty_body;
|
Code empty_body;
|
||||||
{
|
{
|
||||||
Code cmt = def_comment( txt_StrC("Empty struct body") );
|
Code cmt = def_comment( txt_StrC("Empty struct body") );
|
||||||
Code body = def_class_body( 1, cmt );
|
Code body = def_class_body( args( cmt ) );
|
||||||
|
|
||||||
empty_body = def_class( name(TestEmptyStruct), body );
|
empty_body = def_class( name(TestEmptyStruct), body );
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ project( 'test', 'c', 'cpp', default_options : ['buildtype=debug'] )
|
|||||||
includes = include_directories(
|
includes = include_directories(
|
||||||
[
|
[
|
||||||
'../../project',
|
'../../project',
|
||||||
'../../thirdparty'
|
# '../../thirdparty'
|
||||||
])
|
])
|
||||||
|
|
||||||
# get_sources = files('./get_sources.ps1')
|
# get_sources = files('./get_sources.ps1')
|
||||||
|
@ -6,7 +6,7 @@ includes = include_directories(
|
|||||||
[
|
[
|
||||||
'./gen',
|
'./gen',
|
||||||
'../project',
|
'../project',
|
||||||
'../thirdparty'
|
# '../thirdparty'
|
||||||
])
|
])
|
||||||
|
|
||||||
# get_sources = files('./get_sources.ps1')
|
# get_sources = files('./get_sources.ps1')
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifdef gen_time
|
#ifdef gen_time
|
||||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
#define GEN_FEATURE_PARSING
|
#define GEN_FEATURE_PARSING
|
||||||
|
#include "Upfront\Sanity.Upfront.hpp"
|
||||||
#include "Parsed\Array.Parsed.hpp"
|
#include "Parsed\Array.Parsed.hpp"
|
||||||
#include "Parsed\Buffer.Parsed.hpp"
|
#include "Parsed\Buffer.Parsed.hpp"
|
||||||
#include "Parsed\HashTable.Parsed.hpp"
|
#include "Parsed\HashTable.Parsed.hpp"
|
||||||
@ -55,7 +56,7 @@ int gen_main()
|
|||||||
u64 D;
|
u64 D;
|
||||||
};
|
};
|
||||||
)),
|
)),
|
||||||
false
|
128
|
||||||
));
|
));
|
||||||
|
|
||||||
soa_test.write();
|
soa_test.write();
|
||||||
|
Loading…
Reference in New Issue
Block a user