Templates, test changes (prob not working), progress on parsing bodies and operators.

This time, really not touching for a couple of weeks.
This commit is contained in:
Edward R. Gonzalez 2023-07-10 01:15:25 -04:00
parent 9df177edf4
commit ed6a1d0f95
14 changed files with 1343 additions and 503 deletions

45
.vscode/gencpp.natvis vendored
View File

@ -1,23 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="gen::Code">
<DisplayString>{ast.Name} {ast.Type}</DisplayString>
</Type>
<Type Name="gen::AST">
<DisplayString>{Name} {Type}</DisplayString>
</Type>
<Type Name="String">
<DisplayString Condition="Data == nullptr">null</DisplayString>
<DisplayString>{Data,na}</DisplayString>
<Expand>
<!-- Define a synthetic child element for the Header -->
<Synthetic Name="Header">
<!-- Construct a Header object from the Data pointer -->
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
<!-- Define the children of the synthetic element -->
<Expand>
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
@ -36,8 +25,40 @@
</Expand>
</Type>
<Type Name="gen::AST">
<DisplayString>{Name} {Type}</DisplayString>
<Expand>
<Item Name="Type">Type</Item>
<Item Name="Name">Name</Item>
<Item Name="ArrStatic" Condition="DynamicEntries == false">ArrStatic</Item>
</Expand>
</Type>
<Type Name="gen::Code">
<DisplayString>{ast.Name} {ast.Type}</DisplayString>
</Type>
<Type Name ="gen::Parser::Token">
<DisplayString>Type:{Type} Text:{Text, [Length]s} Length:{Length}</DisplayString>
</Type>
<Type Name="gen::Parser::TokArray">
<DisplayString>Current = { Arr[Idx] }</DisplayString>
<DisplayString>Current[ { Arr[Idx] } ]</DisplayString>
<Expand>
<Synthetic Name="Header">
<DisplayString>{(ArrayHeader*)((char*)Arr - sizeof(ArrayHeader))}</DisplayString>
<Expand>
<Item Name="elem_size">((ArrayHeader*)((char*)Arr - sizeof(ArrayHeader)))->elem_size</Item>
<Item Name="count">((ArrayHeader*)((char*)Arr - sizeof(ArrayHeader)))->count</Item>
<Item Name="capacity">((ArrayHeader*)((char*)Arr - sizeof(ArrayHeader)))->capacity</Item>
<Item Name="allocator">((ArrayHeader*)((char*)Arr - sizeof(ArrayHeader)))->allocator</Item>
</Expand>
</Synthetic>
<ArrayItems>
<Size>((ArrayHeader*)((char*)Arr - sizeof(ArrayHeader)))->count</Size>
<ValuePointer>Arr</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

View File

@ -5,8 +5,6 @@ An attempt at simple staged metaprogramming for c/c++.
The library API is a compositon of code element constructors.
These build up a code AST to then serialize with a file builder.
Intended for small-to midsized projects.
### TOC
* [Notes](#notes)
@ -156,31 +154,43 @@ If in your use case, you decide to have exclusive separation or partial separati
### *WHAT IS NOT PROVIDED*
* Macro or template generation : This library is *currently* intended to avoid those, adding support for them adds unnecessary complexity.
* There may be an argument to support basic templates for substitution, to reduce symbol redundancy for the user, since debuggers tend to do well for them.
* Any sort of template complexity however to resolve if the subtiution is valid with templates would not be supported.
* Vendor provided dynamic dispatch (virtuals) : `override` and `final` specifiers complicate the specifier serialization. (I'll problably end up adding in later)
* Lambdas
* Vendor provided dynamic dispatch (virtuals) : `override` and `final` specifiers complicate the specifier parsing and serialization. (I'll problably end up adding in later)
* RTTI
* Exceptions
* Execution statement validation : Execution expressions are defined using the untyped API.
Keywords in from "Modern C++":
Keywords kept from "Modern C++":
* constexpr : Great to store compile-time constants, (easier to guarantee when emitted from gentime)
* consteval : Technically fine so long as templates are not used. Need to make sure to execute in moderation.
* constexpr : Great to store compile-time constants.
* consteval : Technically fine, need to make sure to execute in moderation.
* constinit : Better than constexpr at doing its job, however, its only c++ 20.
* export : Useful if c++ modules ever come around to actually being usable.
* import : ^^
* module : ^^
These features are not horrible when used conservatively, or are a performance benefit (modules).
When it comes to expressions:
There is no support for validating expressions.
The reason: thats where the can of worms open for parsing validation. This library would most likey more than double in size with that addition alone.
Most of the time, the critical complex metaprogramming conundrums are producing the frame of abstractions around the expressions.
Thus its not very much a priority to add such a level of complexity to the library when there isn't a high reward or need for it.
**There is no support for validating expressions.**
**The reason:** Its difficult to parse with not much of a benefit from doing so.
Most of the time, the critical complex metaprogramming conundrums are producing the frame of abstractions around the expressions (which this library provides constructors to help validate, you can skip that process by using the untyped constructors).
Its not very much a priority to add such a level of complexity to the library when there isn't a high reward or need for it.
Especially when the priority is to keep this library small and easy to grasp for what it is.
When it comes to templates:
Only trivial template support is provided. the intention is for only simple, non-recursive subsitution.
The parameters of the template are treated like regular parameter AST entries.
This means that the typename entry for the parameter AST would be either:
* `class`
* `typename`
* A fundamental type, function, or pointer type.
Anything beyond this usage is not supported by parse_template for arguments (at least not intentionally).
Use at your own mental peril...
*Concepts and Constraints are not supported, its usage is non-tirival substiution.*
### The Data & Interface
@ -194,7 +204,7 @@ Data layout of AST struct:
```cpp
union {
AST* ArrStatic[AST::ArrS_Cap];
Array(AST*) ArrDyn;
Array<AST*> ArrDyn;
StringCached Content;
SpecifierT ArrSpecs[AST::ArrSpecs_Cap];
};
@ -250,6 +260,12 @@ Data Notes:
* They are currently using `Memory::GlobalAllocator`, which are tracked array of arenas that grows as needed (adds buckets when one runs out).
* Memory within the buckets is not resused, so its inherently wasteful (most likely will give non-cached strings their own tailored alloator later)
Two generic templated containers throughout the library:
`template< class Type> struct Array` and `template< class Type> struct HashTable >`
Otherwise the library is free of any templates.
## There are three sets of interfaces for Code AST generation the library provides
* Upfront
@ -261,7 +277,7 @@ Data Notes:
All component ASTs must be previously constructed, and provided on creation of the code AST.
The construction will fail and return InvalidCode otherwise.
Interface :
Interface :``
* def_attributes
* *This is preappened right before the function symbol, or placed after the class or struct keyword for any flavor of attributes used.*
@ -283,6 +299,7 @@ Interface :
* def_specifier
* def_specifiers
* def_struct
* def_template
* def_type
* def_typedef
* def_union
@ -327,14 +344,16 @@ Interface :
* parse_export_body
* parse_extern_link
* parse_friend
* Purposefully are only support forward declares with this constructor.
* parse_function
* parse_global_body
* parse_namespace
* parse_operator
* parse_operator (Not ready)
* parse_struct
* parse_template (Not ready)
* parse_type
* parse_typedef
* parse_union
* parse_union (Not ready)
* parse_using
* parse_variable
@ -539,9 +558,6 @@ Currently unsupported. The following changes would have to be made:
* The builder should be done on a per-thread basis.
* Due to the design of the editor and scanner, it will most likely be best to make each file a job to process request entries on. Receipts should have an an array to store per thread. They can be combined to the final reciepts array when all files have been processed.
For now single-threaded has a bunch of optimization that most likely have done to it and will be more than capable
for the majority of projects this thing is intended for. (IF you use this on Unreal... well your asking for it...)
## Extending the library
This library is relatively very small, and can be extended without much hassle.

View File

@ -1,35 +1,35 @@
// Standard Allocation
#define new static_assert( false, "Banned keyword used: " new )
#define delete static_assert( false, "Banned keyword used: " delete )
#define new static_assert( false, "Banned keyword used: new" )
#define delete static_assert( false, "Banned keyword used: delete" )
// Standard Coroutines
#define co_await static_assert( false, "Banned keyword used: " co_await )
#define co_return static_assert( false, "Banned keyword used: " co_return )
#define co_yield static_assert( false, "Banned keyword used: " co_yield )
#define co_await static_assert( false, "Banned keyword used: co_await" )
#define co_return static_assert( false, "Banned keyword used: co_return" )
#define co_yield static_assert( false, "Banned keyword used: co_yield" )
// Standard Exceptions
#define atomic_cancel static_assert( false, "Banned keyword used: " atomic_cancel )
#define atomic_commit static_assert( false, "Banned keyword used: " atomic_commit )
#define atomic_noexcept static_assert( false, "Banned keyword used: " atomic_noexcept )
#define catch static_assert( false, "Banned keyword used: " catch )
#define noexcept static_assert( false, "Banned keyword used: " noexcept )
#define throw static_assert( false, "Banned keyword used: " throw )
#define try static_assert( false, "Banned keyword used: " try )
#define atomic_cancel static_assert( false, "Banned keyword used: atomic_cancel" )
#define atomic_commit static_assert( false, "Banned keyword used: atomic_commit" )
#define atomic_noexcept static_assert( false, "Banned keyword used: atomic_noexcept" )
#define catch static_assert( false, "Banned keyword used: catch" )
#define noexcept static_assert( false, "Banned keyword used: noexcept" )
#define throw static_assert( false, "Banned keyword used: throw" )
#define try static_assert( false, "Banned keyword used: try" )
// Standard RTTI
#define decltype static_assert( false, "Banned keyword used: " decltype )
#define reflexpr static_assert( false, "Banned keyword used: " reflexpr )
#define typeid static_assert( false, "Banned keyword used: " typeid )
#define decltype static_assert( false, "Banned keyword used: decltype" )
#define reflexpr static_assert( false, "Banned keyword used: reflexpr" )
#define typeid static_assert( false, "Banned keyword used: typeid" )
// Object-Oriented Dynamic Dispatch
#define final static_assert( false, "Banned keyword used: " final )
#define override static_assert( false, "Banned keyword used: " override )
#define virtual static_assert( false, "Banned keyword used: " virtual )
#define final static_assert( false, "Banned keyword used: final" )
#define override static_assert( false, "Banned keyword used: override" )
#define virtual static_assert( false, "Banned keyword used: virtual" )
// Private Access Specifier
#define private static_assert( false, "Banned keyword used: " private )
#define private static_assert( false, "Banned keyword used: private" )
// Template Meta-programming
#define concept static_assert( false, "Banned keyword used: " concept )
#define requires static_assert( false, "Banned keyword used: " requires )
#define template static_assert( false, "Banned keyword used: " template )
#define concept static_assert( false, "Banned keyword used: concept" )
#define requires static_assert( false, "Banned keyword used: requires" )
#define template static_assert( false, "Banned keyword used: template" )

View File

@ -25,15 +25,6 @@
# define ZPL_MODULE_CORE
# define ZPL_MODULE_TIMER
# define ZPL_MODULE_HASHING
// # define ZPL_MODULE_REGEX
// # define ZPL_MODULE_EVENT
// # define ZPL_MODULE_DLL
// # define ZPL_MODULE_OPTS
// # define ZPL_MODULE_PROCESS
// # define ZPL_MODULE_MAT
// # define ZPL_MODULE_THREADING
// # define ZPL_MODULE_JOBS
// # define ZPL_MODULE_PARSER
#include "zpl.h"
using zpl::b32;
@ -185,6 +176,450 @@ while(0);
constexpr
char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
#pragma region Containers
#pragma push_macro("template")
#undef template
template<class Type>
struct TArray
{
struct Header
{
AllocatorInfo Allocator;
uw Capacity;
uw Num;
};
static
TArray<Type> init( AllocatorInfo allocator )
{
return init_reserve( allocator, grow_formula(0) );
}
static
TArray<Type> init_reserve( AllocatorInfo allocator, sw capacity )
{
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) ));
if ( header == nullptr )
return { nullptr };
header->Allocator = allocator;
header->Capacity = capacity;
header->Num = 0;
return { rcast( Type*, header + 1) };
}
static
uw grow_formula( uw value )
{
return 2 * value * 8;
}
bool append( Type value )
{
Header& header = get_header();
if ( header.Num == header.Capacity )
{
if ( ! grow( header.Capacity ))
return false;
}
Data[ header.Num ] = value;
header.Num++;
return true;
}
Type& back( void )
{
Header& header = get_header();
return Data[ header.Num - 1 ];
}
void clear( void )
{
Header& header = get_header();
header.Num = 0;
}
bool fill( uw begin, uw end, Type value )
{
Header& header = get_header();
if ( begin < 0 || end >= header.Num )
return false;
for ( sw idx = begin; idx < end; idx++ )
{
Data[ idx ] = value;
}
return true;
}
void free( void )
{
Header& header = get_header();
zpl::free( header.Allocator, &header );
}
Header& get_header( void )
{
return *( reinterpret_cast< Header* >( Data ) - 1 );
}
bool grow( uw min_capacity )
{
Header& header = get_header();
uw new_capacity = grow_formula( header.Capacity );
if ( new_capacity < min_capacity )
new_capacity = 8;
return set_capacity( new_capacity );
}
uw num( void )
{
return get_header().Num;
}
bool pop( void )
{
Header& header = get_header();
ZPL_ASSERT( header.Num > 0 );
header.Num--;
}
void remove_at( uw idx )
{
Header* header = &get_header();
ZPL_ASSERT( idx < header->Num );
mem_move( header + idx, header + idx + 1, sizeof( Type ) * ( header->Num - idx - 1 ) );
header->Num--;
}
bool reserve( uw new_capacity )
{
Header& header = get_header();
if ( header.Capacity < new_capacity )
return set_capacity( new_capacity );
return true;
}
bool resize( uw num )
{
Header& header = get_header();
if ( num > header.Capacity )
{
if ( ! grow( header.Capacity ) )
return false;
}
header.Num = num;
return true;
}
bool set_capacity( uw new_capacity )
{
Header& header = get_header();
if ( new_capacity == header.Capacity )
return true;
if ( new_capacity < header.Num )
header.Num = new_capacity;
sw size = sizeof( Header ) + sizeof( Type ) * new_capacity;
Header* new_header = reinterpret_cast< Header* >( alloc( header.Allocator, size ) );
if ( new_header == nullptr )
return false;
mem_move( new_header, &header, sizeof( Header ) + sizeof( Type ) * header.Num );
new_header->Allocator = header.Allocator;
new_header->Num = header.Num;
new_header->Capacity = new_capacity;
zpl::free( header.Allocator, &header );
Data = ( Type* )new_header + 1;
return true;
}
Type* Data;
operator Type*()
{
return Data;
}
operator Type const*() const
{
return Data;
}
};
template<typename Type>
struct THashTable
{
struct FindResult
{
sw HashIndex;
sw PrevIndex;
sw EntryIndex;
};
struct Entry
{
u64 Key;
sw Next;
Type Value;
};
static
THashTable<Type> init( AllocatorInfo allocator )
{
THashTable<Type> result = {0};
result.Hashes.init( allocator );
result.Entries.init( allocator );
return result;
}
void clear( void )
{
for ( sw idx = 0; idx < Hashes.num(); idx++ )
Hashes[ idx ] = -1;
Hashes.clear();
Entries.clear();
}
void destroy( void )
{
if ( Hashes )
Hashes.free();
if ( Entries )
Entries.free();
}
Type* get( u64 key )
{
sw idx = find( key ).EntryIndex;
if ( idx > 0 )
return & Entries[ idx ].Value;
return nullptr;
}
using MapProc = void (*)( u64 key, Type value );
void map( MapProc map_proc )
{
ZPL_ASSERT_NOT_NULL( map_proc );
for ( sw idx = 0; idx < Entries.num(); idx++ )
{
map_proc( Entries[ idx ].Key, Entries[ idx ].Value );
}
}
using MapMutProc = void (*)( u64 key, Type* value );
void map_mut( MapMutProc map_proc )
{
ZPL_ASSERT_NOT_NULL( map_proc );
for ( sw idx = 0; idx < Entries.num(); idx++ )
{
map_proc( Entries[ idx ].Key, & Entries[ idx ].Value );
}
}
void grow()
{
sw new_num = TArray<Entry>::grow_formula( Entries.num() )
rehash( new_num );
}
void rehash( sw new_num )
{
sw idx;
sw last_added_index;
THashTable<Type> new_ht = init( Hashes.get_header().Allocator );
new_ht.Hashes.resize( new_num );
new_ht.Entries.reserve( new_ht.Hashes.num() );
for ( idx = 0; idx < new_ht.Hashes.num(); ++idx )
new_ht.Hashes[ idx ] = -1;
for ( idx = 0; idx < Entries.num(); ++idx )
{
Entry& entry = Entries[ idx ];
FindResult find_result;
if ( new_ht.Hashes.num() == 0 )
new_ht.grow();
entry = Entries[ idx ];
find_result = new_ht.find( entry.Key );
last_added_index = new_ht.add_entry( entry.Key );
if ( find_result.PrevIndex < 0 )
new_ht.Hashes[ find_result.HashIndex ] = last_added_index;
else
new_ht.Entries[ find_result.PrevIndex ].Next = last_added_index;
new_ht.Entries[ last_added_index ].Next = find_result.EntryIndex;
new_ht.Entries[ last_added_index ].Value = entry.Value;
}
// *this = new_ht;
// old_ht.destroy();
destroy();
Hashes = new_ht.Hashes;
Entries = new_ht.Entries;
}
void rehash_fast()
{
sw idx;
for ( idx = 0; idx < Entries.num(); idx++ )
Entries[ idx ].Next = -1;
for ( idx = 0; idx < Hashes.num(); idx++ )
Hashes[ idx ] = -1;
for ( idx = 0; idx < Entries.num(); idx++ )
{
Entry* entry;
FindResult find_result;
}
}
void remove( u64 key )
{
FindResult find_result = find( key);
if ( find_result.EntryIndex >= 0 )
{
Entries.remove_at( find_result.EntryIndex );
rehash_fast();
}
}
void remove_entry( sw idx )
{
Entries.remove_at( idx );
}
void set( u64 key, Type value )
{
sw idx;
FindResult find_result;
if ( Hashes.num() == 0 )
grow();
find_result = find( key );
if ( find_result.EntryIndex >= 0 )
{
idx = find_result.EntryIndex;
}
else
{
idx = add_entry( key );
if ( find_result.PrevIndex >= 0 )
{
Entries[ find_result.PrevIndex ].Next = idx;
}
else
{
Hashes[ find_result.HashIndex ] = idx;
}
}
Entries[ idx ].Value = value;
if ( full() )
grow();
}
sw slot( u64 key )
{
for ( sw idx = 0; idx < Hashes.num(); ++idx )
if ( Hashes[ idx ] == key )
return idx;
return -1;
}
TArray< sw> Hashes;
TArray< Entry> Entries;
protected:
sw add_entry( u64 key )
{
sw idx;
Entry entry = { key, -1 };
idx = Entries.num();
Entries.append( entry );
return idx;
}
FindResult find( u64 key )
{
FindResult result = { -1, -1, -1 };
if ( Hashes.num() > 0 )
{
result.HashIndex = key % Hashes.num();
result.EntryIndex = Hashes[ result.HashIndex ];
while ( result.EntryIndex >= 0 )
{
if ( Entries[ result.EntryIndex ].Key == key )
break;
result.PrevIndex = result.EntryIndex;
result.EntryIndex = Entries[ result.EntryIndex ].Next;
}
}
return result;
}
b32 full()
{
return 0.75f * Hashes.num() < Entries.num();
}
};
#pragma pop_macro("template")
#pragma endregion Containers
#pragma region Memory
#pragma endregion Memory
@ -221,18 +656,21 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
sw Capacity;
};
static String make( AllocatorInfo allocator, char const* str )
static
String make( AllocatorInfo allocator, char const* str )
{
sw length = str ? str_len( str ) : 0;
return make_length( allocator, str, length );
}
static String make( AllocatorInfo allocator, StrC str )
static
String make( AllocatorInfo allocator, StrC str )
{
return make_length( allocator, str.Ptr, str.Len );
}
static String make_reserve( AllocatorInfo allocator, sw capacity )
static
String make_reserve( AllocatorInfo allocator, sw capacity )
{
constexpr sw header_size = sizeof( Header );
@ -254,7 +692,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return result;
}
static String make_length( AllocatorInfo allocator, char const* str, sw length )
static
String make_length( AllocatorInfo allocator, char const* str, sw length )
{
constexpr sw header_size = sizeof( Header );
@ -281,7 +720,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return result;
}
static String fmt( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... )
static
String fmt( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... )
{
va_list va;
va_start( va, fmt );
@ -291,7 +731,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return make( allocator, buf );
}
static String fmt_buf( AllocatorInfo allocator, char const* fmt, ... )
static
String fmt_buf( AllocatorInfo allocator, char const* fmt, ... )
{
local_persist thread_local
char buf[ ZPL_PRINTF_MAXLEN ] = { 0 };
@ -304,7 +745,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return make( allocator, buf );
}
static String join( AllocatorInfo allocator, char const** parts, sw num_parts, char const* glue )
static
String join( AllocatorInfo allocator, char const** parts, sw num_parts, char const* glue )
{
String result = make( allocator, "" );
@ -319,7 +761,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return result;
}
static bool are_equal( String lhs, String rhs )
static
bool are_equal( String lhs, String rhs )
{
if ( lhs.length() != rhs.length() )
return false;
@ -520,6 +963,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
};
}
// Used with cached strings
// Essentially makes the string a string view.
String const& operator = ( String const& other ) const
{
if ( this == & other )
@ -532,12 +977,6 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return this_;
}
String& operator += ( String const& other )
{
append( other );
return *this;
}
char& operator [] ( sw index )
{
return Data[ index ];
@ -548,7 +987,6 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
return Data[ index ];
}
char* Data = nullptr;
};
@ -581,6 +1019,7 @@ namespace Memory
void cleanup();
}
inline
sw log_fmt(char const* fmt, ...)
{

File diff suppressed because it is too large Load Diff

View File

@ -71,6 +71,7 @@ namespace gen
Entry( Struct ) \
Entry( Struct_Fwd ) \
Entry( Struct_Body ) \
Entry( Template ) \
Entry( Typedef ) \
Entry( Typename ) \
Entry( Union ) \
@ -771,7 +772,7 @@ namespace gen
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_param ( Code type, StrC name, Code value = NoCode );
Code def_param ( Code type, StrC name, Code value = NoCode );
Code def_specifier( SpecifierT specifier );
Code def_struct( StrC name
@ -780,6 +781,8 @@ namespace gen
, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_template( Code params, Code body, ModuleFlag mflags = ModuleFlag::None );
Code def_type ( StrC name, Code arrayexpr = NoCode, Code specifiers = NoCode, Code attributes = NoCode );
Code def_typedef( StrC name, Code type, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
@ -831,6 +834,7 @@ namespace gen
Code parse_namespace ( StrC namespace_def );
Code parse_operator ( StrC operator_def );
Code parse_struct ( StrC struct_def );
Code parse_template ( StrC template_def );
Code parse_type ( StrC type_def );
Code parse_typedef ( StrC typedef_def );
Code parse_union ( StrC union_def );
@ -1050,6 +1054,8 @@ namespace gen
extern Code t_bool;
extern Code t_char;
extern Code t_wchar_t;
extern Code t_class;
extern Code t_typename;
extern Code access_public;
extern Code access_protected;

View File

@ -114,7 +114,6 @@ Code gen__array( StrC type, sw type_size )
Header& header = get_header();
return Data[ header.Num - 1 ];
))
, spec_inline
);
Code clear = def_function( name(clear), __, t_void
@ -122,7 +121,6 @@ Code gen__array( StrC type, sw type_size )
Header& header = get_header();
header.Num = 0;
))
, spec_inline
);
Code fill;
@ -155,14 +153,12 @@ Code gen__array( StrC type, sw type_size )
Header& header = get_header();
zpl::free( header.Allocator, & header );
))
, spec_inline
);
Code get_header = def_function( name(get_header), __, t_header_ref
, def_execution( code(
return * ( rcast( Header*, Data ) - 1 );
))
, spec_inline
);
Code grow = def_function( name(grow), def_param( t_uw, name(min_capacity)), t_bool
@ -182,7 +178,6 @@ Code gen__array( StrC type, sw type_size )
, def_execution( code(
return get_header().Num;
))
, spec_inline
);
Code pop = def_function( name(pop), __, t_bool
@ -192,7 +187,6 @@ Code gen__array( StrC type, sw type_size )
ZPL_ASSERT( header.Num > 0 );
header.Num--;
))
, spec_inline
);
Code remove_at = def_function( name(remove_at), def_param( t_uw, name(idx)), t_void
@ -203,7 +197,6 @@ Code gen__array( StrC type, sw type_size )
mem_move( header + idx, header + idx + 1, sizeof( Type ) * ( header->Num - idx - 1 ) );
header->Num--;
))
, spec_inline
);
Code reserve = def_function( name(reserve), def_param( t_uw, name(new_capacity)), t_bool
@ -316,7 +309,7 @@ Array(GenArrayRequest) GenArrayRequests;
void gen__array_request( StrC type, sw size, StrC dep = {} )
{
do_once_start
array_init( GenArrayRequests, g_allocator );
array_init( GenArrayRequests, Memory::GlobalAllocator );
do_once_end
// Make sure we don't already have a request for the type.

View File

@ -101,7 +101,6 @@ Code gen__buffer( StrC type, sw type_size )
Data[ header.Num ] = value;
header.Num++;
))
, spec_inline
);
Code appendv;
@ -121,7 +120,6 @@ Code gen__buffer( StrC type, sw type_size )
header.Num += num;
))
, spec_inline
);
}
@ -130,7 +128,6 @@ Code gen__buffer( StrC type, sw type_size )
Header& header = get_header();
header.Num = 0;
))
, spec_inline
);
Code end = def_function( name(end), __, t_type_ref
@ -138,7 +135,6 @@ Code gen__buffer( StrC type, sw type_size )
Header& header = get_header();
return Data[ header.Num - 1 ];
))
, spec_inline
);
Code free = def_function( name(free), __, t_void
@ -146,21 +142,18 @@ Code gen__buffer( StrC type, sw type_size )
Header& header = get_header();
zpl::free( header.Backing, & header );
))
, spec_inline
);
Code get_header = def_function( name(get_header), __, t_header_ref
, def_execution( code(
return * ( rcast( Header*, Data ) - 1 );
))
, spec_inline
);
Code num = def_function( name(num), __, t_sw
, def_execution( code(
return get_header().Num;
))
, spec_inline
);
Code pop = def_function( name(pop), __, t_type
@ -169,7 +162,6 @@ Code gen__buffer( StrC type, sw type_size )
header.Num--;
return Data[ header.Num ];
))
, spec_inline
);
Code wipe = def_function( name(wipe), __, t_void
@ -178,7 +170,6 @@ Code gen__buffer( StrC type, sw type_size )
header.Num = 0;
mem_set( Data, 0, header.Capacity * sizeof( Type ) );
))
, spec_inline
);
Code op_type_ptr = untyped_str( code(
@ -223,7 +214,7 @@ Array(GenBufferRequest) GenBufferRequests;
void gen__buffer_request( StrC type, sw size, StrC dep = {} )
{
do_once_start
array_init( GenBufferRequests, g_allocator );
array_init( GenBufferRequests, Memory::GlobalAllocator );
do_once_end
// Make sure we don't already have a request for the type.

View File

@ -90,7 +90,7 @@ Code gen__hashtable( StrC type, sw type_size )
Code clear = def_function( name(clear), __, t_void
, def_execution( code(
if ( s32 idx = 0; idx < Hashes.num(), idx++ )
for ( s32 idx = 0; idx < Hashes.num(), idx++ )
Hashes[ idx ] = -1;
Entries.clear();
@ -100,11 +100,10 @@ Code gen__hashtable( StrC type, sw type_size )
Code destroy = def_function( name(destroy), __, t_void
, def_execution( code(
if ( Hashes )
Hashes .free();
Hashes.free();
if ( Entries )
Entries.free();
))
, spec_inline
);
Code get = def_function( name(get), def_param( t_u64, name(key)), t_type_ptr
@ -174,7 +173,6 @@ Code gen__hashtable( StrC type, sw type_size )
sw new_num = array_grow_formula( Entries.num() );
rehash( new_num );
))
, spec_inline
);
Code rehash;
@ -214,7 +212,6 @@ Code gen__hashtable( StrC type, sw type_size )
new_ht.Entries[ last_added_index ].Value = entry.Value;
}
// <type>* old_ht = this;
// *this = new_ht;
// old_ht.destroy();
@ -320,7 +317,6 @@ Code gen__hashtable( StrC type, sw type_size )
return -1;
))
, spec_inline
);
Code add_entry = def_function( name(add_entry), def_param( t_u64, name(key)), t_sw
@ -332,7 +328,6 @@ Code gen__hashtable( StrC type, sw type_size )
Entries.append( entry );
return idx;
))
, spec_inline
);
Code find = def_function( name(find), def_param( t_u64, name(key)), t_find_result
@ -362,7 +357,6 @@ Code gen__hashtable( StrC type, sw type_size )
, def_execution( code(
return 0.75f * Hashes.num() < Entries.num();
))
, spec_inline
);
hashtable = def_struct( name, def_struct_body( 24
@ -411,7 +405,7 @@ Array(GenHashTableRequest) GenHashTableRequests;
void gen__hashtable_request( StrC type, sw size, StrC dep = {} )
{
do_once_start
array_init( GenHashTableRequests, g_allocator );
array_init( GenHashTableRequests, Memory::GlobalAllocator );
gen_array( sw );
do_once_end

View File

@ -80,7 +80,6 @@ Code gen__ring( StrC type, sw type_size )
if ( Head == Tail )
Tail = ( Tail + 1 ) % Capacity;
))
, spec_inline
);
Code appendv;
@ -102,21 +101,18 @@ Code gen__ring( StrC type, sw type_size )
, def_execution( code(
return Head == Tail;
))
, spec_inline
);
Code free = def_function( name(free), __, t_void
, def_execution( code(
Buffer.free();
))
, spec_inline
);
Code full = def_function( name(full), __, t_bool
, def_execution( code(
return (Head + 1) % Capacity == Tail;
))
, spec_inline
);
Code get = def_function( name(get), __, t_type_ref
@ -134,7 +130,6 @@ Code gen__ring( StrC type, sw type_size )
Tail = 0;
Buffer.wipe();
))
, spec_inline
);
ring = def_struct( name, def_struct_body( 14,
@ -172,7 +167,7 @@ Array(GenRingRequest) GenRingRequests;
void gen__ring_request( StrC type, sw size, StrC dep = {} )
{
do_once_start
array_init( GenRingRequests, g_allocator );
array_init( GenRingRequests, Memory::GlobalAllocator );
do_once_end
// Make sure we don't already have a request for the type.

View File

@ -78,13 +78,13 @@ Code gen__array( StrC type, sw type_size )
return true;
}
inline Type& back( void )
Type& back( void )
{
Header& header = get_header();
return Data[ header.Num - 1 ];
}
inline void clear( void )
void clear( void )
{
Header& header = get_header();
header.Num = 0;
@ -105,13 +105,13 @@ Code gen__array( StrC type, sw type_size )
return true;
}
inline void free( void )
void free( void )
{
Header& header = get_header();
zpl::free( header.Allocator, &header );
}
inline Header& get_header( void )
Header& get_header( void )
{
return *( reinterpret_cast< Header* >( Data ) - 1 );
}
@ -127,12 +127,12 @@ Code gen__array( StrC type, sw type_size )
return set_capacity( new_capacity );
}
inline uw num( void )
uw num( void )
{
return get_header().Num;
}
inline bool pop( void )
bool pop( void )
{
Header& header = get_header();
@ -140,7 +140,7 @@ Code gen__array( StrC type, sw type_size )
header.Num--;
}
inline void remove_at( uw idx )
void remove_at( uw idx )
{
Header* header = &get_header();
ZPL_ASSERT( idx < header->Num );
@ -233,7 +233,7 @@ Array(GenArrayRequest) GenArrayRequests;
void gen__array_request( StrC type, sw size, StrC dep = {} )
{
do_once_start
array_init( GenArrayRequests, g_allocator );
array_init( GenArrayRequests, Memory::GlobalAllocator );
do_once_end
// Make sure we don't already have a request for the type.

View File

@ -192,7 +192,6 @@ u32 gen_sanity()
gen_sanity_file.print_fmt("\n");
// Specifiers
if (0)
{
Code fwd_fn = parse_function( code(
inline

View File

@ -2,10 +2,11 @@
The following tests focus on attempting to generate some math, containers, and the memory module of zpl.
Not all the files are written how I would practically use the librarry,
Not all the files are written how I would practically use the librarry, the containers for example would
be better on in c++ as templates, since the templates they generate are trivial symbols to inspect or debug.
There will be down the line a proper container, and memory libraries made with this gen library
once the stress test files are complete.
An exmaple of a non-trival generation is a container for elements with SOA or AOS policy for layout.
(If a unified element syntax is desired)
The test is divided between two major sets of tests: Parsed and Nonparsed.

View File

@ -25,5 +25,5 @@ endif
add_project_arguments('-Dgen_time', language : ['c', 'cpp'])
# executable( 'gencpp', sources, include_directories : includes )
executable( 'gencpp', sources, include_directories : includes )
executable( 'gencpp_parsed', sources_parsed, include_directories : includes )