gencpp/base/components/interface.cpp

454 lines
15 KiB
C++
Raw Permalink Normal View History

#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "code_serialization.cpp"
#endif
2024-12-07 14:17:02 -08:00
GEN_NS_PARSER_BEGIN
internal void parser_init();
internal void parser_deinit();
2024-12-07 14:17:02 -08:00
GEN_NS_PARSER_END
internal
void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags )
{
Arena* last = array_back(Global_AllocatorBuckets);
switch ( type )
{
case EAllocation_ALLOC:
{
if ( ( last->TotalUsed + size ) > last->TotalSize )
{
Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize );
if ( bucket.PhysicalStart == nullptr )
GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets");
if ( ! array_append( Global_AllocatorBuckets, bucket ) )
GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets");
last = array_back(Global_AllocatorBuckets);
}
return alloc_align( arena_allocator_info(last), size, alignment );
}
case EAllocation_FREE:
{
// Doesn't recycle.
}
break;
case EAllocation_FREE_ALL:
{
// Memory::cleanup instead.
}
break;
case EAllocation_RESIZE:
{
if ( last->TotalUsed + size > last->TotalSize )
{
Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize );
if ( bucket.PhysicalStart == nullptr )
GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets");
if ( ! array_append( Global_AllocatorBuckets, bucket ) )
GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets");
last = array_back(Global_AllocatorBuckets);
}
void* result = alloc_align( last->Backing, size, alignment );
if ( result != nullptr && old_memory != nullptr )
{
mem_copy( result, old_memory, old_size );
}
return result;
}
}
return nullptr;
}
internal
2023-07-24 17:59:20 -07:00
void define_constants()
{
Code_Global = make_code();
Code_Global->Name = get_cached_string( txt("Global Code") );
Code_Global->Content = Code_Global->Name;
2024-12-01 21:03:38 -08:00
Code_Invalid = make_code();
code_set_global(Code_Invalid);
2024-12-03 12:19:39 -08:00
t_empty = (CodeTypename) make_code();
t_empty->Type = CT_Typename;
t_empty->Name = get_cached_string( txt("") );
code_set_global(cast(Code, t_empty));
access_private = make_code();
2024-12-03 12:19:39 -08:00
access_private->Type = CT_Access_Private;
access_private->Name = get_cached_string( txt("private:\n") );
code_set_global(cast(Code, access_private));
access_protected = make_code();
2024-12-03 12:19:39 -08:00
access_protected->Type = CT_Access_Protected;
access_protected->Name = get_cached_string( txt("protected:\n") );
code_set_global(access_protected);
access_public = make_code();
2024-12-03 12:19:39 -08:00
access_public->Type = CT_Access_Public;
access_public->Name = get_cached_string( txt("public:\n") );
code_set_global(access_public);
Str api_export_str = code(GEN_API_Export_Code);
attrib_api_export = def_attributes( api_export_str );
code_set_global(cast(Code, attrib_api_export));
Str api_import_str = code(GEN_API_Import_Code);
attrib_api_import = def_attributes( api_import_str );
code_set_global(cast(Code, attrib_api_import));
module_global_fragment = make_code();
2024-12-03 12:19:39 -08:00
module_global_fragment->Type = CT_Untyped;
module_global_fragment->Name = get_cached_string( txt("module;") );
module_global_fragment->Content = module_global_fragment->Name;
code_set_global(cast(Code, module_global_fragment));
module_private_fragment = make_code();
2024-12-03 12:19:39 -08:00
module_private_fragment->Type = CT_Untyped;
module_private_fragment->Name = get_cached_string( txt("module : private;") );
module_private_fragment->Content = module_private_fragment->Name;
code_set_global(cast(Code, module_private_fragment));
fmt_newline = make_code();
2024-12-03 12:19:39 -08:00
fmt_newline->Type = CT_NewLine;
code_set_global((Code)fmt_newline);
pragma_once = (CodePragma) make_code();
2024-12-03 12:19:39 -08:00
pragma_once->Type = CT_Preprocess_Pragma;
pragma_once->Name = get_cached_string( txt("once") );
pragma_once->Content = pragma_once->Name;
code_set_global((Code)pragma_once);
param_varadic = (CodeParams) make_code();
2024-12-03 12:19:39 -08:00
param_varadic->Type = CT_Parameters;
param_varadic->Name = get_cached_string( txt("...") );
param_varadic->ValueType = t_empty;
code_set_global((Code)param_varadic);
preprocess_else = (CodePreprocessCond) make_code();
2024-12-03 12:19:39 -08:00
preprocess_else->Type = CT_Preprocess_Else;
code_set_global((Code)preprocess_else);
preprocess_endif = (CodePreprocessCond) make_code();
2024-12-03 12:19:39 -08:00
preprocess_endif->Type = CT_Preprocess_EndIf;
code_set_global((Code)preprocess_endif);
Str auto_str = txt("auto"); t_auto = def_type( auto_str ); code_set_global( t_auto );
Str void_str = txt("void"); t_void = def_type( void_str ); code_set_global( t_void );
Str int_str = txt("int"); t_int = def_type( int_str ); code_set_global( t_int );
Str bool_str = txt("bool"); t_bool = def_type( bool_str ); code_set_global( t_bool );
Str char_str = txt("char"); t_char = def_type( char_str ); code_set_global( t_char );
Str wchar_str = txt("wchar_t"); t_wchar_t = def_type( wchar_str ); code_set_global( t_wchar_t );
Str class_str = txt("class"); t_class = def_type( class_str ); code_set_global( t_class );
Str typename_str = txt("typename"); t_typename = def_type( typename_str ); code_set_global( t_typename );
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
t_b32 = def_type( name(b32) ); code_set_global( t_b32 );
Str s8_str = txt("s8"); t_s8 = def_type( s8_str ); code_set_global( t_s8 );
Str s16_str = txt("s16"); t_s16 = def_type( s16_str ); code_set_global( t_s16 );
Str s32_str = txt("s32"); t_s32 = def_type( s32_str ); code_set_global( t_s32 );
Str s64_str = txt("s64"); t_s64 = def_type( s64_str ); code_set_global( t_s64 );
Str u8_str = txt("u8"); t_u8 = def_type( u8_str ); code_set_global( t_u8 );
Str u16_str = txt("u16"); t_u16 = def_type( u16_str ); code_set_global( t_u16 );
Str u32_str = txt("u32"); t_u32 = def_type( u32_str ); code_set_global( t_u32 );
Str u64_str = txt("u64"); t_u64 = def_type( u64_str ); code_set_global( t_u64 );
Str ssize_str = txt("ssize"); t_ssize = def_type( ssize_str ); code_set_global( t_ssize );
Str usize_str = txt("usize"); t_usize = def_type( usize_str ); code_set_global( t_usize );
Str f32_str = txt("f32"); t_f32 = def_type( f32_str ); code_set_global( t_f32 );
Str f64_str = txt("f64"); t_f64 = def_type( f64_str ); code_set_global( t_f64 );
#endif
spec_const = def_specifier( Spec_Const); code_set_global( cast(Code, spec_const ));
spec_consteval = def_specifier( Spec_Consteval); code_set_global( cast(Code, spec_consteval ));;
spec_constexpr = def_specifier( Spec_Constexpr); code_set_global( cast(Code, spec_constexpr ));;
spec_constinit = def_specifier( Spec_Constinit); code_set_global( cast(Code, spec_constinit ));;
spec_extern_linkage = def_specifier( Spec_External_Linkage); code_set_global( cast(Code, spec_extern_linkage ));;
spec_final = def_specifier( Spec_Final); code_set_global( cast(Code, spec_final ));;
spec_forceinline = def_specifier( Spec_ForceInline); code_set_global( cast(Code, spec_forceinline ));;
spec_global = def_specifier( Spec_Global); code_set_global( cast(Code, spec_global ));;
spec_inline = def_specifier( Spec_Inline); code_set_global( cast(Code, spec_inline ));;
spec_internal_linkage = def_specifier( Spec_Internal_Linkage); code_set_global( cast(Code, spec_internal_linkage ));;
spec_local_persist = def_specifier( Spec_Local_Persist); code_set_global( cast(Code, spec_local_persist ));;
spec_mutable = def_specifier( Spec_Mutable); code_set_global( cast(Code, spec_mutable ));;
spec_neverinline = def_specifier( Spec_NeverInline); code_set_global( cast(Code, spec_neverinline ));;
spec_noexcept = def_specifier( Spec_NoExceptions); code_set_global( cast(Code, spec_noexcept ));;
spec_override = def_specifier( Spec_Override); code_set_global( cast(Code, spec_override ));;
spec_ptr = def_specifier( Spec_Ptr); code_set_global( cast(Code, spec_ptr ));;
spec_pure = def_specifier( Spec_Pure); code_set_global( cast(Code, spec_pure ));
spec_ref = def_specifier( Spec_Ref); code_set_global( cast(Code, spec_ref ));;
spec_register = def_specifier( Spec_Register); code_set_global( cast(Code, spec_register ));;
spec_rvalue = def_specifier( Spec_RValue); code_set_global( cast(Code, spec_rvalue ));;
spec_static_member = def_specifier( Spec_Static); code_set_global( cast(Code, spec_static_member ));;
spec_thread_local = def_specifier( Spec_Thread_Local); code_set_global( cast(Code, spec_thread_local ));;
spec_virtual = def_specifier( Spec_Virtual); code_set_global( cast(Code, spec_virtual ));;
spec_volatile = def_specifier( Spec_Volatile); code_set_global( cast(Code, spec_volatile ));
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
code_set_global(cast(Code, spec_local_persist));
if (enum_underlying_sig.Len == 0) {
enum_underlying_sig = txt("enum_underlying(");
}
array_append(PreprocessorDefines, enum_underlying_sig);
# undef def_constant_spec
}
void init()
{
// Setup global allocator
{
AllocatorInfo becasue_C = { & Global_Allocator_Proc, nullptr };
GlobalAllocator = becasue_C;
Global_AllocatorBuckets = array_init_reserve(Arena, heap(), 128 );
if ( Global_AllocatorBuckets == nullptr )
GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets");
Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize );
if ( bucket.PhysicalStart == nullptr )
GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets");
array_append( Global_AllocatorBuckets, bucket );
}
2024-12-08 20:10:10 -08:00
if (Allocator_DataArrays.Proc == nullptr) {
2024-12-10 16:31:50 -08:00
Allocator_DataArrays = GlobalAllocator;
2024-12-08 20:10:10 -08:00
}
if (Allocator_CodePool.Proc == nullptr ) {
2024-12-10 16:31:50 -08:00
Allocator_CodePool = GlobalAllocator;
2024-12-08 20:10:10 -08:00
}
if (Allocator_Lexer.Proc == nullptr) {
2024-12-10 16:31:50 -08:00
Allocator_Lexer = GlobalAllocator;
2024-12-08 20:10:10 -08:00
}
if (Allocator_StringArena.Proc == nullptr) {
2024-12-10 16:31:50 -08:00
Allocator_StringArena = GlobalAllocator;
2024-12-08 20:10:10 -08:00
}
if (Allocator_StringTable.Proc == nullptr) {
2024-12-10 16:31:50 -08:00
Allocator_StringTable = GlobalAllocator;
2024-12-08 20:10:10 -08:00
}
if (Allocator_TypeTable.Proc == nullptr) {
2024-12-10 16:31:50 -08:00
Allocator_TypeTable = GlobalAllocator;
2024-12-08 20:10:10 -08:00
}
// Setup the arrays
{
CodePools = array_init_reserve(Pool, Allocator_DataArrays, InitSize_DataArrays );
if ( CodePools == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the CodePools array" );
StringArenas = array_init_reserve(Arena, Allocator_DataArrays, InitSize_DataArrays );
if ( StringArenas == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" );
}
// Setup the code pool and code entries arena.
{
Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) );
if ( code_pool.PhysicalStart == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the code pool" );
array_append( CodePools, code_pool );
LexArena = arena_init_from_allocator( Allocator_Lexer, LexAllocator_Size );
Arena strbuilder_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena );
if ( strbuilder_arena.PhysicalStart == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the string arena" );
array_append( StringArenas, strbuilder_arena );
}
// Setup the hash tables
{
StringCache = hashtable_init(StringCached, Allocator_StringTable);
if ( StringCache.Entries == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the StringCache");
}
// Preprocessor Defines
PreprocessorDefines = array_init_reserve(StringCached, GlobalAllocator, kilobytes(1) );
define_constants();
GEN_NS_PARSER parser_init();
}
void deinit()
{
usize index = 0;
usize left = array_num(CodePools);
do
{
Pool* code_pool = & CodePools[index];
pool_free(code_pool);
index++;
}
while ( left--, left );
index = 0;
left = array_num(StringArenas);
do
{
Arena* strbuilder_arena = & StringArenas[index];
arena_free(strbuilder_arena);
index++;
}
while ( left--, left );
hashtable_destroy(StringCache);
array_free( CodePools);
array_free( StringArenas);
arena_free(& LexArena);
array_free(PreprocessorDefines);
index = 0;
left = array_num(Global_AllocatorBuckets);
do
{
Arena* bucket = & Global_AllocatorBuckets[ index ];
arena_free(bucket);
index++;
}
while ( left--, left );
array_free(Global_AllocatorBuckets);
GEN_NS_PARSER parser_deinit();
}
void reset()
{
s32 index = 0;
s32 left = array_num(CodePools);
do
{
Pool* code_pool = & CodePools[index];
2024-12-04 08:30:54 -08:00
pool_clear(code_pool);
index++;
}
while ( left--, left );
index = 0;
left = array_num(StringArenas);
do
{
Arena* strbuilder_arena = & StringArenas[index];
strbuilder_arena->TotalUsed = 0;;
index++;
}
while ( left--, left );
hashtable_clear(StringCache);
define_constants();
}
AllocatorInfo get_strbuilder_allocator( s32 c_str_length )
{
Arena* last = array_back(StringArenas);
usize size_req = c_str_length + sizeof(StrBuilderHeader) + sizeof(char*);
if ( last->TotalUsed + scast(ssize, size_req) > last->TotalSize )
{
Arena new_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena );
if ( ! array_append( StringArenas, new_arena ) )
GEN_FATAL( "gen::get_strbuilder_allocator: Failed to allocate a new string arena" );
last = array_back(StringArenas);
}
return arena_allocator_info(last);
}
// Will either make or retrive a code string.
StringCached get_cached_string( Str str )
{
s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len;
u64 key = crc32( str.Ptr, hash_length );
{
StringCached* result = hashtable_get(StringCache, key );
if ( result )
return * result;
}
Str result = strbuilder_to_str( strbuilder_make_str( get_strbuilder_allocator( str.Len ), str ));
hashtable_set(StringCache, key, result );
return result;
}
// Used internally to retireve a Code object form the CodePool.
Code make_code()
{
Pool* allocator = array_back( CodePools);
if ( allocator->FreeList == nullptr )
{
Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) );
if ( code_pool.PhysicalStart == nullptr )
GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." );
if ( ! array_append( CodePools, code_pool ) )
GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." );
allocator = array_back( CodePools);
}
Code result = { rcast( AST*, alloc( pool_allocator_info(allocator), sizeof(AST) )) };
mem_set( rcast(void*, cast(AST*, result)), 0, sizeof(AST) );
return result;
}
void set_allocator_data_arrays( AllocatorInfo allocator )
{
Allocator_DataArrays = allocator;
}
void set_allocator_code_pool( AllocatorInfo allocator )
{
Allocator_CodePool = allocator;
}
void set_allocator_lexer( AllocatorInfo allocator )
{
Allocator_Lexer = allocator;
}
void set_allocator_strbuilder_arena( AllocatorInfo allocator )
{
Allocator_StringArena = allocator;
}
void set_allocator_strbuilder_table( AllocatorInfo allocator )
{
Allocator_StringArena = allocator;
}