C-library gen progress: Header files mostly done, starting dep c impl and fixes to generic selection generation

This commit is contained in:
2024-12-08 16:37:04 -05:00
parent c016e245eb
commit 65c3fabc52
26 changed files with 732 additions and 445 deletions

View File

@ -459,6 +459,7 @@ FileContents file_read_contents( AllocatorInfo a, b32 zero_terminate, char const
return result;
}
typedef struct _memory_fd _memory_fd;
struct _memory_fd
{
u8 magic;
@ -505,7 +506,7 @@ b8 file_stream_new( FileInfo* file, AllocatorInfo allocator )
d->allocator = allocator;
d->flags = EFileStream_CLONE_WRITABLE;
d->cap = 0;
d->buf = array_init<u8>( allocator );
d->buf = array_init( u8, allocator );
if ( ! d->buf )
return false;
@ -531,7 +532,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize
d->flags = flags;
if ( d->flags & EFileStream_CLONE_WRITABLE )
{
Array<u8> arr = array_init_reserve<u8>( allocator, size );
Array(u8) arr = array_init_reserve(u8, allocator, size );
d->buf = arr;
if ( ! d->buf )
@ -608,9 +609,9 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write )
if ( d->flags & EFileStream_CLONE_WRITABLE )
{
Array<u8> arr = { d->buf };
Array(u8) arr = { d->buf };
if ( array_get_header(arr)->Capacity < usize(new_cap) )
if ( array_get_header(arr)->Capacity < scast(usize, new_cap) )
{
if ( ! array_grow( & arr, ( s64 )( new_cap ) ) )
return false;
@ -622,7 +623,7 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write )
if ( ( d->flags & EFileStream_CLONE_WRITABLE ) && extralen > 0 )
{
Array<u8> arr = { d->buf };
Array(u8) arr = { d->buf };
mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen );
d->cap = new_cap;
@ -646,7 +647,7 @@ GEN_FILE_CLOSE_PROC( _memory_file_close )
if ( d->flags & EFileStream_CLONE_WRITABLE )
{
Array<u8> arr = { d->buf };
Array(u8) arr = { d->buf };
array_free(arr);
}

View File

@ -284,14 +284,15 @@
#endif
#if GEN_COMPILER_C
// ------------------------ _Generic function overloading -----------------------------------------
// This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in:
// https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md
// Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unopaque as possible.
// Extensive effort was put in below to make this as easy as possible to understand what is going on with this mess of a preoprocessor.
// Where the signature would be defined using:
#define GEN_TYPE_TO_EXP(type) (* (type*)NULL)
// ____ _ ______ _ _ ____ _ __ _
// / ___} (_) | ____} | | (_) / __ \ | | | |(_)
// | | ___ ___ _ __ ___ _ __ _ ___ | |__ _ _ _ __ ___| |_ _ ___ _ __ | | | |_ _____ _ __ | | ___ __ _ __| | _ _ __ __ _
// | |{__ |/ _ \ '_ \ / _ \ '__} |/ __| | __} | | | '_ \ / __} __} |/ _ \| '_ \ | | | \ \ / / _ \ '_ \| |/ _ \ / _` |/ _` || | '_ \ / _` |
// | |__j | __/ | | | __/ | | | (__ | | | |_| | | | | (__| l_| | (_) | | | | | l__| |\ V / __/ | | | | (_) | (_| | (_| || | | | | (_| |
// \____/ \___}_l l_l\___}_l l_l\___| l_l \__,_l_l l_l\___}\__}_l\___/l_l l_l \____/ \_/ \___}_l l_l_l\___/ \__,_l\__,_l|_|_| |_|\__, |
// This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in: __| |
// https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md {___/
// Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible.
#define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly.
@ -314,25 +315,23 @@
#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , )
// ^ Selects the comma ^ is the type ^ is the function ^ Insert a comma
// The slot won't exist if that comma is not found. |
// |
// This is the same as above but it does not insert a comma V no comma here.
#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ), , )
// Needed for the last slot as they don't allow trailing commas.
// For the occastion where an expression didn't resolve to a selection option the "default: <value>" wilbe set to:
struct NO_RESOLVED_GENERIC_SELECTION {
unsigned long long failure;
};
struct NO_RESOLVED_GENERIC_SELECTION const gen_generic_selection_fail = {};
// Which will provide the message: error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer
// ----------------------------------------------------------------------------------------------------------------------------------
// Below are generated on demand for an overlaod depdendent on a type:
// ----------------------------------------------------------------------------------------------------------------------------------
#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( \
(selector_arg), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_1 ) \
// -----------------------------------------------------------------------------------------------------#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( k
#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( \
(selector_arg), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg )
// ----------------------------------------------------------------------------------------------------------------------------------
@ -355,17 +354,18 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u
// If using an Editor with support for syntax hightlighting macros: HASH__ARGS_SIG_1 and HASH_ARGS_SIG_2 should show color highlighting indicating the slot is enabled,
// or, "defined" for usage during the compilation pass that handles the _Generic instrinsic.
#define hash( function_arguments ) _Generic( \
(function_arguments), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( HASH__ARGS_SIG_8 ) \
#define hash( function_arguments ) _Generic( \
(function_arguments), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_8 ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( function_arguments )
// Additional Variations:
@ -376,7 +376,8 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
... \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_N ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ )
// If the function does not take the arugment as a parameter:
@ -385,9 +386,13 @@ size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761u
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
/* ... */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_N ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(FunctionID__ARGS_SIG_N ) \
default: gen_generic_selection_fail \
) GEN_RESOLVED_FUNCTION_CALL()
// Used to keep the _Generic keyword happy as bare types are not considered "expressions"
#define GEN_TYPE_TO_EXP(type) (* (type*)NULL)
// typedef void* GEN_GenericExampleType;
// GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType );

View File

@ -46,6 +46,7 @@ void const* mem_find( void const* data, u8 c, ssize n )
#define GEN_HEAP_STATS_MAGIC 0xDEADC0DE
typedef struct _heap_stats _heap_stats;
struct _heap_stats
{
u32 magic;
@ -80,6 +81,7 @@ void heap_stats_check( void )
GEN_ASSERT( _heap_stats_info.alloc_count == 0 );
}
typedef struct _heap_alloc_info _heap_alloc_info;
struct _heap_alloc_info
{
ssize size;

View File

@ -33,6 +33,7 @@ enum
GEN_FMT_INTS = GEN_FMT_CHAR | GEN_FMT_SHORT | GEN_FMT_INT | GEN_FMT_LONG | GEN_FMT_LLONG | GEN_FMT_SIZE | GEN_FMT_INTPTR
};
typedef struct _format_info _format_info;
struct _format_info
{
s32 base;
@ -429,7 +430,7 @@ neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_lis
break;
}
String gen_str = String { va_arg( va, char*) };
String gen_str = { va_arg( va, char*) };
info.precision = string_length(gen_str);
len = _print_string( text, remaining, &info, gen_str );

View File

@ -7,17 +7,21 @@
String string_make_length( AllocatorInfo allocator, char const* str, ssize length )
{
constexpr ssize header_size = sizeof( StringHeader );
ssize const header_size = sizeof( StringHeader );
s32 alloc_size = header_size + length + 1;
void* allocation = alloc( allocator, alloc_size );
if ( allocation == nullptr )
return { nullptr };
if ( allocation == nullptr ) {
String null_string = {nullptr};
return null_string;
}
StringHeader&
header = * rcast(StringHeader*, allocation);
header = { allocator, length, length };
StringHeader*
header = rcast(StringHeader*, allocation);
header->Allocator = allocator;
header->Capacity = length;
header->Length = length;
String result = { rcast( char*, allocation) + header_size };
@ -33,14 +37,15 @@ String string_make_length( AllocatorInfo allocator, char const* str, ssize lengt
String string_make_reserve( AllocatorInfo allocator, ssize capacity )
{
constexpr ssize header_size = sizeof( StringHeader );
ssize const header_size = sizeof( StringHeader );
s32 alloc_size = header_size + capacity + 1;
void* allocation = alloc( allocator, alloc_size );
if ( allocation == nullptr )
return { nullptr };
if ( allocation == nullptr ) {
String null_string = {nullptr};
return null_string;
}
mem_set( allocation, 0, alloc_size );
StringHeader*

View File

@ -7,12 +7,12 @@
struct StrC;
StrC to_strc_from_c_str (char const* bad_string);
bool strc_are_equal (StrC lhs, StrC rhs);
char const* strc_back (StrC str);
bool strc_contains (StrC str, StrC substring);
StrC strc_duplicate (StrC str, AllocatorInfo allocator);
b32 strc_starts_with (StrC str, StrC substring);
StrC strc_to_str (char const* bad_string);
StrC strc_visualize_whitespace(StrC str, AllocatorInfo allocator);
// Constant string with length.