Parsing constructors passed the sanity test!

This commit is contained in:
2023-07-10 22:14:41 -04:00
parent ed6a1d0f95
commit 14568d512e
19 changed files with 1296 additions and 491 deletions

View File

@ -2,6 +2,165 @@
#include "Bloat.hpp"
void* gen_Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags )
{
gen_Arena* arena = rcast(gen_Arena*, allocator_data);
void* ptr = NULL;
// unused( old_size );
switch ( type )
{
case EAllocation_ALLOC :
{
void* end = pointer_add( arena->PhysicalStart, arena->TotalUsed );
sw total_size = align_forward_i64( size, alignment );
// NOTE: Out of memory
if ( arena->TotalUsed + total_size > (sw) arena->TotalSize )
{
// zpl__printf_err("%s", "Arena out of memory\n");
return nullptr;
}
ptr = align_forward( end, alignment );
arena->TotalUsed += total_size;
if ( flags & ZPL_ALLOCATOR_FLAG_CLEAR_TO_ZERO )
zero_size( ptr, size );
}
break;
case EAllocation_FREE :
// NOTE: Free all at once
// Use Temp_Arena_Memory if you want to free a block
break;
case EAllocation_FREE_ALL :
arena->TotalUsed = 0;
break;
case EAllocation_RESIZE :
{
// TODO : Check if ptr is on top of stack and just extend
AllocatorInfo a = arena->Backing;
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
}
break;
}
return ptr;
}
void* gen_Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags )
{
gen_Pool* pool = zpl_cast( gen_Pool* ) allocator_data;
void* ptr = NULL;
// unused( old_size );
switch ( type )
{
case EAllocation_ALLOC :
{
uptr next_free;
ZPL_ASSERT( size == pool->BlockSize );
ZPL_ASSERT( alignment == pool->BlockAlign );
ZPL_ASSERT( pool->FreeList != NULL );
next_free = *zpl_cast( uptr* ) pool->FreeList;
ptr = pool->FreeList;
pool->FreeList = zpl_cast( void* ) next_free;
pool->TotalSize += pool->BlockSize;
if ( flags & ZPL_ALLOCATOR_FLAG_CLEAR_TO_ZERO )
zero_size( ptr, size );
}
break;
case EAllocation_FREE :
{
uptr* next;
if ( old_memory == NULL )
return NULL;
next = zpl_cast( uptr* ) old_memory;
*next = zpl_cast( uptr ) pool->FreeList;
pool->FreeList = old_memory;
pool->TotalSize -= pool->BlockSize;
}
break;
case EAllocation_FREE_ALL :
{
sw actual_block_size, block_index;
void* curr;
uptr* end;
actual_block_size = pool->BlockSize + pool->BlockAlign;
pool->TotalSize = 0;
// NOTE: Init intrusive freelist
curr = pool->PhysicalStart;
for ( block_index = 0; block_index < pool->NumBlocks - 1; block_index++ )
{
uptr* next = zpl_cast( uptr* ) curr;
*next = zpl_cast( uptr ) curr + actual_block_size;
curr = pointer_add( curr, actual_block_size );
}
end = zpl_cast( uptr* ) curr;
*end = zpl_cast( uptr ) NULL;
pool->FreeList = pool->PhysicalStart;
}
break;
case EAllocation_RESIZE :
// NOTE: Cannot resize
ZPL_PANIC( "You cannot resize something allocated by with a pool." );
break;
}
return ptr;
}
gen_Pool gen_Pool::init_align( AllocatorInfo backing, sw num_blocks, sw block_size, sw block_align )
{
gen_Pool pool = {};
sw actual_block_size, pool_size, block_index;
void *data, *curr;
uptr* end;
pool.Backing = backing;
pool.BlockSize = block_size;
pool.BlockAlign = block_align;
pool.NumBlocks = num_blocks;
actual_block_size = block_size + block_align;
pool_size = num_blocks * actual_block_size;
data = alloc_align( backing, pool_size, block_align );
// NOTE: Init intrusive freelist
curr = data;
for ( block_index = 0; block_index < num_blocks - 1; block_index++ )
{
uptr* next = ( uptr* ) curr;
*next = ( uptr ) curr + actual_block_size;
curr = pointer_add( curr, actual_block_size );
}
end = ( uptr* ) curr;
*end = ( uptr ) 0;
pool.PhysicalStart = data;
pool.FreeList = data;
return pool;
}
namespace Memory
{
using namespace zpl;
@ -16,7 +175,7 @@ namespace Memory
switch ( type )
{
case EAllocationALLOC:
case EAllocation_ALLOC:
{
if ( last->total_allocated + size > last->total_size )
{
@ -34,15 +193,15 @@ namespace Memory
return alloc_align( arena_allocator( last), size, alignment );
}
case EAllocationFREE:
case EAllocation_FREE:
{
// Doesn't recycle.
}
case EAllocationFREE_ALL:
case EAllocation_FREE_ALL:
{
// Memory::cleanup instead.
}
case EAllocationRESIZE:
case EAllocation_RESIZE:
{
if ( last->total_allocated + size > last->total_size )
{

View File

@ -40,6 +40,7 @@ using zpl::sw;
using zpl::sptr;
using zpl::uptr;
using zpl::AllocType;
using zpl::Arena;
using zpl::AllocatorInfo;
using zpl::ArrayHeader;
@ -48,9 +49,17 @@ using zpl::FileError;
using zpl::Pool;
// using zpl::String;
using zpl::EAllocation_ALLOC;
using zpl::EAllocation_FREE;
using zpl::EAllocation_FREE_ALL;
using zpl::EAllocation_RESIZE;
using zpl::EFileMode_WRITE;
using zpl::EFileError_NONE;
using zpl::ZPL_ALLOCATOR_FLAG_CLEAR_TO_ZERO;
using zpl::align_forward;
using zpl::align_forward_i64;
using zpl::alloc;
using zpl::alloc_align;
using zpl::arena_allocator;
@ -58,7 +67,6 @@ using zpl::arena_init_from_memory;
using zpl::arena_init_from_allocator;
using zpl::arena_free;
using zpl::assert_crash;
using zpl::str_fmt_buf;
using zpl::char_first_occurence;
using zpl::char_is_alpha;
using zpl::char_is_alphanumeric;
@ -67,19 +75,23 @@ using zpl::char_is_hex_digit;
using zpl::char_is_space;
using zpl::crc32;
using zpl::free_all;
using zpl::is_power_of_two;
using zpl::mem_copy;
using zpl::mem_move;
using zpl::mem_set;
using zpl::pointer_add;
using zpl::pool_allocator;
using zpl::pool_init;
using zpl::pool_free;
using zpl::process_exit;
using zpl::str_compare;
using zpl::str_copy;
using zpl::str_fmt_buf;
using zpl::str_fmt_va;
using zpl::str_fmt_out_va;
using zpl::str_fmt_out_err_va;
using zpl::str_compare;
using zpl::str_len;
using zpl::zero_size;
#if __clang__
# pragma clang diagnostic pop
@ -141,14 +153,13 @@ using zpl::str_len;
#define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Type_, Field_, Mask_ ) ( (Type_(Mask_) & Type_(Field_)) == Type_(Mask_) )
#define forceinline ZPL_ALWAYS_INLINE
#define print_nl( _) zpl_printf("\n")
#define ccast( Type_, Value_ ) * const_cast< Type_* >( & (Value_) )
#define scast( Type_, Value_ ) static_cast< Type_ >( Value_ )
#define rcast( Type_, Value_ ) reinterpret_cast< Type_ >( Value_ )
#define pcast( Type_, Value_ ) ( * (Type_*)( & (Value_) ) )
#define txt_impl( ... ) #__VA_ARGS__
#define txt( ... ) txt_impl( __VA_ARGS__ )
#define txt_n_len( ... ) sizeof( txt_impl( __VA_ARGS__ ) ), txt_impl( __VA_ARGS__ )
#define GEN_STRINGIZE_VA( ... ) #__VA_ARGS__
#define txt( ... ) GEN_STRINGIZE_VA( __VA_ARGS__ )
#define txt_to_StrC( ... ) sizeof( GEN_STRINGIZE_VA( __VA_ARGS__ ) ), GEN_STRINGIZE_VA( __VA_ARGS__ )
#define do_once() \
do \
{ \
@ -176,10 +187,127 @@ while(0);
constexpr
char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
#pragma region Memory
// TODO : Use it.
struct gen_Arena
{
static
void* allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags );
static
gen_Arena init_from_memory( void* start, sw size )
{
return
{
{ nullptr, nullptr },
start,
size,
0,
0
};
}
static
gen_Arena init_from_allocator( AllocatorInfo backing, sw size )
{
gen_Arena result =
{
backing,
alloc( backing, size),
size,
0,
0
};
return result;
}
static
gen_Arena init_sub( gen_Arena& parent, sw size )
{
return init_from_allocator( parent.Backing, size );
}
sw alignment_of( sw alignment )
{
sw alignment_offset, result_pointer, mask;
ZPL_ASSERT( is_power_of_two( alignment ) );
alignment_offset = 0;
result_pointer = (sw) PhysicalStart + TotalUsed;
mask = alignment - 1;
if ( result_pointer & mask )
alignment_offset = alignment - ( result_pointer & mask );
return alignment_offset;
}
void check()
{
ZPL_ASSERT( TempCount == 0 );
}
void free()
{
if ( Backing.proc )
{
zpl::free( Backing, PhysicalStart );
PhysicalStart = nullptr;
}
}
sw size_remaining( sw alignment )
{
sw result = TotalSize - ( TotalUsed + alignment_of( alignment ) );
return result;
}
AllocatorInfo Backing;
void* PhysicalStart;
sw TotalSize;
sw TotalUsed;
sw TempCount;
};
struct gen_Pool
{
static
void* allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags );
static
gen_Pool init( AllocatorInfo backing, sw num_blocks, sw block_size )
{
return init_align( backing, num_blocks, block_size, ZPL_DEFAULT_MEMORY_ALIGNMENT );
}
static
gen_Pool init_align( AllocatorInfo backing, sw num_blocks, sw block_size, sw block_align );
void free()
{
if ( Backing.proc )
{
zpl::free( Backing, PhysicalStart );
}
}
AllocatorInfo Backing;
void* PhysicalStart;
void* FreeList;
sw BlockSize;
sw BlockAlign;
sw TotalSize;
sw NumBlocks;
};
#pragma endregion Memory
#pragma region Containers
#pragma push_macro("template")
#undef template
// TODO : Use it.
template<class Type>
struct TArray
{
@ -191,13 +319,13 @@ struct TArray
};
static
TArray<Type> init( AllocatorInfo allocator )
TArray init( AllocatorInfo allocator )
{
return init_reserve( allocator, grow_formula(0) );
}
static
TArray<Type> init_reserve( AllocatorInfo allocator, sw capacity )
TArray init_reserve( AllocatorInfo allocator, sw capacity )
{
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) ));
@ -369,6 +497,7 @@ struct TArray
}
};
// TODO : Use it.
template<typename Type>
struct THashTable
{
@ -387,7 +516,7 @@ struct THashTable
};
static
THashTable<Type> init( AllocatorInfo allocator )
THashTable init( AllocatorInfo allocator )
{
THashTable<Type> result = {0};
@ -621,9 +750,6 @@ protected:
#pragma pop_macro("template")
#pragma endregion Containers
#pragma region Memory
#pragma endregion Memory
#pragma region String
// Constant string with length.
struct StrC

File diff suppressed because it is too large Load Diff

View File

@ -65,6 +65,8 @@ namespace gen
Entry( Operator_Fwd ) \
Entry( Operator_Member ) \
Entry( Operator_Member_Fwd ) \
Entry( Operator_Cast ) \
Entry( Operator_Cast_Fwd ) \
Entry( Parameters ) \
Entry( Preprocessor_Include ) \
Entry( Specifiers ) \
@ -95,7 +97,7 @@ namespace gen
{
static
StrC lookup[Num_Types] = {
# define Entry( Type ) { txt_n_len( Type ) },
# define Entry( Type ) { txt_to_StrC( Type ) },
Define_Types
# undef Entry
};
@ -132,11 +134,11 @@ namespace gen
Entry( Assign, = ) \
Entry( Assign_Add, += ) \
Entry( Assign_Subtract, -= ) \
Entry( Assgin_Multiply, *= ) \
Entry( Assgin_Divide, /= ) \
Entry( Assgin_Modulo, %= ) \
Entry( Assgin_BAnd, &= ) \
Entry( Assgin_BOr, |= ) \
Entry( Assign_Multiply, *= ) \
Entry( Assign_Divide, /= ) \
Entry( Assign_Modulo, %= ) \
Entry( Assign_BAnd, &= ) \
Entry( Assign_BOr, |= ) \
Entry( Assign_BXOr, ^= ) \
Entry( Assign_LShift, <<= ) \
Entry( Assign_RShift, >>= ) \
@ -144,6 +146,7 @@ namespace gen
Entry( Decrement, -- ) \
Entry( Unary_Plus, + ) \
Entry( Unary_Minus, - ) \
Entry( UnaryNot, ! ) \
Entry( Add, + ) \
Entry( Subtract, - ) \
Entry( Multiply, * ) \
@ -155,11 +158,10 @@ namespace gen
Entry( BXOr, ^ ) \
Entry( LShift, << ) \
Entry( RShift, >> ) \
Entry( LNot, ! ) \
Entry( LAnd, && ) \
Entry( LOr, || ) \
Entry( Equals, == ) \
Entry( NotEquals, != ) \
Entry( LEqual, == ) \
Entry( LNot, != ) \
Entry( Lesser, < ) \
Entry( Greater, > ) \
Entry( LesserEqual, <= ) \
@ -250,7 +252,7 @@ namespace gen
# define internal internal
# define local_persist local_persist
# define Entry( Spec_, Code_ ) { txt_n_len(Code_) },
# define Entry( Spec_, Code_ ) { txt_to_StrC(Code_) },
Define_Specifiers
# undef Entry
@ -272,7 +274,9 @@ namespace gen
{
StrC enum_str = to_str( (Type)index );
keymap[index] = crc32( enum_str.Ptr, enum_str.Len);
// We subtract 1 to remove the null terminator
// This is because the tokens lexed are not null terminated.
keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1);
}
do_once_end
@ -398,7 +402,6 @@ namespace gen
# pragma region Member Functions
void add_entry( AST* other );
inline
AST* body()
{
return entry( 0 );
@ -411,22 +414,18 @@ namespace gen
return DynamicEntries ? ArrDyn[ idx ] : ArrStatic[ idx ];
}
inline
bool has_entries()
{
return num_entries();
}
inline
bool is_invalid()
{
return Type != ECode::Invalid;
}
inline
bool is_equal( AST* other );
inline
s32 num_entries()
{
return DynamicEntries ? array_count( ArrDyn ) : StaticIndex;
@ -434,7 +433,6 @@ namespace gen
// Parameter
inline
AST* get_param( s32 index )
{
if ( index <= 0 )
@ -443,14 +441,12 @@ namespace gen
return entry( index + 1 );
}
inline
s32 param_count()
{
// The first entry (which holds the type) represents the first parameter.
return num_entries();
}
inline
AST* param_type()
{
return entry( 0 );
@ -458,7 +454,6 @@ namespace gen
// Specifiers
inline
bool add_specifier( SpecifierT spec )
{
if ( StaticIndex == AST::ArrSpecs_Cap )
@ -472,7 +467,6 @@ namespace gen
return true;
}
inline
s32 has_specifier( SpecifierT spec )
{
for ( s32 idx = 0; idx < StaticIndex; idx++ )
@ -486,21 +480,18 @@ namespace gen
// Typename
inline
bool typename_is_ptr()
{
assert_crash("not implemented");
return false;
}
inline
bool typename_is_ref()
{
assert_crash("not implemented");
return false;
}
inline
AST* typename_specifiers()
{
return entry( 0 );
@ -508,7 +499,6 @@ namespace gen
// Serialization
inline
char const* debug_str()
{
char const* fmt = txt(
@ -530,7 +520,6 @@ namespace gen
);
}
inline
char const* type_str()
{
return ECode::to_str( Type );
@ -582,9 +571,6 @@ namespace gen
# undef Using_CodePOD
};
constexpr sw size_AST = sizeof(AST);
constexpr sw size_POD = sizeof(AST_POD);
// Its intended for the AST to have equivalent size to its POD.
// All extra functionality within the AST namespace should just be syntatic sugar.
static_assert( sizeof(AST) == sizeof(AST_POD), "ERROR: AST IS NOT POD" );
@ -604,7 +590,6 @@ namespace gen
# pragma endregion Statics
# pragma region Member Functions
inline
Code body()
{
if ( ast == nullptr )
@ -622,13 +607,11 @@ namespace gen
return { ast->body() };
}
inline
String to_string() const
{
return ast->to_string();
}
inline
void set_global()
{
if ( ast == nullptr )
@ -640,45 +623,34 @@ namespace gen
ast->Parent = Global.ast;
}
inline
operator bool() const
bool is_valid()
{
return ast;
// 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;
}
inline
bool operator ==( Code other )
{
return ast == other.ast;
}
inline
bool operator !=( Code other )
{
return ast != other.ast;
}
inline
operator AST*()
{
return ast;
}
inline
Code& operator=( Code other )
{
if ( other.ast == nullptr )
{
log_failure("Attempted to assign a nullptr!");
return *this;
}
ast = other.ast;
return *this;
}
inline
AST* operator->()
{
if ( ast == nullptr )
@ -732,12 +704,12 @@ namespace gen
// Set these before calling gen's init() procedure.
// Data
void set_allocator_data_arrays ( AllocatorInfo data_array_allocator );
void set_allocator_code_pool ( AllocatorInfo pool_allocator );
void set_allocator_code_enries_arena( AllocatorInfo pool_allocator );
void set_allocator_string_arena ( AllocatorInfo string_allocator );
void set_allocator_string_table ( AllocatorInfo string_allocator );
void set_allocator_type_table ( AllocatorInfo type_reg_allocator );
void set_allocator_data_arrays ( AllocatorInfo data_array_allocator );
void set_allocator_code_pool ( AllocatorInfo pool_allocator );
void set_allocator_code_enrties_arena( AllocatorInfo pool_allocator );
void set_allocator_string_arena ( AllocatorInfo string_allocator );
void set_allocator_string_table ( AllocatorInfo string_allocator );
void set_allocator_type_table ( AllocatorInfo type_reg_allocator );
# pragma region Upfront
Code def_attributes( StrC content );
@ -772,6 +744,8 @@ namespace gen
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_operator_cast( Code type, Code body = NoCode );
Code def_param ( Code type, StrC name, Code value = NoCode );
Code def_specifier( SpecifierT specifier );
@ -824,22 +798,23 @@ namespace gen
# pragma region Parsing
# ifdef GEN_FEATURE_PARSING
Code parse_class ( StrC class_def );
Code parse_enum ( StrC enum_def );
Code parse_export_body ( StrC export_def );
Code parse_extern_link ( StrC exten_link_def);
Code parse_friend ( StrC friend_def );
Code parse_function ( StrC fn_def );
Code parse_global_body ( StrC body_def );
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 );
Code parse_using ( StrC using_def );
Code parse_variable ( StrC var_def );
Code parse_class ( StrC class_def );
Code parse_enum ( StrC enum_def );
Code parse_export_body ( StrC export_def );
Code parse_extern_link ( StrC exten_link_def);
Code parse_friend ( StrC friend_def );
Code parse_function ( StrC fn_def );
Code parse_global_body ( StrC body_def );
Code parse_namespace ( StrC namespace_def );
Code parse_operator ( StrC operator_def );
Code parse_operator_cast( 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 );
Code parse_using ( StrC using_def );
Code parse_variable ( StrC var_def );
# endif
# pragma endregion Parsing
@ -994,10 +969,10 @@ namespace gen
// Convienence for defining any name used with the gen api.
// Lets you provide the length and string literal to the functions without the need for the DSL.
# define name( Id_ ) { txt_n_len( Id_ ) }
# define name( Id_ ) { txt_to_StrC( Id_ ) }
// Same as name just used to indicate intention of literal for code instead of names.
# define code( ... ) { txt_n_len( __VA_ARGS__ ) }
# define code( ... ) { txt_to_StrC( __VA_ARGS__ ) }
#pragma endregion Macros
#pragma region Constants

View File

@ -0,0 +1,28 @@
#if gen_time
// This undefines the macros used by the gen library but are not necessary for the user.
// TODO : This is incomplete until all dependencies are brough in from ZPL into bloat.
#undef bit
#undef bitfield_is_equal
#undef ccast
#undef scast
#undef rcast
#undef pcast
#undef do_once
#undef do_once_start
#undef do_once_end
#undef kilobytes
#undef megabytes
#undef gigabytes
#undef terabytes
#undef global
#undef internal
#undef local_persist
#undef forceinline
#undef txt
// gen_time
#endif