WIP: Converting api to use custom String types

This commit is contained in:
Edward R. Gonzalez 2023-05-06 15:49:43 -04:00
parent e8264c560f
commit e34b3694da
5 changed files with 815 additions and 328 deletions

View File

@ -54,7 +54,7 @@ using zpl::ArrayHeader;
using zpl::FileInfo;
using zpl::FileError;
using zpl::Pool;
using zpl::String;
// using zpl::String;
using zpl::EFileMode_WRITE;
using zpl::EFileError_NONE;
@ -77,6 +77,7 @@ using zpl::pool_allocator;
using zpl::pool_init;
using zpl::pool_free;
using zpl::process_exit;
using zpl::str_copy;
using zpl::str_fmt_out_va;
using zpl::str_fmt_out_err_va;
using zpl::str_compare;
@ -188,7 +189,25 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
#pragma endregion Memory
#pragma region String
#if 0
#if 1
// Constant string with length.
struct StrC
{
sw Len;
char const* Ptr;
static StrC from( char const* str )
{
return { str_len( str ), str };
}
operator char const* () const
{
return Ptr;
}
};
// Dynamic String
struct String
{
struct Header
@ -238,10 +257,12 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
void append( char c );
void append( char const* str );
void append( char const* str, sw length );
void append( StrC str);
void append( const String other );
void append( char const* fmt, ... );
void append( const String other );
void append_fmt( char const* fmt, ... );
sw avail_space();
sw capacity();
@ -251,13 +272,67 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
void free();
Header& header();
Header& get_headder()
{
return pcast( Header, Data[ - sizeof( Header ) ] );
}
sw length();
sw length() const;
void trim( char const* cut_set );
void trim_space();
operator bool()
{
return Data;
}
operator char* ()
{
return Data;
}
operator char const* () const
{
return Data;
}
operator StrC()
{
return
{
length(),
Data
};
}
String const& operator = ( String const& other ) const
{
if ( this == & other )
return *this;
String& this_ = ccast( String, *this );
this_.Data = other.Data;
return this_;
}
String& operator += ( String const& other )
{
append( other );
return *this;
}
char& operator [] ( sw index )
{
return Data[ index ];
}
char const& operator [] ( sw index ) const
{
return Data[ index ];
}
char* Data = nullptr;
};
@ -287,7 +362,7 @@ namespace Memory
}
inline
sw log_fmt(char const *fmt, ...)
sw log_fmt(char const* fmt, ...)
{
sw res;
va_list va;
@ -300,7 +375,7 @@ sw log_fmt(char const *fmt, ...)
}
inline
sw fatal(char const *fmt, ...)
sw fatal(char const* fmt, ...)
{
local_persist thread_local
char buf[ZPL_PRINTF_MAXLEN] = { 0 };

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@
#include "Bloat.hpp"
// Temporarily here for debugging purposes.
#define GEN_DEFINE_DSL
// #define GEN_DEFINE_DSL
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
// #define GEN_DONT_USE_FATAL
#define GEN_ENFORCE_READONLY_AST
@ -94,11 +94,11 @@ namespace gen
};
inline
char const* to_str( Type type )
StrC to_str( Type type )
{
static
char const* lookup[Num_Types] = {
# define Entry( Type ) txt( Type ),
StrC lookup[Num_Types] = {
# define Entry( Type ) { txt_n_len( Type ) },
Define_Types
# undef Entry
};
@ -248,11 +248,11 @@ namespace gen
// Specifier to string
inline
char const* to_str( Type specifier )
StrC to_str( Type specifier )
{
local_persist
char const* lookup[ Num_Specifiers ] = {
# define Entry( Spec_, Code_ ) txt(Code_),
StrC lookup[ Num_Specifiers ] = {
# define Entry( Spec_, Code_ ) { txt_n_len(Code_) },
Define_Specifiers
# undef Entry
};
@ -261,20 +261,20 @@ namespace gen
}
inline
Type to_type( char const* str, s32 length )
Type to_type( StrC str )
{
local_persist
u32 keymap[ Num_Specifiers ];
do_once_start
for ( u32 index = 0; index < Num_Specifiers; index++ )
{
char const* enum_str = to_str( (Type)index );
StrC enum_str = to_str( (Type)index );
keymap[index] = crc32( enum_str, str_len(enum_str, 42) );
keymap[index] = crc32( enum_str.Ptr, enum_str.Len);
}
do_once_end
u32 hash = crc32(str, length );
u32 hash = crc32( str.Ptr, str.Len );
for ( u32 index = 0; index < Num_Specifiers; index++ )
{
@ -371,7 +371,7 @@ namespace gen
// Represents strings cached with the string table.
// Should never be modified, if changed string is desired, cache_string( str ) another.
using StringCached = char const*;
using StringCached = String const;
// Desired width of the AST data structure.
constexpr u32 AST_POD_Size = 256;
@ -424,7 +424,7 @@ namespace gen
// Parameter
bool add_param( AST* type, s32 length, char const* name );
bool add_param( AST* type, StrC name );
inline
AST* get_param( s32 index )
@ -638,7 +638,7 @@ namespace gen
}
inline
char const* to_string()
String to_string()
{
return ast->to_string();
}
@ -743,7 +743,7 @@ namespace gen
// Used internally to retrive or make string allocations.
// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena)
StringCached get_cached_string( char const* cstr, s32 length );
StringCached get_cached_string( StrC str );
/*
This provides a fresh Code AST.
@ -767,58 +767,58 @@ namespace gen
void set_allocator_type_table ( AllocatorInfo type_reg_allocator );
# pragma region Upfront
Code def_comment ( s32 length, char const* content );
Code def_attributes( s32 length, char const* content );
Code def_comment ( StrC content );
Code def_attributes( StrC content );
Code def_class( s32 length, char const* name
Code def_class( StrC name
, Code body = NoCode
, Code parent = NoCode, AccessSpec access = AccessSpec::Public
, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_enum( s32 length, char const* name
Code def_enum( StrC
, Code body = NoCode, Code type = NoCode
, EnumT specifier = EnumRegular, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_execution ( s32 length, char const* content );
Code def_extern_link( s32 length, char const* name, Code body, ModuleFlag mflags = ModuleFlag::None );
Code def_execution ( StrC content );
Code def_extern_link( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None );
Code def_friend ( Code symbol );
Code def_function( s32 length, char const* name
Code def_function( StrC name
, Code params = NoCode, Code ret_type = NoCode, Code body = NoCode
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_include ( s32 length, char const* path );
Code def_module ( s32 length, char const* name, ModuleFlag mflags = ModuleFlag::None );
Code def_namespace( s32 length, char const* name, Code body, ModuleFlag mflags = ModuleFlag::None );
Code def_include ( StrC content );
Code def_module ( StrC name, ModuleFlag mflags = ModuleFlag::None );
Code def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None );
Code def_operator( OperatorT op
, Code params = NoCode, Code ret_type = NoCode, Code body = NoCode
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_param ( Code type, s32 length, char const* name, Code value = NoCode );
Code def_param ( Code type, StrC name, Code value = NoCode );
Code def_specifier( SpecifierT specifier );
Code def_struct( s32 length, char const* name
Code def_struct( StrC name
, Code body
, Code parent = NoCode, AccessSpec access = AccessSpec::Public
, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_typedef( s32 length, char const* name, Code type, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
Code def_type ( s32 length, char const* name, Code arrayexpr = NoCode, Code specifiers = NoCode );
Code def_typedef( StrC name, Code type, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
Code def_type ( StrC name, Code arrayexpr = NoCode, Code specifiers = NoCode );
Code def_union( s32 length, char const* name, Code body = NoCode, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
Code def_union( StrC name, Code body = NoCode, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
Code def_using( s32 length, char const* name, UsingT specifier = UsingRegular
Code def_using( StrC name, UsingT specifier = UsingRegular
, Code type = NoCode
, Code attributess = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_variable( Code type, s32 length, char const* name, Code value = NoCode
Code def_variable( Code type, StrC name, Code value = NoCode
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
@ -847,24 +847,24 @@ namespace gen
# pragma region Incremental
# ifdef GEN_FEATURE_INCREMENTAL
Code make_class( s32 length, char const* name
Code make_class( StrC name
, Code parent = NoCode, AccessSpec access = AccessSpec::Public
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code make_enum( s32 length, char const* name
Code make_enum( StrC name
, Code type = NoCode, EnumT specifier = EnumRegular
, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
Code make_export_body ( s32 length = 1, char const* name = "" );
Code make_export_body ( StrC name = { 1, "" } );
Code make_extern_linkage( s32 length, char const* name, ModuleFlag mflags = ModuleFlag::None );
Code make_function( s32 length, char const* name
Code make_function( StrC name
, Code params = NoCode, Code ret_type = NoCode
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code make_global_body( s32 length = 1, char const* name = "" );
Code make_global_body( StrC name = { 1, "" } );
Code make_namespace ( s32 length, char const* name, ModuleFlag mflags = ModuleFlag::None );
Code make_operator( OperatorT op
@ -875,32 +875,32 @@ namespace gen
Code make_params ();
Code make_specifiers();
Code make_struct( s32 length, char const* name
Code make_struct( StrC name
, Code parent = NoCode, AccessSpec access
, Code specifiers = NoCode, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code make_union( s32 length, char const* name, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
Code make_union( StrC name, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
# endif
# pragma endregion Incremental
#pragma region Parsing
#ifdef GEN_FEATURE_PARSING
Code parse_class ( s32 length, char const* class_def );
Code parse_enum ( s32 length, char const* enum_def );
Code parse_export_body( s32 length, char const* export_def );
Code parse_exten_link ( s32 length, char const* exten_link_def);
Code parse_friend ( s32 length, char const* friend_def );
Code parse_function ( s32 length, char const* fn_def );
Code parse_global_body( s32 length, char const* body_def );
Code parse_namespace ( s32 length, char const* namespace_def );
Code parse_operator ( s32 length, char const* operator_def );
Code parse_struct ( s32 length, char const* struct_def );
Code parse_type ( s32 length, char const* type_def );
Code parse_typedef ( s32 length, char const* typedef_def );
Code parse_union ( s32 length, char const* union_def );
Code parse_using ( s32 length, char const* using_def );
Code parse_variable ( s32 length, char const* var_def );
Code parse_class ( StrC class_def );
Code parse_enum ( StrC enum_def );
Code parse_export_body( StrC export_def );
Code parse_exten_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_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
@ -921,7 +921,7 @@ namespace gen
return buf;
}
Code untyped_str ( s32 length, char const* str);
Code untyped_str ( StrC content);
Code untyped_fmt ( char const* fmt, ... );
Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... );
#pragma endregion Untyped text
@ -1058,10 +1058,10 @@ namespace gen
// Convienence for defining any name used with the gen interface.
// 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_n_len( Id_ ) }
// Same as name just used to indicate intention of literal for code instead of names.
# define code( Code_ ) txt_n_len( Code_ )
# define code( Code_ ) { txt_n_len( Code_ ) }
/*
gen's Domain Specific Langauge.
@ -1285,7 +1285,7 @@ namespace gen
}
inline
bool AST::add_param( AST* type, s32 length, char const* name )
bool AST::add_param( AST* type, StrC name )
{
if ( Type != ECode::Function )
{
@ -1293,9 +1293,9 @@ namespace gen
return Code::Invalid;
}
if ( length <= 0 )
if ( name.Len <= 0 )
{
log_failure( "gen::AST::add_param: Invalid name length provided - %d", length );
log_failure( "gen::AST::add_param: Invalid name length provided - %d", name.Len );
return Code::Invalid;
}
@ -1317,7 +1317,7 @@ namespace gen
}
else if ( score == 2)
{
Name = name;
Name = get_cached_string( name );
Entries[0] = type;
return true;
}

View File

@ -0,0 +1,231 @@
#pragma once
#if gen_time
#include "gen.hpp"
using namespace gen;
Code gen__array_base()
{
Code t_allocator_info = def_type( name(AllocatorInfo) );
Code header;
{
Code allocator = def_variable( t_allocator_info, name(Allocator) );
Code capacity = def_variable( t_uw, name(Capacity) );
Code num = def_variable( t_uw, name(Num) );
Code body = def_struct_body( 3, allocator, capacity, num );
header = def_struct( name(Header), body );
}
Code grow_formula;
{
Code params = def_param( t_uw, name(value));
Code body = untyped_str( code( return 2 * value * 8; ));
Code spec = def_specifiers( ESpecifier::Static_Member, ESpecifier::Inline );
grow_formula = def_function( name(grow_formula), params, t_uw, body, spec );
}
Code body = def_struct_body( 2, header, grow_formula );
Code array_base = def_struct( name(ArrayBase), body );
return array_base;
}
Code gen__array( StrC type, sw type_size )
{
Code t_allocator_info = def_type( name(AllocatorInfo) );
Code v_nullptr = untyped_str( code(nullptr));
static Code ArrayBase = gen__array_base();
StrC name;
{
char const* name_str = str_fmt_buf( "Array_%s", type.Ptr );
s32 name_len = str_len( name );
name = { name_len, name_str };
};
Code t_array_type = def_type( name );
Code t_type = def_type( type );
Code t_type_ptr = def_type( type, __, spec_ptr );
Code t_type_ref = def_type( type, __, spec_ref );
Code t_header = def_type( name(Header) );
Code t_header_ptr = def_type( name(Header), __, spec_ptr );
Code t_header_ref = def_type( name(Header), __, spec_ref );
Code spec_static_inline = def_specifiers( ESpecifier::Static_Member, ESpecifier::Inline );
Code spec_static = def_specifiers( ESpecifier::Static_Member );
Code array;
{
Code using_type = def_using( name(Type), UsingRegular, t_type );
Code data = def_variable( t_type_ptr, name(Data) );
Code init;
{
Code params = def_param( t_allocator_info, name(allocator) );
Code body = untyped_str( code(
return init_reserve( allocator, grow_formula(0) );
));
init = def_function( name(init), params, t_array_type, body, spec_static );
}
Code init_reserve;
{
Code params = def_params( 2, t_allocator_info, name(allocator), t_sw, name(capacity) );
Code body = untyped_str( code(
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) ));
if ( header == nullptr )
return false;
header->Allocator = allocator;
header->Capacity = capacity;
header->Num = 0;
Data = rcast( Type*, header + 1 );
return true;
));
init_reserve = def_function( name(init_reserve), params, t_array_type, body, spec_static );
}
Code append;
{
Code params = def_param( t_type, name(value));
Code body = untyped_str( code(
Header& header = get_header();
if ( header.Num == header.Capacity )
{
if ( ! grow( header.Allocator ))
return false;
}
data[ header.Num ] = value;
header.Num++;
return true;
));
append = def_function( name(append), params, t_bool, body );
}
Code back;
{
Code body = untyped_str( code(
Header& header = get_header();
return Data[ header.Num - 1 ];
));
back = def_function( name(back), __, t_type_ref, body );
}
Code clear;
Code fill;
Code free;
{
Code body = untyped_str( code(
Header& header = get_header();
::free( header.Allocator, & header );
));
free = def_function( name(free), __, t_void, body, spec_inline );
}
Code get_header;
Code grow;
Code pop;
Code reserve;
Code resize;
Code set_capacity;
Code body = def_struct_body( 17
, using_type
, init
, init_reserve
, append
, back
, clear
, fill
, free
, get_header
, grow
, pop
, reserve
, resize
, set_capacity
, data
);
array = def_struct( name, body );
}
return array;
}
struct GenArrayRequest
{
StrC Type;
StrC Dependency;
sw Size;
};
Array(GenArrayRequest) GenArrayRequests;
void gen__array_request( StrC type, StrC dep, sw size )
{
GenArrayRequest request = { type, dep, size };
array_append( GenArrayRequests, request );
}
#define Gen_Array( type ) gen__array_request( txt_n_len( type ), sizeof(type) )
u32 gen_array_file()
{
Builder
gen_array_file;
gen_array_file.open( "array.gen.hpp" );
GenArrayRequest* current = GenArrayRequests;
s32 left = array_count( GenArrayRequests );
while (left--)
{
GenArrayRequest const& request = * current;
Code generated_array = gen__array( request.Type, request.Size );
if ( request.Dependency )
{
char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type );
s32 cmt_len = str_len( cmt_str );
Code cmt = def_comment( { cmt_len, cmt_str } );
Code include = def_include( request.Dependency );
gen_array_file.print( cmt );
gen_array_file.print( include );
}
gen_array_file.print( generated_array );
current++;
}
gen_array_file.write();
return 0;
}
#endif

View File

@ -0,0 +1,170 @@
#pragma once
#if gen_time
#include "gen.hpp"
using namespace gen;
Code gen__array_base()
{
Code array_base = parse_struct( code(
struct ArrayBase
{
struct Header
{
AllocatorInfo Allocator;
uw Capacity;
uw Num;
};
static inline
sw grow_formula( sw value )
{
return 2 * value * 8;
}
};
));
return array_base;
}
Code gen__array( s32 length, char const* type_str, sw type_size )
{
StrC tmpl = code(
struct Array_{type} : ArrayBase
{
using Type = {type};
Type* Data;
static Array_{type} init( AllocatorInfo allocator )
{
return init_reserve( allocator, grow_formula(0) );
}
static Array_{type} init_reserve( AllocatorInfo allocator, uw capacity )
{
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) ));
if ( header == nullptr )
return false;
header->Allocator = allocator;
header->Capacity = capacity;
header->Num = 0;
Array_{type} array;
array.Data = rcast( Type*, header + 1 );
return array;
}
bool append( Type const& value )
{
Header& header = get_header();
if ( header.Num == header.Capacity )
{
if ( ! grow( header.Allocator ))
return false;
}
data[ header.Num ] = value;
header.Num++;
return true;
}
Type& back()
{
Header& header = get_header();
return data[ header.Num - 1 ];
}
void clear();
bool fill();
void free()
{
Header& header = get_header();
::free( header.Allocator, & header );
}
Header& get_header()
{
return rcast( Header*, Data ) - 1;
}
bool grow();
void pop();
bool reserve( uw num );
bool resize( uw num );
bool set_capacity( uw capacity );
}
);
char const* gen_from_tmpl = token_fmt( tmpl.Ptr, 1, "type", type_str );
s32 gen_from_tmpl_len = str_len( gen_from_tmpl );
Code array = parse_struct( { gen_from_tmpl_len, gen_from_tmpl } );
}
struct GenArrayRequest
{
s32 TypeLength;
char const* Type;
sw Size;
s32 DependencyLength;
char const* Dependency;
};
Array(GenArrayRequest) GenArrayRequests;
void gen__array_request( s32 type_len, char const* type_str, sw type_size, s32 dep_len, char const* dep )
{
GenArrayRequest request = { type_len, type_str, type_size, dep_len, dep };
array_append( GenArrayRequests, request );
}
#define Gen_Array( type ) gen__array_request( txt_n_len( type ), sizeof(type) )
u32 gen_array_file()
{
Builder
gen_array_file;
gen_array_file.open( "array.gen.hpp" );
GenArrayRequest* current = GenArrayRequests;
s32 left = array_count( GenArrayRequests );
while (left--)
{
GenArrayRequest const& request = * current;
Code generated_array = gen__array( request.TypeLength, request.Type, request.Size );
if ( request.Dependency )
{
char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type );
s32 cmt_len = str_len( cmt_str );
Code cmt = def_comment( { cmt_len, cmt_str } );
Code include = def_include( { request.DependencyLength, request.Dependency } );
gen_array_file.print( cmt );
gen_array_file.print( include );
}
gen_array_file.print( generated_array );
current++;
}
gen_array_file.write();
return 0;
}
#endif