mirror of
https://github.com/Ed94/gencpp.git
synced 2024-11-10 02:54:53 -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
|
||||
|
||||
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:
|
||||
|
||||
@ -224,7 +224,7 @@ u8 _Align_Pad[3];
|
||||
*`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`*
|
||||
*`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.
|
||||
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_union_body
|
||||
|
||||
* def_body
|
||||
|
||||
Usage:
|
||||
|
||||
```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 );
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
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`
|
||||
|
||||
|
||||
## 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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 region Gen Interface
|
||||
@ -4404,7 +4512,7 @@ namespace gen
|
||||
\
|
||||
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; \
|
||||
}
|
||||
|
||||
@ -4504,9 +4612,9 @@ namespace gen
|
||||
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;
|
||||
}
|
||||
|
||||
@ -4536,7 +4644,7 @@ namespace gen
|
||||
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() ); \
|
||||
return Code::Invalid;
|
||||
@ -4906,7 +5014,7 @@ namespace gen
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -4936,7 +5044,7 @@ namespace gen
|
||||
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() ); \
|
||||
return Code::Invalid;
|
||||
@ -8099,7 +8207,7 @@ namespace gen
|
||||
#pragma region Builder
|
||||
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, ... )
|
||||
|
260
project/gen.hpp
260
project/gen.hpp
@ -2666,6 +2666,61 @@ namespace gen
|
||||
// Desired width of the AST data structure.
|
||||
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.
|
||||
/*
|
||||
Simple AST POD with functionality to seralize into C++ syntax.
|
||||
@ -2679,6 +2734,9 @@ namespace gen
|
||||
struct AST
|
||||
{
|
||||
# pragma region Member Functions
|
||||
// add_entry with validation
|
||||
void add( AST* other );
|
||||
|
||||
void add_entry( AST* other );
|
||||
|
||||
AST* body()
|
||||
@ -2688,7 +2746,7 @@ namespace gen
|
||||
|
||||
AST* duplicate();
|
||||
|
||||
AST*& entry( u32 idx )
|
||||
AST* entry( u32 idx )
|
||||
{
|
||||
return DynamicEntries ? ArrDyn[ idx ] : ArrStatic[ idx ];
|
||||
}
|
||||
@ -2698,11 +2756,6 @@ namespace gen
|
||||
return num_entries();
|
||||
}
|
||||
|
||||
bool is_invalid()
|
||||
{
|
||||
return Type != ECode::Invalid;
|
||||
}
|
||||
|
||||
bool is_equal( AST* other );
|
||||
|
||||
s32 num_entries()
|
||||
@ -2799,12 +2852,16 @@ namespace gen
|
||||
);
|
||||
}
|
||||
|
||||
String to_string();
|
||||
|
||||
char const* type_str()
|
||||
{
|
||||
return ECode::to_str( Type );
|
||||
}
|
||||
|
||||
String to_string();
|
||||
bool validate_body();
|
||||
|
||||
operator Code();
|
||||
# pragma endregion Member Functions
|
||||
|
||||
constexpr static
|
||||
@ -2852,106 +2909,10 @@ namespace gen
|
||||
|
||||
// Its intended for the AST to have equivalent size to its POD.
|
||||
// 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_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.
|
||||
constexpr Code NoCode = { nullptr };
|
||||
#pragma endregion Data Structures
|
||||
@ -3051,6 +3012,9 @@ namespace gen
|
||||
, Code specifiers = NoCode, Code attributes = NoCode
|
||||
, ModuleFlag mflags = ModuleFlag::None );
|
||||
|
||||
// There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num,
|
||||
/// 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, ... );
|
||||
@ -3073,6 +3037,9 @@ namespace gen
|
||||
Code def_struct_body ( s32 num, Code* codes );
|
||||
Code def_union_body ( s32 num, ... );
|
||||
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 region Parsing
|
||||
@ -3099,23 +3066,7 @@ namespace gen
|
||||
|
||||
# pragma region Untyped text
|
||||
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va );
|
||||
|
||||
//! 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 };
|
||||
}
|
||||
StrC token_fmt_impl( sw, ... );
|
||||
|
||||
Code untyped_str ( StrC content);
|
||||
Code untyped_fmt ( char const* fmt, ... );
|
||||
@ -3383,6 +3334,73 @@ namespace gen
|
||||
|
||||
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
|
||||
|
||||
|
@ -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(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);
|
||||
}
|
||||
@ -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(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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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(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(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 long u32; )) );
|
||||
|
49
test/SOA.hpp
49
test/SOA.hpp
@ -4,21 +4,29 @@
|
||||
#include "gen.hpp"
|
||||
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;
|
||||
name.Ptr = str_fmt_buf( "SOA_%s", (char const*) struct_def->Name );
|
||||
name.Len = str_len( name );
|
||||
StringCached name = get_cached_string( token_fmt( "name", (StrC)struct_def->Name,
|
||||
stringize( SOA_<name> )
|
||||
));
|
||||
|
||||
Code
|
||||
soa_entry = { struct_def->duplicate() };
|
||||
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++ )
|
||||
{
|
||||
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) };
|
||||
|
||||
StrC num_entries_str = to_StrC( str_fmt_buf( "%d", num_entries ) );
|
||||
|
||||
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,
|
||||
stringize( Array<<type>> <name>; )
|
||||
@ -36,20 +46,20 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_arr = parse_variable( token_fmt( "type", (StrC)var_type->Name, "name", (StrC)struct_mem->Name,
|
||||
stringize( <type> <name>[100]; )
|
||||
entry_arr = parse_variable( token_fmt( "type", (StrC)var_type->Name, "name", (StrC)struct_mem->Name, "num", num_entries_str,
|
||||
stringize( <type> <name>[<num>]; )
|
||||
));
|
||||
}
|
||||
|
||||
vars.append( entry_arr );
|
||||
soa.body()->add_entry( entry_arr );
|
||||
soa->body()->add_entry( entry_arr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Code make;
|
||||
{
|
||||
make = parse_function( token_fmt("SOA_Type", name,
|
||||
make = parse_function( token_fmt("SOA_Type", (StrC)name,
|
||||
stringize(
|
||||
static
|
||||
<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++ )
|
||||
{
|
||||
@ -69,11 +79,11 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
||||
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;
|
||||
@ -99,11 +109,14 @@ Code gen_SOA( Code struct_def, bool use_dynamic = false )
|
||||
|
||||
Code ret = def_execution( content );
|
||||
|
||||
get.body()->add_entry( ret );
|
||||
get->body()->add_entry( ret );
|
||||
}
|
||||
|
||||
soa.body()->add_entry( make );
|
||||
soa.body()->add_entry( get );
|
||||
soa->body()->add_entry( make );
|
||||
soa->body()->add_entry( get );
|
||||
soa->body()->validate_body();
|
||||
vars.free();
|
||||
|
||||
return soa;
|
||||
}
|
||||
#endif
|
||||
|
@ -51,7 +51,7 @@ Code gen__buffer( StrC type, sw type_size )
|
||||
Code init;
|
||||
{
|
||||
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))
|
||||
));
|
||||
|
||||
|
@ -140,7 +140,7 @@ Code gen__hashtable( StrC type )
|
||||
char const* tmpl = stringize(
|
||||
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);
|
||||
}
|
||||
@ -166,7 +166,7 @@ Code gen__hashtable( StrC type )
|
||||
char const* tmpl = stringize(
|
||||
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);
|
||||
}
|
||||
@ -373,7 +373,7 @@ Code gen__hashtable( StrC type )
|
||||
);
|
||||
|
||||
hashtable = def_struct( name, def_struct_body( args(
|
||||
, using_entry
|
||||
using_entry
|
||||
, using_array_entry
|
||||
, using_find_result
|
||||
, using_map_proc
|
||||
|
@ -46,7 +46,7 @@ Code gen__ring( StrC type )
|
||||
Code init;
|
||||
{
|
||||
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) )
|
||||
));
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
using namespace gen;
|
||||
|
||||
u32 gen_sanity()
|
||||
u32 gen_sanity_upfront()
|
||||
{
|
||||
Builder
|
||||
gen_sanity_file;
|
||||
@ -27,7 +27,8 @@ u32 gen_sanity()
|
||||
Code empty_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 );
|
||||
}
|
||||
@ -87,9 +88,7 @@ u32 gen_sanity()
|
||||
// Friend
|
||||
{
|
||||
Code fwd = def_class( name(TestFriendFwd));
|
||||
Code body = def_class_body( 1
|
||||
, def_friend( fwd )
|
||||
);
|
||||
Code body = def_class_body( args( def_friend( fwd ) ) );
|
||||
|
||||
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_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);
|
||||
}
|
||||
@ -262,7 +261,7 @@ u32 gen_sanity()
|
||||
Code empty_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 );
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ project( 'test', 'c', 'cpp', default_options : ['buildtype=debug'] )
|
||||
includes = include_directories(
|
||||
[
|
||||
'../../project',
|
||||
'../../thirdparty'
|
||||
# '../../thirdparty'
|
||||
])
|
||||
|
||||
# get_sources = files('./get_sources.ps1')
|
||||
|
@ -6,7 +6,7 @@ includes = include_directories(
|
||||
[
|
||||
'./gen',
|
||||
'../project',
|
||||
'../thirdparty'
|
||||
# '../thirdparty'
|
||||
])
|
||||
|
||||
# get_sources = files('./get_sources.ps1')
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifdef gen_time
|
||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||
#define GEN_FEATURE_PARSING
|
||||
#include "Upfront\Sanity.Upfront.hpp"
|
||||
#include "Parsed\Array.Parsed.hpp"
|
||||
#include "Parsed\Buffer.Parsed.hpp"
|
||||
#include "Parsed\HashTable.Parsed.hpp"
|
||||
@ -55,7 +56,7 @@ int gen_main()
|
||||
u64 D;
|
||||
};
|
||||
)),
|
||||
false
|
||||
128
|
||||
));
|
||||
|
||||
soa_test.write();
|
||||
|
Loading…
Reference in New Issue
Block a user