mirror of
https://github.com/Ed94/gencpp.git
synced 2024-11-10 02:54:53 -08:00
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:
parent
9df177edf4
commit
ed6a1d0f95
45
.vscode/gencpp.natvis
vendored
45
.vscode/gencpp.natvis
vendored
@ -1,23 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
<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">
|
<Type Name="String">
|
||||||
<DisplayString Condition="Data == nullptr">null</DisplayString>
|
<DisplayString Condition="Data == nullptr">null</DisplayString>
|
||||||
<DisplayString>{Data,na}</DisplayString>
|
<DisplayString>{Data,na}</DisplayString>
|
||||||
<Expand>
|
<Expand>
|
||||||
<!-- Define a synthetic child element for the Header -->
|
|
||||||
<Synthetic Name="Header">
|
<Synthetic Name="Header">
|
||||||
<!-- Construct a Header object from the Data pointer -->
|
|
||||||
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
|
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
|
||||||
<!-- Define the children of the synthetic element -->
|
|
||||||
<Expand>
|
<Expand>
|
||||||
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
|
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
|
||||||
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
|
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
|
||||||
@ -36,8 +25,40 @@
|
|||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</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">
|
<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>
|
</Type>
|
||||||
|
|
||||||
</AutoVisualizer>
|
</AutoVisualizer>
|
||||||
|
60
Readme.md
60
Readme.md
@ -5,8 +5,6 @@ An attempt at simple staged metaprogramming for c/c++.
|
|||||||
The library API is a compositon of code element constructors.
|
The library API is a compositon of code element constructors.
|
||||||
These build up a code AST to then serialize with a file builder.
|
These build up a code AST to then serialize with a file builder.
|
||||||
|
|
||||||
Intended for small-to midsized projects.
|
|
||||||
|
|
||||||
### TOC
|
### TOC
|
||||||
|
|
||||||
* [Notes](#notes)
|
* [Notes](#notes)
|
||||||
@ -156,31 +154,43 @@ If in your use case, you decide to have exclusive separation or partial separati
|
|||||||
|
|
||||||
### *WHAT IS NOT PROVIDED*
|
### *WHAT IS NOT PROVIDED*
|
||||||
|
|
||||||
* Macro or template generation : This library is *currently* intended to avoid those, adding support for them adds unnecessary complexity.
|
* Lambdas
|
||||||
* 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.
|
* Vendor provided dynamic dispatch (virtuals) : `override` and `final` specifiers complicate the specifier parsing and serialization. (I'll problably end up adding in later)
|
||||||
* 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)
|
|
||||||
* RTTI
|
* RTTI
|
||||||
* Exceptions
|
* Exceptions
|
||||||
* Execution statement validation : Execution expressions are defined using the untyped API.
|
* 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)
|
* constexpr : Great to store compile-time constants.
|
||||||
* consteval : Technically fine so long as templates are not used. Need to make sure to execute in moderation.
|
* consteval : Technically fine, need to make sure to execute in moderation.
|
||||||
* constinit : Better than constexpr at doing its job, however, its only c++ 20.
|
* 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.
|
* export : Useful if c++ modules ever come around to actually being usable.
|
||||||
* import : ^^
|
* import : ^^
|
||||||
* module : ^^
|
* module : ^^
|
||||||
|
|
||||||
These features are not horrible when used conservatively, or are a performance benefit (modules).
|
|
||||||
|
|
||||||
When it comes to expressions:
|
When it comes to expressions:
|
||||||
|
|
||||||
There is no support for validating 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.
|
**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.
|
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).
|
||||||
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.
|
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
|
### The Data & Interface
|
||||||
|
|
||||||
@ -194,7 +204,7 @@ Data layout of AST struct:
|
|||||||
```cpp
|
```cpp
|
||||||
union {
|
union {
|
||||||
AST* ArrStatic[AST::ArrS_Cap];
|
AST* ArrStatic[AST::ArrS_Cap];
|
||||||
Array(AST*) ArrDyn;
|
Array<AST*> ArrDyn;
|
||||||
StringCached Content;
|
StringCached Content;
|
||||||
SpecifierT ArrSpecs[AST::ArrSpecs_Cap];
|
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).
|
* 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)
|
* 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
|
## There are three sets of interfaces for Code AST generation the library provides
|
||||||
|
|
||||||
* Upfront
|
* Upfront
|
||||||
@ -261,7 +277,7 @@ Data Notes:
|
|||||||
All component ASTs must be previously constructed, and provided on creation of the code AST.
|
All component ASTs must be previously constructed, and provided on creation of the code AST.
|
||||||
The construction will fail and return InvalidCode otherwise.
|
The construction will fail and return InvalidCode otherwise.
|
||||||
|
|
||||||
Interface :
|
Interface :``
|
||||||
|
|
||||||
* def_attributes
|
* def_attributes
|
||||||
* *This is preappened right before the function symbol, or placed after the class or struct keyword for any flavor of attributes used.*
|
* *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_specifier
|
||||||
* def_specifiers
|
* def_specifiers
|
||||||
* def_struct
|
* def_struct
|
||||||
|
* def_template
|
||||||
* def_type
|
* def_type
|
||||||
* def_typedef
|
* def_typedef
|
||||||
* def_union
|
* def_union
|
||||||
@ -327,14 +344,16 @@ Interface :
|
|||||||
* parse_export_body
|
* parse_export_body
|
||||||
* parse_extern_link
|
* parse_extern_link
|
||||||
* parse_friend
|
* parse_friend
|
||||||
|
* Purposefully are only support forward declares with this constructor.
|
||||||
* parse_function
|
* parse_function
|
||||||
* parse_global_body
|
* parse_global_body
|
||||||
* parse_namespace
|
* parse_namespace
|
||||||
* parse_operator
|
* parse_operator (Not ready)
|
||||||
* parse_struct
|
* parse_struct
|
||||||
|
* parse_template (Not ready)
|
||||||
* parse_type
|
* parse_type
|
||||||
* parse_typedef
|
* parse_typedef
|
||||||
* parse_union
|
* parse_union (Not ready)
|
||||||
* parse_using
|
* parse_using
|
||||||
* parse_variable
|
* 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.
|
* 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.
|
* 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
|
## Extending the library
|
||||||
|
|
||||||
This library is relatively very small, and can be extended without much hassle.
|
This library is relatively very small, and can be extended without much hassle.
|
||||||
|
@ -1,35 +1,35 @@
|
|||||||
// Standard Allocation
|
// Standard Allocation
|
||||||
#define new static_assert( false, "Banned keyword used: " new )
|
#define new static_assert( false, "Banned keyword used: new" )
|
||||||
#define delete static_assert( false, "Banned keyword used: " delete )
|
#define delete static_assert( false, "Banned keyword used: delete" )
|
||||||
|
|
||||||
// Standard Coroutines
|
// Standard Coroutines
|
||||||
#define co_await static_assert( false, "Banned keyword used: " co_await )
|
#define co_await static_assert( false, "Banned keyword used: co_await" )
|
||||||
#define co_return static_assert( false, "Banned keyword used: " co_return )
|
#define co_return static_assert( false, "Banned keyword used: co_return" )
|
||||||
#define co_yield static_assert( false, "Banned keyword used: " co_yield )
|
#define co_yield static_assert( false, "Banned keyword used: co_yield" )
|
||||||
|
|
||||||
// Standard Exceptions
|
// Standard Exceptions
|
||||||
#define atomic_cancel static_assert( false, "Banned keyword used: " atomic_cancel )
|
#define atomic_cancel static_assert( false, "Banned keyword used: atomic_cancel" )
|
||||||
#define atomic_commit static_assert( false, "Banned keyword used: " atomic_commit )
|
#define atomic_commit static_assert( false, "Banned keyword used: atomic_commit" )
|
||||||
#define atomic_noexcept static_assert( false, "Banned keyword used: " atomic_noexcept )
|
#define atomic_noexcept static_assert( false, "Banned keyword used: atomic_noexcept" )
|
||||||
#define catch static_assert( false, "Banned keyword used: " catch )
|
#define catch static_assert( false, "Banned keyword used: catch" )
|
||||||
#define noexcept static_assert( false, "Banned keyword used: " noexcept )
|
#define noexcept static_assert( false, "Banned keyword used: noexcept" )
|
||||||
#define throw static_assert( false, "Banned keyword used: " throw )
|
#define throw static_assert( false, "Banned keyword used: throw" )
|
||||||
#define try static_assert( false, "Banned keyword used: " try )
|
#define try static_assert( false, "Banned keyword used: try" )
|
||||||
|
|
||||||
// Standard RTTI
|
// Standard RTTI
|
||||||
#define decltype static_assert( false, "Banned keyword used: " decltype )
|
#define decltype static_assert( false, "Banned keyword used: decltype" )
|
||||||
#define reflexpr static_assert( false, "Banned keyword used: " reflexpr )
|
#define reflexpr static_assert( false, "Banned keyword used: reflexpr" )
|
||||||
#define typeid static_assert( false, "Banned keyword used: " typeid )
|
#define typeid static_assert( false, "Banned keyword used: typeid" )
|
||||||
|
|
||||||
// Object-Oriented Dynamic Dispatch
|
// Object-Oriented Dynamic Dispatch
|
||||||
#define final static_assert( false, "Banned keyword used: " final )
|
#define final static_assert( false, "Banned keyword used: final" )
|
||||||
#define override static_assert( false, "Banned keyword used: " override )
|
#define override static_assert( false, "Banned keyword used: override" )
|
||||||
#define virtual static_assert( false, "Banned keyword used: " virtual )
|
#define virtual static_assert( false, "Banned keyword used: virtual" )
|
||||||
|
|
||||||
// Private Access Specifier
|
// Private Access Specifier
|
||||||
#define private static_assert( false, "Banned keyword used: " private )
|
#define private static_assert( false, "Banned keyword used: private" )
|
||||||
|
|
||||||
// Template Meta-programming
|
// Template Meta-programming
|
||||||
#define concept static_assert( false, "Banned keyword used: " concept )
|
#define concept static_assert( false, "Banned keyword used: concept" )
|
||||||
#define requires static_assert( false, "Banned keyword used: " requires )
|
#define requires static_assert( false, "Banned keyword used: requires" )
|
||||||
#define template static_assert( false, "Banned keyword used: " template )
|
#define template static_assert( false, "Banned keyword used: template" )
|
||||||
|
@ -25,15 +25,6 @@
|
|||||||
# define ZPL_MODULE_CORE
|
# define ZPL_MODULE_CORE
|
||||||
# define ZPL_MODULE_TIMER
|
# define ZPL_MODULE_TIMER
|
||||||
# define ZPL_MODULE_HASHING
|
# 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"
|
#include "zpl.h"
|
||||||
|
|
||||||
using zpl::b32;
|
using zpl::b32;
|
||||||
@ -185,6 +176,450 @@ while(0);
|
|||||||
constexpr
|
constexpr
|
||||||
char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
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 region Memory
|
||||||
#pragma endregion Memory
|
#pragma endregion Memory
|
||||||
@ -221,18 +656,21 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
sw Capacity;
|
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;
|
sw length = str ? str_len( str ) : 0;
|
||||||
return make_length( allocator, str, length );
|
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 );
|
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 );
|
constexpr sw header_size = sizeof( Header );
|
||||||
|
|
||||||
@ -254,7 +692,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return result;
|
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 );
|
constexpr sw header_size = sizeof( Header );
|
||||||
|
|
||||||
@ -281,7 +720,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return result;
|
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_list va;
|
||||||
va_start( va, fmt );
|
va_start( va, fmt );
|
||||||
@ -291,7 +731,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return make( allocator, buf );
|
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
|
local_persist thread_local
|
||||||
char buf[ ZPL_PRINTF_MAXLEN ] = { 0 };
|
char buf[ ZPL_PRINTF_MAXLEN ] = { 0 };
|
||||||
@ -304,7 +745,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return make( allocator, buf );
|
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, "" );
|
String result = make( allocator, "" );
|
||||||
|
|
||||||
@ -319,7 +761,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool are_equal( String lhs, String rhs )
|
static
|
||||||
|
bool are_equal( String lhs, String rhs )
|
||||||
{
|
{
|
||||||
if ( lhs.length() != rhs.length() )
|
if ( lhs.length() != rhs.length() )
|
||||||
return false;
|
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
|
String const& operator = ( String const& other ) const
|
||||||
{
|
{
|
||||||
if ( this == & other )
|
if ( this == & other )
|
||||||
@ -532,12 +977,6 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return this_;
|
return this_;
|
||||||
}
|
}
|
||||||
|
|
||||||
String& operator += ( String const& other )
|
|
||||||
{
|
|
||||||
append( other );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
char& operator [] ( sw index )
|
char& operator [] ( sw index )
|
||||||
{
|
{
|
||||||
return Data[ index ];
|
return Data[ index ];
|
||||||
@ -548,7 +987,6 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
|
|||||||
return Data[ index ];
|
return Data[ index ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* Data = nullptr;
|
char* Data = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -581,6 +1019,7 @@ namespace Memory
|
|||||||
void cleanup();
|
void cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
sw log_fmt(char const* fmt, ...)
|
sw log_fmt(char const* fmt, ...)
|
||||||
{
|
{
|
||||||
|
1137
project/gen.cpp
1137
project/gen.cpp
File diff suppressed because it is too large
Load Diff
@ -71,6 +71,7 @@ namespace gen
|
|||||||
Entry( Struct ) \
|
Entry( Struct ) \
|
||||||
Entry( Struct_Fwd ) \
|
Entry( Struct_Fwd ) \
|
||||||
Entry( Struct_Body ) \
|
Entry( Struct_Body ) \
|
||||||
|
Entry( Template ) \
|
||||||
Entry( Typedef ) \
|
Entry( Typedef ) \
|
||||||
Entry( Typename ) \
|
Entry( Typename ) \
|
||||||
Entry( Union ) \
|
Entry( Union ) \
|
||||||
@ -771,7 +772,7 @@ namespace gen
|
|||||||
, Code specifiers = NoCode, Code attributes = NoCode
|
, Code specifiers = NoCode, Code attributes = NoCode
|
||||||
, ModuleFlag mflags = ModuleFlag::None );
|
, 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_specifier( SpecifierT specifier );
|
||||||
|
|
||||||
Code def_struct( StrC name
|
Code def_struct( StrC name
|
||||||
@ -780,6 +781,8 @@ namespace gen
|
|||||||
, Code attributes = NoCode
|
, Code attributes = NoCode
|
||||||
, ModuleFlag mflags = ModuleFlag::None );
|
, 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_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 );
|
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_namespace ( StrC namespace_def );
|
||||||
Code parse_operator ( StrC operator_def );
|
Code parse_operator ( StrC operator_def );
|
||||||
Code parse_struct ( StrC struct_def );
|
Code parse_struct ( StrC struct_def );
|
||||||
|
Code parse_template ( StrC template_def );
|
||||||
Code parse_type ( StrC type_def );
|
Code parse_type ( StrC type_def );
|
||||||
Code parse_typedef ( StrC typedef_def );
|
Code parse_typedef ( StrC typedef_def );
|
||||||
Code parse_union ( StrC union_def );
|
Code parse_union ( StrC union_def );
|
||||||
@ -1050,6 +1054,8 @@ namespace gen
|
|||||||
extern Code t_bool;
|
extern Code t_bool;
|
||||||
extern Code t_char;
|
extern Code t_char;
|
||||||
extern Code t_wchar_t;
|
extern Code t_wchar_t;
|
||||||
|
extern Code t_class;
|
||||||
|
extern Code t_typename;
|
||||||
|
|
||||||
extern Code access_public;
|
extern Code access_public;
|
||||||
extern Code access_protected;
|
extern Code access_protected;
|
||||||
|
@ -114,7 +114,6 @@ Code gen__array( StrC type, sw type_size )
|
|||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
return Data[ header.Num - 1 ];
|
return Data[ header.Num - 1 ];
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code clear = def_function( name(clear), __, t_void
|
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& header = get_header();
|
||||||
header.Num = 0;
|
header.Num = 0;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code fill;
|
Code fill;
|
||||||
@ -155,14 +153,12 @@ Code gen__array( StrC type, sw type_size )
|
|||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
zpl::free( header.Allocator, & header );
|
zpl::free( header.Allocator, & header );
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code get_header = def_function( name(get_header), __, t_header_ref
|
Code get_header = def_function( name(get_header), __, t_header_ref
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
return * ( rcast( Header*, Data ) - 1 );
|
return * ( rcast( Header*, Data ) - 1 );
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code grow = def_function( name(grow), def_param( t_uw, name(min_capacity)), t_bool
|
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(
|
, def_execution( code(
|
||||||
return get_header().Num;
|
return get_header().Num;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code pop = def_function( name(pop), __, t_bool
|
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 );
|
ZPL_ASSERT( header.Num > 0 );
|
||||||
header.Num--;
|
header.Num--;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code remove_at = def_function( name(remove_at), def_param( t_uw, name(idx)), t_void
|
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 ) );
|
mem_move( header + idx, header + idx + 1, sizeof( Type ) * ( header->Num - idx - 1 ) );
|
||||||
header->Num--;
|
header->Num--;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code reserve = def_function( name(reserve), def_param( t_uw, name(new_capacity)), t_bool
|
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 = {} )
|
void gen__array_request( StrC type, sw size, StrC dep = {} )
|
||||||
{
|
{
|
||||||
do_once_start
|
do_once_start
|
||||||
array_init( GenArrayRequests, g_allocator );
|
array_init( GenArrayRequests, Memory::GlobalAllocator );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
// Make sure we don't already have a request for the type.
|
// Make sure we don't already have a request for the type.
|
||||||
|
@ -101,7 +101,6 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
Data[ header.Num ] = value;
|
Data[ header.Num ] = value;
|
||||||
header.Num++;
|
header.Num++;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code appendv;
|
Code appendv;
|
||||||
@ -121,7 +120,6 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
|
|
||||||
header.Num += num;
|
header.Num += num;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +128,6 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
header.Num = 0;
|
header.Num = 0;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code end = def_function( name(end), __, t_type_ref
|
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();
|
Header& header = get_header();
|
||||||
return Data[ header.Num - 1 ];
|
return Data[ header.Num - 1 ];
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code free = def_function( name(free), __, t_void
|
Code free = def_function( name(free), __, t_void
|
||||||
@ -146,21 +142,18 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
zpl::free( header.Backing, & header );
|
zpl::free( header.Backing, & header );
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code get_header = def_function( name(get_header), __, t_header_ref
|
Code get_header = def_function( name(get_header), __, t_header_ref
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
return * ( rcast( Header*, Data ) - 1 );
|
return * ( rcast( Header*, Data ) - 1 );
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code num = def_function( name(num), __, t_sw
|
Code num = def_function( name(num), __, t_sw
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
return get_header().Num;
|
return get_header().Num;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code pop = def_function( name(pop), __, t_type
|
Code pop = def_function( name(pop), __, t_type
|
||||||
@ -169,7 +162,6 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
header.Num--;
|
header.Num--;
|
||||||
return Data[ header.Num ];
|
return Data[ header.Num ];
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code wipe = def_function( name(wipe), __, t_void
|
Code wipe = def_function( name(wipe), __, t_void
|
||||||
@ -178,7 +170,6 @@ Code gen__buffer( StrC type, sw type_size )
|
|||||||
header.Num = 0;
|
header.Num = 0;
|
||||||
mem_set( Data, 0, header.Capacity * sizeof( Type ) );
|
mem_set( Data, 0, header.Capacity * sizeof( Type ) );
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code op_type_ptr = untyped_str( code(
|
Code op_type_ptr = untyped_str( code(
|
||||||
@ -223,7 +214,7 @@ Array(GenBufferRequest) GenBufferRequests;
|
|||||||
void gen__buffer_request( StrC type, sw size, StrC dep = {} )
|
void gen__buffer_request( StrC type, sw size, StrC dep = {} )
|
||||||
{
|
{
|
||||||
do_once_start
|
do_once_start
|
||||||
array_init( GenBufferRequests, g_allocator );
|
array_init( GenBufferRequests, Memory::GlobalAllocator );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
// Make sure we don't already have a request for the type.
|
// Make sure we don't already have a request for the type.
|
||||||
|
@ -90,7 +90,7 @@ Code gen__hashtable( StrC type, sw type_size )
|
|||||||
|
|
||||||
Code clear = def_function( name(clear), __, t_void
|
Code clear = def_function( name(clear), __, t_void
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
if ( s32 idx = 0; idx < Hashes.num(), idx++ )
|
for ( s32 idx = 0; idx < Hashes.num(), idx++ )
|
||||||
Hashes[ idx ] = -1;
|
Hashes[ idx ] = -1;
|
||||||
|
|
||||||
Entries.clear();
|
Entries.clear();
|
||||||
@ -100,11 +100,10 @@ Code gen__hashtable( StrC type, sw type_size )
|
|||||||
Code destroy = def_function( name(destroy), __, t_void
|
Code destroy = def_function( name(destroy), __, t_void
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
if ( Hashes )
|
if ( Hashes )
|
||||||
Hashes .free();
|
Hashes.free();
|
||||||
if ( Entries )
|
if ( Entries )
|
||||||
Entries.free();
|
Entries.free();
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code get = def_function( name(get), def_param( t_u64, name(key)), t_type_ptr
|
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() );
|
sw new_num = array_grow_formula( Entries.num() );
|
||||||
rehash( new_num );
|
rehash( new_num );
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code rehash;
|
Code rehash;
|
||||||
@ -214,7 +212,6 @@ Code gen__hashtable( StrC type, sw type_size )
|
|||||||
new_ht.Entries[ last_added_index ].Value = entry.Value;
|
new_ht.Entries[ last_added_index ].Value = entry.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <type>* old_ht = this;
|
|
||||||
// *this = new_ht;
|
// *this = new_ht;
|
||||||
|
|
||||||
// old_ht.destroy();
|
// old_ht.destroy();
|
||||||
@ -320,7 +317,6 @@ Code gen__hashtable( StrC type, sw type_size )
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code add_entry = def_function( name(add_entry), def_param( t_u64, name(key)), t_sw
|
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 );
|
Entries.append( entry );
|
||||||
return idx;
|
return idx;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code find = def_function( name(find), def_param( t_u64, name(key)), t_find_result
|
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(
|
, def_execution( code(
|
||||||
return 0.75f * Hashes.num() < Entries.num();
|
return 0.75f * Hashes.num() < Entries.num();
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
hashtable = def_struct( name, def_struct_body( 24
|
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 = {} )
|
void gen__hashtable_request( StrC type, sw size, StrC dep = {} )
|
||||||
{
|
{
|
||||||
do_once_start
|
do_once_start
|
||||||
array_init( GenHashTableRequests, g_allocator );
|
array_init( GenHashTableRequests, Memory::GlobalAllocator );
|
||||||
|
|
||||||
gen_array( sw );
|
gen_array( sw );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
@ -80,7 +80,6 @@ Code gen__ring( StrC type, sw type_size )
|
|||||||
if ( Head == Tail )
|
if ( Head == Tail )
|
||||||
Tail = ( Tail + 1 ) % Capacity;
|
Tail = ( Tail + 1 ) % Capacity;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code appendv;
|
Code appendv;
|
||||||
@ -102,21 +101,18 @@ Code gen__ring( StrC type, sw type_size )
|
|||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
return Head == Tail;
|
return Head == Tail;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code free = def_function( name(free), __, t_void
|
Code free = def_function( name(free), __, t_void
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
Buffer.free();
|
Buffer.free();
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code full = def_function( name(full), __, t_bool
|
Code full = def_function( name(full), __, t_bool
|
||||||
, def_execution( code(
|
, def_execution( code(
|
||||||
return (Head + 1) % Capacity == Tail;
|
return (Head + 1) % Capacity == Tail;
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Code get = def_function( name(get), __, t_type_ref
|
Code get = def_function( name(get), __, t_type_ref
|
||||||
@ -134,7 +130,6 @@ Code gen__ring( StrC type, sw type_size )
|
|||||||
Tail = 0;
|
Tail = 0;
|
||||||
Buffer.wipe();
|
Buffer.wipe();
|
||||||
))
|
))
|
||||||
, spec_inline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ring = def_struct( name, def_struct_body( 14,
|
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 = {} )
|
void gen__ring_request( StrC type, sw size, StrC dep = {} )
|
||||||
{
|
{
|
||||||
do_once_start
|
do_once_start
|
||||||
array_init( GenRingRequests, g_allocator );
|
array_init( GenRingRequests, Memory::GlobalAllocator );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
// Make sure we don't already have a request for the type.
|
// Make sure we don't already have a request for the type.
|
||||||
|
@ -78,13 +78,13 @@ Code gen__array( StrC type, sw type_size )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Type& back( void )
|
Type& back( void )
|
||||||
{
|
{
|
||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
return Data[ header.Num - 1 ];
|
return Data[ header.Num - 1 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void clear( void )
|
void clear( void )
|
||||||
{
|
{
|
||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
header.Num = 0;
|
header.Num = 0;
|
||||||
@ -105,13 +105,13 @@ Code gen__array( StrC type, sw type_size )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void free( void )
|
void free( void )
|
||||||
{
|
{
|
||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
zpl::free( header.Allocator, &header );
|
zpl::free( header.Allocator, &header );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Header& get_header( void )
|
Header& get_header( void )
|
||||||
{
|
{
|
||||||
return *( reinterpret_cast< Header* >( Data ) - 1 );
|
return *( reinterpret_cast< Header* >( Data ) - 1 );
|
||||||
}
|
}
|
||||||
@ -127,12 +127,12 @@ Code gen__array( StrC type, sw type_size )
|
|||||||
return set_capacity( new_capacity );
|
return set_capacity( new_capacity );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uw num( void )
|
uw num( void )
|
||||||
{
|
{
|
||||||
return get_header().Num;
|
return get_header().Num;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool pop( void )
|
bool pop( void )
|
||||||
{
|
{
|
||||||
Header& header = get_header();
|
Header& header = get_header();
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ Code gen__array( StrC type, sw type_size )
|
|||||||
header.Num--;
|
header.Num--;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void remove_at( uw idx )
|
void remove_at( uw idx )
|
||||||
{
|
{
|
||||||
Header* header = &get_header();
|
Header* header = &get_header();
|
||||||
ZPL_ASSERT( idx < header->Num );
|
ZPL_ASSERT( idx < header->Num );
|
||||||
@ -233,7 +233,7 @@ Array(GenArrayRequest) GenArrayRequests;
|
|||||||
void gen__array_request( StrC type, sw size, StrC dep = {} )
|
void gen__array_request( StrC type, sw size, StrC dep = {} )
|
||||||
{
|
{
|
||||||
do_once_start
|
do_once_start
|
||||||
array_init( GenArrayRequests, g_allocator );
|
array_init( GenArrayRequests, Memory::GlobalAllocator );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
// Make sure we don't already have a request for the type.
|
// Make sure we don't already have a request for the type.
|
||||||
|
@ -192,7 +192,6 @@ u32 gen_sanity()
|
|||||||
gen_sanity_file.print_fmt("\n");
|
gen_sanity_file.print_fmt("\n");
|
||||||
|
|
||||||
// Specifiers
|
// Specifiers
|
||||||
if (0)
|
|
||||||
{
|
{
|
||||||
Code fwd_fn = parse_function( code(
|
Code fwd_fn = parse_function( code(
|
||||||
inline
|
inline
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
The following tests focus on attempting to generate some math, containers, and the memory module of zpl.
|
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
|
An exmaple of a non-trival generation is a container for elements with SOA or AOS policy for layout.
|
||||||
once the stress test files are complete.
|
(If a unified element syntax is desired)
|
||||||
|
|
||||||
The test is divided between two major sets of tests: Parsed and Nonparsed.
|
The test is divided between two major sets of tests: Parsed and Nonparsed.
|
||||||
|
|
||||||
|
@ -25,5 +25,5 @@ endif
|
|||||||
|
|
||||||
add_project_arguments('-Dgen_time', language : ['c', 'cpp'])
|
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 )
|
executable( 'gencpp_parsed', sources_parsed, include_directories : includes )
|
||||||
|
Loading…
Reference in New Issue
Block a user