mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 07:44:45 -08:00
Scripting updates, some refactors..
Made a package release script. Did refactors based on some design considerations Still need to make some major decisions...
This commit is contained in:
parent
5aff89262b
commit
aa928ff446
@ -360,7 +360,7 @@ Code <name> = code_str( <some code without "" quotes > )
|
||||
Template metaprogramming in the traditional sense becomes possible with the use of `token_fmt` and parse constructors:
|
||||
|
||||
```cpp
|
||||
StrC value = txt_StrC("Something");
|
||||
StrC value = txt("Something");
|
||||
|
||||
char const* template_str = txt(
|
||||
Code with <key> to replace with token_values
|
||||
@ -447,7 +447,7 @@ and have the desired specifiers assigned to them beforehand.
|
||||
|
||||
## Code generation and modification
|
||||
|
||||
There are three provided file interfaces:
|
||||
There are three provided auxillary interfaces:
|
||||
|
||||
* Builder
|
||||
* Editor
|
||||
@ -462,11 +462,12 @@ Editor and Scanner are disabled by default, use `GEN_FEATURE_EDITOR` and `GEN_FE
|
||||
* The code is provided via print( code ) function will be serialized to its buffer.
|
||||
* When all serialization is finished, use the write() command to write the buffer to the file.
|
||||
|
||||
### Editor is for editing a series of files based on a set of requests provided to it
|
||||
### Editor is for editing a series of files/asts based on a set of requests provided to it
|
||||
|
||||
**Note: Not implemented yet**
|
||||
|
||||
* The purpose is to overrite a specific file, it places its contents in a buffer to scan.
|
||||
* If editing an AST it will generate a new ast as a result (ASTs are not edited).
|
||||
* Requests are populated using the following interface:
|
||||
* add : Add code.
|
||||
* remove : Remove code.
|
||||
@ -486,7 +487,7 @@ Additionally if `GEN_FEATURE_EDITOR_REFACTOR` is defined, refactor( file_path, s
|
||||
Refactor is based of the refactor library and uses its interface.
|
||||
It will on call add a request to the queue to run the refactor script on the file.
|
||||
|
||||
### Scanner allows the user to generate Code ASTs by reading files
|
||||
### Scanner allows the user to sift through a series of files/asts based on a set of requests provided to it
|
||||
|
||||
**Note: Not implemented yet**
|
||||
|
||||
@ -495,8 +496,6 @@ It will on call add a request to the queue to run the refactor script on the fil
|
||||
|
||||
The file will only be read from, no writing supported.
|
||||
|
||||
One great use case is for example: generating the single-header library for gencpp!
|
||||
|
||||
### Additional Info (Editor and Scanner)
|
||||
|
||||
When all requests have been populated, call process_requests().
|
||||
|
1
project/auxillary/scanner.cpp
Normal file
1
project/auxillary/scanner.cpp
Normal file
@ -0,0 +1 @@
|
||||
|
@ -5,13 +5,13 @@ Code scan_file( char const* path )
|
||||
FileError error = file_open_mode( & file, EFileMode_READ, path );
|
||||
if ( error != EFileError_NONE )
|
||||
{
|
||||
fatal( "scan_file: Could not open: %s", path );
|
||||
GEN_FATAL( "scan_file: Could not open: %s", path );
|
||||
}
|
||||
|
||||
sw fsize = file_size( & file );
|
||||
if ( fsize <= 0 )
|
||||
{
|
||||
fatal("scan_file: %s is empty", path );
|
||||
GEN_FATAL("scan_file: %s is empty", path );
|
||||
}
|
||||
|
||||
String str = String::make_reserve( GlobalAllocator, fsize );
|
||||
@ -36,7 +36,6 @@ struct SymbolInfo
|
||||
Code Signature;
|
||||
};
|
||||
|
||||
|
||||
struct Scanner
|
||||
{
|
||||
struct RequestEntry
|
@ -15,10 +15,10 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw a
|
||||
Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize );
|
||||
|
||||
if ( bucket.PhysicalStart == nullptr )
|
||||
fatal( "Failed to create bucket for Global_AllocatorBuckets");
|
||||
GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets");
|
||||
|
||||
if ( ! Global_AllocatorBuckets.append( bucket ) )
|
||||
fatal( "Failed to append bucket to Global_AllocatorBuckets");
|
||||
GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets");
|
||||
|
||||
last = & Global_AllocatorBuckets.back();
|
||||
}
|
||||
@ -42,10 +42,10 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw a
|
||||
Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize );
|
||||
|
||||
if ( bucket.PhysicalStart == nullptr )
|
||||
fatal( "Failed to create bucket for Global_AllocatorBuckets");
|
||||
GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets");
|
||||
|
||||
if ( ! Global_AllocatorBuckets.append( bucket ) )
|
||||
fatal( "Failed to append bucket to Global_AllocatorBuckets");
|
||||
GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets");
|
||||
|
||||
last = & Global_AllocatorBuckets.back();
|
||||
}
|
||||
@ -68,7 +68,7 @@ internal
|
||||
void define_constants()
|
||||
{
|
||||
Code::Global = make_code();
|
||||
Code::Global->Name = get_cached_string( txt_StrC("Global Code") );
|
||||
Code::Global->Name = get_cached_string( txt("Global Code") );
|
||||
Code::Global->Content = Code::Global->Name;
|
||||
|
||||
Code::Invalid = make_code();
|
||||
@ -76,22 +76,22 @@ void define_constants()
|
||||
|
||||
t_empty = (CodeType) make_code();
|
||||
t_empty->Type = ECode::Typename;
|
||||
t_empty->Name = get_cached_string( txt_StrC("") );
|
||||
t_empty->Name = get_cached_string( txt("") );
|
||||
t_empty.set_global();
|
||||
|
||||
access_private = make_code();
|
||||
access_private->Type = ECode::Access_Private;
|
||||
access_private->Name = get_cached_string( txt_StrC("private:") );
|
||||
access_private->Name = get_cached_string( txt("private:") );
|
||||
access_private.set_global();
|
||||
|
||||
access_protected = make_code();
|
||||
access_protected->Type = ECode::Access_Protected;
|
||||
access_protected->Name = get_cached_string( txt_StrC("protected:") );
|
||||
access_protected->Name = get_cached_string( txt("protected:") );
|
||||
access_protected.set_global();
|
||||
|
||||
access_public = make_code();
|
||||
access_public->Type = ECode::Access_Public;
|
||||
access_public->Name = get_cached_string( txt_StrC("public:") );
|
||||
access_public->Name = get_cached_string( txt("public:") );
|
||||
access_public.set_global();
|
||||
|
||||
attrib_api_export = def_attributes( code(GEN_API_Export_Code));
|
||||
@ -102,13 +102,13 @@ void define_constants()
|
||||
|
||||
module_global_fragment = make_code();
|
||||
module_global_fragment->Type = ECode::Untyped;
|
||||
module_global_fragment->Name = get_cached_string( txt_StrC("module;") );
|
||||
module_global_fragment->Name = get_cached_string( txt("module;") );
|
||||
module_global_fragment->Content = module_global_fragment->Name;
|
||||
module_global_fragment.set_global();
|
||||
|
||||
module_private_fragment = make_code();
|
||||
module_private_fragment->Type = ECode::Untyped;
|
||||
module_private_fragment->Name = get_cached_string( txt_StrC("module : private;") );
|
||||
module_private_fragment->Name = get_cached_string( txt("module : private;") );
|
||||
module_private_fragment->Content = module_private_fragment->Name;
|
||||
module_private_fragment.set_global();
|
||||
|
||||
@ -118,13 +118,13 @@ void define_constants()
|
||||
|
||||
pragma_once = (CodePragma) make_code();
|
||||
pragma_once->Type = ECode::Preprocess_Pragma;
|
||||
pragma_once->Name = get_cached_string( txt_StrC("once") );
|
||||
pragma_once->Name = get_cached_string( txt("once") );
|
||||
pragma_once->Content = pragma_once->Name;
|
||||
pragma_once.set_global();
|
||||
|
||||
param_varadic = (CodeType) make_code();
|
||||
param_varadic->Type = ECode::Parameters;
|
||||
param_varadic->Name = get_cached_string( txt_StrC("...") );
|
||||
param_varadic->Name = get_cached_string( txt("...") );
|
||||
param_varadic->ValueType = t_empty;
|
||||
param_varadic.set_global();
|
||||
|
||||
@ -226,12 +226,12 @@ void init()
|
||||
Global_AllocatorBuckets = Array<Arena>::init_reserve( heap(), 128 );
|
||||
|
||||
if ( Global_AllocatorBuckets == nullptr )
|
||||
fatal( "Failed to reserve memory for Global_AllocatorBuckets");
|
||||
GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets");
|
||||
|
||||
Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize );
|
||||
|
||||
if ( bucket.PhysicalStart == nullptr )
|
||||
fatal( "Failed to create first bucket for Global_AllocatorBuckets");
|
||||
GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets");
|
||||
|
||||
Global_AllocatorBuckets.append( bucket );
|
||||
|
||||
@ -242,12 +242,12 @@ void init()
|
||||
CodePools = Array<Pool>::init_reserve( Allocator_DataArrays, InitSize_DataArrays );
|
||||
|
||||
if ( CodePools == nullptr )
|
||||
fatal( "gen::init: Failed to initialize the CodePools array" );
|
||||
GEN_FATAL( "gen::init: Failed to initialize the CodePools array" );
|
||||
|
||||
StringArenas = Array<Arena>::init_reserve( Allocator_DataArrays, InitSize_DataArrays );
|
||||
|
||||
if ( StringArenas == nullptr )
|
||||
fatal( "gen::init: Failed to initialize the StringArenas array" );
|
||||
GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" );
|
||||
}
|
||||
|
||||
// Setup the code pool and code entries arena.
|
||||
@ -255,7 +255,7 @@ void init()
|
||||
Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) );
|
||||
|
||||
if ( code_pool.PhysicalStart == nullptr )
|
||||
fatal( "gen::init: Failed to initialize the code pool" );
|
||||
GEN_FATAL( "gen::init: Failed to initialize the code pool" );
|
||||
|
||||
CodePools.append( code_pool );
|
||||
|
||||
@ -264,7 +264,7 @@ void init()
|
||||
Arena string_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena );
|
||||
|
||||
if ( string_arena.PhysicalStart == nullptr )
|
||||
fatal( "gen::init: Failed to initialize the string arena" );
|
||||
GEN_FATAL( "gen::init: Failed to initialize the string arena" );
|
||||
|
||||
StringArenas.append( string_arena );
|
||||
}
|
||||
@ -274,7 +274,7 @@ void init()
|
||||
StringCache = StringTable::init( Allocator_StringTable );
|
||||
|
||||
if ( StringCache.Entries == nullptr )
|
||||
fatal( "gen::init: Failed to initialize the StringCache");
|
||||
GEN_FATAL( "gen::init: Failed to initialize the StringCache");
|
||||
}
|
||||
|
||||
define_constants();
|
||||
@ -362,7 +362,7 @@ AllocatorInfo get_string_allocator( s32 str_length )
|
||||
Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena );
|
||||
|
||||
if ( ! StringArenas.append( new_arena ) )
|
||||
fatal( "gen::get_string_allocator: Failed to allocate a new string arena" );
|
||||
GEN_FATAL( "gen::get_string_allocator: Failed to allocate a new string arena" );
|
||||
|
||||
last = & StringArenas.back();
|
||||
}
|
||||
@ -397,10 +397,10 @@ Code make_code()
|
||||
Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) );
|
||||
|
||||
if ( code_pool.PhysicalStart == nullptr )
|
||||
fatal( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." );
|
||||
GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." );
|
||||
|
||||
if ( ! CodePools.append( code_pool ) )
|
||||
fatal( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." );
|
||||
GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." );
|
||||
|
||||
allocator = & CodePools.back();
|
||||
}
|
||||
|
@ -1122,7 +1122,7 @@ if ( def.Ptr == nullptr ) \
|
||||
# define check( Type_ ) ( left && currtok.Type == Type_ )
|
||||
|
||||
# define push_scope() \
|
||||
StackNode scope { nullptr, currtok, NullToken, txt_StrC( __func__ ) }; \
|
||||
StackNode scope { nullptr, currtok, NullToken, txt( __func__ ) }; \
|
||||
Context.push( & scope )
|
||||
|
||||
#pragma endregion Helper Macros
|
||||
@ -1329,7 +1329,7 @@ Code parse_static_assert()
|
||||
|
||||
char const* result = str_fmt_buf( "%.*s\n", content.Length, content.Text );
|
||||
|
||||
assert->Content = get_cached_string( to_StrC( result ) );
|
||||
assert->Content = get_cached_string( to_str( result ) );
|
||||
assert->Name = assert->Content;
|
||||
|
||||
Context.pop();
|
||||
@ -2264,7 +2264,7 @@ Code parse_simple_preprocess( Parser::TokType which )
|
||||
|
||||
char const* content = str_fmt_buf( "%.*s\n", tok.Length, tok.Text );
|
||||
|
||||
Code result = untyped_str( to_StrC( content ) );
|
||||
Code result = untyped_str( to_str( content ) );
|
||||
Context.Scope->Name = tok;
|
||||
|
||||
if ( str_compare( Context.Scope->Prev->ProcName.Ptr, "parse_typedef", Context.Scope->Prev->ProcName.Len ) != 0 )
|
||||
|
@ -89,4 +89,5 @@ namespace ECode
|
||||
# undef Define_Types
|
||||
}
|
||||
using CodeT = ECode::Type;
|
||||
using ECode::to_str;
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace EOperator
|
||||
# define Entry( Type_, Token_ ) { sizeof(stringize(Token_)), stringize(Token_) },
|
||||
Define_Operators
|
||||
# undef Entry
|
||||
txt_StrC(",")
|
||||
txt(",")
|
||||
};
|
||||
|
||||
return lookup[ op ];
|
||||
@ -73,4 +73,5 @@ namespace EOperator
|
||||
# undef Define_Operators
|
||||
}
|
||||
using OperatorT = EOperator::Type;
|
||||
using EOperator::to_str;
|
||||
|
||||
|
@ -107,4 +107,5 @@ namespace ESpecifier
|
||||
# undef Define_Specifiers
|
||||
}
|
||||
using SpecifierT = ESpecifier::Type;
|
||||
using ESpecifier::to_str;
|
||||
|
||||
|
@ -165,6 +165,7 @@ namespace Parser
|
||||
};
|
||||
|
||||
using TokType = ETokType::Type;
|
||||
using ETokType::to_str;
|
||||
|
||||
} // Parser
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
using LogFailType = sw(*)(char const*, ...);
|
||||
|
||||
// By default this library will either crash or exit if an error is detected while generating codes.
|
||||
// Even if set to not use fatal, fatal will still be used for memory failures as the library is unusable when they occur.
|
||||
// Even if set to not use GEN_FATAL, GEN_FATAL will still be used for memory failures as the library is unusable when they occur.
|
||||
#ifdef GEN_DONT_USE_FATAL
|
||||
#define log_failure log_fmt
|
||||
#else
|
||||
#define log_failure fatal
|
||||
#define log_failure GEN_FATAL
|
||||
#endif
|
||||
|
||||
enum class AccessSpec : u32
|
||||
@ -46,7 +46,6 @@ enum class EnumT : u8
|
||||
constexpr EnumT EnumClass = EnumT::Class;
|
||||
constexpr EnumT EnumRegular = EnumT::Regular;
|
||||
|
||||
|
||||
enum class ModuleFlag : u32
|
||||
{
|
||||
None = 0,
|
||||
@ -76,50 +75,3 @@ constexpr EPreprocessCond PreprocessCond_IfDef = EPreprocessCond::IfDef;
|
||||
constexpr EPreprocessCond PreprocessCond_IfNotDef = EPreprocessCond::IfNotDef;
|
||||
constexpr EPreprocessCond PreprocessCond_ElIf = EPreprocessCond::ElIf;
|
||||
|
||||
/*
|
||||
Predefined attributes
|
||||
Used for the parser constructors to identify non-standard attributes
|
||||
|
||||
Override these to change the attribute to your own unique identifier convention.
|
||||
|
||||
The tokenizer identifies attribute defines with the GEN_DEFINE_ATTRIBUTE_TOKENS macros.
|
||||
See the example below and the Define_TokType macro used in gen.cpp to know the format.
|
||||
While the library can parse raw attributes, most projects use defines to wrap them for compiler
|
||||
platform indendence. The token define allows support for them without having to modify the library.
|
||||
*/
|
||||
#if defined(GEN_SYSTEM_WINDOWS) || defined( __CYGWIN__ )
|
||||
#ifndef GEN_Attribute_Keyword
|
||||
# define GEN_API_Export_Code __declspec(dllexport)
|
||||
# define GEN_API_Import_Code __declspec(dllimport)
|
||||
# define GEN_Attribute_Keyword __declspec
|
||||
#endif
|
||||
|
||||
constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword);
|
||||
|
||||
#elif GEN_HAS_ATTRIBUTE( visibility ) || GEN_GCC_VERSION_CHECK( 3, 3, 0 )
|
||||
#ifndef GEN_Attribute_Keyword
|
||||
# define GEN_API_Export_Code __attribute__ ((visibility ("default")))
|
||||
# define GEN_API_Import_Code __attribute__ ((visibility ("default")))
|
||||
# define GEN_Attribute_Keyword __attribute__
|
||||
#endif
|
||||
|
||||
constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword );
|
||||
|
||||
#else
|
||||
#ifndef GEN_Attribute_Keyword
|
||||
# define GEN_API_Export_Code
|
||||
# define GEN_API_Import_Code
|
||||
# define GEN_Attribute_Keyword
|
||||
#endif
|
||||
|
||||
constexpr char const* Attribute_Keyword = "";
|
||||
|
||||
#endif
|
||||
|
||||
// Implements basic string interning. Data structure is based off the ZPL Hashtable.
|
||||
using StringTable = HashTable<String const>;
|
||||
|
||||
// Represents strings cached with the string table.
|
||||
// Should never be modified, if changed string is desired, cache_string( str ) another.
|
||||
using StringCached = String const;
|
||||
|
||||
|
@ -34,7 +34,7 @@ s32 assert_crash( char const* condition );
|
||||
void process_exit( u32 code );
|
||||
|
||||
#if Build_Debug
|
||||
#define fatal( fmt, ... ) \
|
||||
#define GEN_FATAL( fmt, ... ) \
|
||||
do \
|
||||
{ \
|
||||
local_persist thread_local \
|
||||
@ -46,7 +46,7 @@ void process_exit( u32 code );
|
||||
while (0)
|
||||
#else
|
||||
|
||||
# define fatal( fmt, ... ) \
|
||||
# define GEN_FATAL( fmt, ... ) \
|
||||
do \
|
||||
{ \
|
||||
str_fmt_out_err( fmt, __VA_ARGS__ ); \
|
||||
|
@ -100,25 +100,6 @@
|
||||
#define GEN_DEF_INLINE static
|
||||
#define GEN_IMPL_INLINE static inline
|
||||
|
||||
#ifdef GEN_COMPILER_MSVC
|
||||
# define forceinline __forceinline
|
||||
# define neverinline __declspec( noinline )
|
||||
#elif defined(GEN_COMPILER_GCC)
|
||||
# define forceinline inline __attribute__((__always_inline__))
|
||||
# define neverinline __attribute__( ( __noinline__ ) )
|
||||
#elif defined(GEN_COMPILER_CLANG)
|
||||
#if __has_attribute(__always_inline__)
|
||||
# define forceinline inline __attribute__((__always_inline__))
|
||||
# define neverinline __attribute__( ( __noinline__ ) )
|
||||
#else
|
||||
# define forceinline
|
||||
# define neverinline
|
||||
#endif
|
||||
#else
|
||||
# define forceinline
|
||||
# define neverinline
|
||||
#endif
|
||||
|
||||
#pragma endregion Platform Detection
|
||||
|
||||
#pragma region Mandatory Includes
|
||||
|
@ -8,6 +8,25 @@
|
||||
#define internal static // Internal linkage
|
||||
#define local_persist static // Local Persisting variables
|
||||
|
||||
#ifdef GEN_COMPILER_MSVC
|
||||
# define forceinline __forceinline
|
||||
# define neverinline __declspec( noinline )
|
||||
#elif defined(GEN_COMPILER_GCC)
|
||||
# define forceinline inline __attribute__((__always_inline__))
|
||||
# define neverinline __attribute__( ( __noinline__ ) )
|
||||
#elif defined(GEN_COMPILER_CLANG)
|
||||
#if __has_attribute(__always_inline__)
|
||||
# define forceinline inline __attribute__((__always_inline__))
|
||||
# define neverinline __attribute__( ( __noinline__ ) )
|
||||
#else
|
||||
# define forceinline
|
||||
# define neverinline
|
||||
#endif
|
||||
#else
|
||||
# define forceinline
|
||||
# define neverinline
|
||||
#endif
|
||||
|
||||
// Bits
|
||||
|
||||
#define bit( Value ) ( 1 << Value )
|
||||
@ -125,6 +144,12 @@
|
||||
#define min( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
|
||||
#define size_of( x ) ( sw )( sizeof( x ) )
|
||||
|
||||
#if defined( _MSC_VER ) || defined( GEN_COMPILER_TINYC )
|
||||
# define offset_of( Type, element ) ( ( GEN_NS( gen_sw ) ) & ( ( ( Type* )0 )->element ) )
|
||||
#else
|
||||
# define offset_of( Type, element ) __builtin_offsetof( Type, element )
|
||||
#endif
|
||||
|
||||
template< class Type >
|
||||
void swap( Type& a, Type& b )
|
||||
{
|
||||
|
@ -221,7 +221,7 @@ void* Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw a
|
||||
if ( arena->TotalUsed + total_size > (sw) arena->TotalSize )
|
||||
{
|
||||
// zpl__printf_err("%s", "Arena out of memory\n");
|
||||
fatal("Arena out of memory! (Possibly could not fit for the largest size Arena!!)");
|
||||
GEN_FATAL("Arena out of memory! (Possibly could not fit for the largest size Arena!!)");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma region String
|
||||
#pragma region Strings
|
||||
|
||||
// Constant string with length.
|
||||
struct StrC
|
||||
@ -12,18 +12,14 @@ struct StrC
|
||||
}
|
||||
};
|
||||
|
||||
#define txt_StrC( text ) StrC { sizeof( text ) - 1, text }
|
||||
#define cast_to_strc( str ) * rcast( StrC*, str - sizeof(sw) )
|
||||
#define txt( text ) StrC { sizeof( text ) - 1, text }
|
||||
|
||||
StrC to_StrC( char const* str )
|
||||
StrC to_str( char const* str )
|
||||
{
|
||||
return { str_len( str ), str };
|
||||
}
|
||||
|
||||
sw StrC_len( char const* str )
|
||||
{
|
||||
return (sw) ( str - 1 );
|
||||
}
|
||||
|
||||
// Dynamic String
|
||||
// This is directly based off the ZPL string api.
|
||||
// They used a header pattern
|
||||
@ -33,8 +29,8 @@ struct String
|
||||
struct Header
|
||||
{
|
||||
AllocatorInfo Allocator;
|
||||
sw Length;
|
||||
sw Capacity;
|
||||
sw Length;
|
||||
};
|
||||
|
||||
static
|
||||
@ -332,11 +328,7 @@ struct String
|
||||
|
||||
operator StrC() const
|
||||
{
|
||||
return
|
||||
{
|
||||
length(),
|
||||
Data
|
||||
};
|
||||
return { length(), Data };
|
||||
}
|
||||
|
||||
// Used with cached strings
|
||||
@ -363,19 +355,21 @@ struct String
|
||||
return Data[ index ];
|
||||
}
|
||||
|
||||
char* Data = nullptr;
|
||||
char* Data;
|
||||
};
|
||||
|
||||
struct String_POD
|
||||
{
|
||||
char* Data;
|
||||
|
||||
operator String()
|
||||
{
|
||||
return * rcast(String*, this);
|
||||
}
|
||||
};
|
||||
static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" );
|
||||
|
||||
#pragma endregion String
|
||||
// Implements basic string interning. Data structure is based off the ZPL Hashtable.
|
||||
using StringTable = HashTable<String const>;
|
||||
|
||||
// Represents strings cached with the string table.
|
||||
// Should never be modified, if changed string is desired, cache_string( str ) another.
|
||||
using StringCached = String const;
|
||||
|
||||
#pragma endregion Strings
|
||||
|
@ -3,15 +3,16 @@
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#include "gen.cpp"
|
||||
|
||||
#include "helpers/push_ignores.inline.hpp"
|
||||
#include "helpers/helper.hpp"
|
||||
|
||||
GEN_NS_BEGIN
|
||||
#include "dependencies/parsing.cpp"
|
||||
GEN_NS_END
|
||||
|
||||
#include "file_processors/builder.hpp"
|
||||
#include "file_processors/builder.cpp"
|
||||
#include "file_processors/scanner.hpp"
|
||||
#include "auxillary/builder.hpp"
|
||||
#include "auxillary/builder.cpp"
|
||||
#include "auxillary/scanner.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
@ -37,8 +38,8 @@ int gen_main()
|
||||
Code printing = scan_file( "dependencies/printing.hpp" );
|
||||
Code containers = scan_file( "dependencies/containers.hpp" );
|
||||
Code hashing = scan_file( "dependencies/hashing.hpp" );
|
||||
Code string = scan_file( "dependencies/string.hpp" );
|
||||
Code file_handling = scan_file( "dependencies/file_handling.hpp" );
|
||||
Code strings = scan_file( "dependencies/strings.hpp" );
|
||||
Code filesystem = scan_file( "dependencies/filesystem.hpp" );
|
||||
Code timing = scan_file( "dependencies/timing.hpp" );
|
||||
|
||||
Builder
|
||||
@ -56,8 +57,8 @@ int gen_main()
|
||||
header.print( printing );
|
||||
header.print( containers );
|
||||
header.print( hashing );
|
||||
header.print( string );
|
||||
header.print( file_handling );
|
||||
header.print( strings );
|
||||
header.print( filesystem );
|
||||
header.print( timing );
|
||||
|
||||
header.print_fmt( "GEN_NS_END\n\n" );
|
||||
@ -72,8 +73,8 @@ int gen_main()
|
||||
Code printing = scan_file( "dependencies/printing.cpp" );
|
||||
Code memory = scan_file( "dependencies/memory.cpp" );
|
||||
Code hashing = scan_file( "dependencies/hashing.cpp" );
|
||||
Code string = scan_file( "dependencies/string.cpp" );
|
||||
Code file_handling = scan_file( "dependencies/file_handling.cpp" );
|
||||
Code strings = scan_file( "dependencies/strings.cpp" );
|
||||
Code filesystem = scan_file( "dependencies/filesystem.cpp" );
|
||||
Code timing = scan_file( "dependencies/timing.cpp" );
|
||||
|
||||
Builder
|
||||
@ -88,8 +89,8 @@ int gen_main()
|
||||
src.print( printing );
|
||||
src.print( hashing );
|
||||
src.print( memory );
|
||||
src.print( string );
|
||||
src.print( file_handling );
|
||||
src.print( strings );
|
||||
src.print( filesystem );
|
||||
src.print( timing );
|
||||
|
||||
src.print_fmt( "GEN_NS_END\n\n" );
|
||||
@ -189,13 +190,13 @@ int gen_main()
|
||||
|
||||
// gen_builder.hpp
|
||||
{
|
||||
Code builder = scan_file( "file_processors/builder.hpp" );
|
||||
Code builder = scan_file( "auxillary/builder.hpp" );
|
||||
|
||||
Builder
|
||||
header = Builder::open( "gen/gen.builder.hpp" );
|
||||
header.print_fmt( generation_notice );
|
||||
header.print_fmt( "#pragma once\n\n" );
|
||||
header.print( def_include( txt_StrC("gen.hpp") ));
|
||||
header.print( def_include( txt("gen.hpp") ));
|
||||
header.print_fmt( "\nGEN_NS_BEGIN\n\n" );
|
||||
header.print( builder );
|
||||
header.print_fmt( "\nGEN_NS_END\n\n" );
|
||||
@ -204,12 +205,12 @@ int gen_main()
|
||||
|
||||
// gen_builder.cpp
|
||||
{
|
||||
Code builder = scan_file( "file_processors/builder.cpp" );
|
||||
Code builder = scan_file( "auxillary/builder.cpp" );
|
||||
|
||||
Builder
|
||||
src = Builder::open( "gen/gen.builder.cpp" );
|
||||
src.print_fmt( generation_notice );
|
||||
src.print( def_include( txt_StrC("gen.builder.hpp") ) );
|
||||
src.print( def_include( txt("gen.builder.hpp") ) );
|
||||
src.print_fmt( "\nGEN_NS_BEGIN\n\n" );
|
||||
src.print( builder );
|
||||
src.print_fmt( "\nGEN_NS_END\n\n" );
|
||||
@ -219,13 +220,13 @@ int gen_main()
|
||||
// gen_scanner.hpp
|
||||
{
|
||||
Code parsing = scan_file( "dependencies/parsing.hpp" );
|
||||
Code scanner = scan_file( "file_processors/scanner.hpp" );
|
||||
Code scanner = scan_file( "auxillary/scanner.hpp" );
|
||||
|
||||
Builder
|
||||
header = Builder::open( "gen/gen.scanner.hpp" );
|
||||
header.print_fmt( generation_notice );
|
||||
header.print_fmt( "#pragma once\n\n" );
|
||||
header.print( def_include( txt_StrC("gen.hpp") ) );
|
||||
header.print( def_include( txt("gen.hpp") ) );
|
||||
header.print_fmt( "\nGEN_NS_BEGIN\n\n" );
|
||||
header.print( parsing );
|
||||
header.print( scanner );
|
||||
@ -236,15 +237,15 @@ int gen_main()
|
||||
// gen_scanner.cpp
|
||||
{
|
||||
Code parsing = scan_file( "dependencies/parsing.cpp" );
|
||||
// Code scanner = scan_file( "file_processors/scanner.cpp" );
|
||||
Code scanner = scan_file( "auxillary/scanner.cpp" );
|
||||
|
||||
Builder
|
||||
src = Builder::open( "gen/gen.scanner.cpp" );
|
||||
src.print_fmt( generation_notice );
|
||||
src.print( def_include( txt_StrC("gen.scanner.hpp") ) );
|
||||
src.print( def_include( txt("gen.scanner.hpp") ) );
|
||||
src.print_fmt( "\nGEN_NS_BEGIN\n\n" );
|
||||
src.print( parsing );
|
||||
// src.print( scanner );
|
||||
src.print( scanner );
|
||||
src.print_fmt( "\nGEN_NS_END\n\n" );
|
||||
src.write();
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ GEN_NS_BEGIN
|
||||
#include "dependencies/printing.cpp"
|
||||
#include "dependencies/memory.cpp"
|
||||
#include "dependencies/hashing.cpp"
|
||||
#include "dependencies/string.cpp"
|
||||
#include "dependencies/file_handling.cpp"
|
||||
#include "dependencies/strings.cpp"
|
||||
#include "dependencies/filesystem.cpp"
|
||||
#include "dependencies/timing.cpp"
|
||||
|
||||
GEN_NS_END
|
||||
|
@ -13,8 +13,8 @@ GEN_NS_BEGIN
|
||||
#include "dependencies/printing.hpp"
|
||||
#include "dependencies/containers.hpp"
|
||||
#include "dependencies/hashing.hpp"
|
||||
#include "dependencies/string.hpp"
|
||||
#include "dependencies/file_handling.hpp"
|
||||
#include "dependencies/strings.hpp"
|
||||
#include "dependencies/filesystem.hpp"
|
||||
#include "dependencies/timing.hpp"
|
||||
|
||||
GEN_NS_END
|
||||
|
@ -531,7 +531,7 @@ CodeBody gen_ast_inlines()
|
||||
CodeBody impl_cast_var = parse_global_body( token_fmt( "typename", StrC name(Var), cast_tmpl ));
|
||||
|
||||
CodeBody result = def_global_body( args(
|
||||
def_pragma( txt_StrC("region generated code inline implementation")),
|
||||
def_pragma( txt("region generated code inline implementation")),
|
||||
fmt_newline,
|
||||
impl_code,
|
||||
impl_code_body,
|
||||
@ -563,9 +563,9 @@ CodeBody gen_ast_inlines()
|
||||
impl_code_using,
|
||||
impl_code_var,
|
||||
fmt_newline,
|
||||
def_pragma( txt_StrC("endregion generated code inline implementation")),
|
||||
def_pragma( txt("endregion generated code inline implementation")),
|
||||
fmt_newline,
|
||||
def_pragma( txt_StrC("region generated AST/Code cast implementation")),
|
||||
def_pragma( txt("region generated AST/Code cast implementation")),
|
||||
fmt_newline,
|
||||
impl_cast_body,
|
||||
impl_cast_attribute,
|
||||
@ -596,7 +596,7 @@ CodeBody gen_ast_inlines()
|
||||
impl_cast_using,
|
||||
impl_cast_var,
|
||||
fmt_newline,
|
||||
def_pragma( txt_StrC("endregion generated AST/Code cast implementation")),
|
||||
def_pragma( txt("endregion generated AST/Code cast implementation")),
|
||||
fmt_newline
|
||||
));
|
||||
|
||||
|
@ -64,7 +64,7 @@
|
||||
#undef stringize
|
||||
#undef stringize
|
||||
#undef stringize_va
|
||||
#undef txt_StrC
|
||||
#undef txt
|
||||
|
||||
#undef GEN_TIME
|
||||
#undef gen_main
|
||||
|
@ -8,6 +8,20 @@ Generation, testing, and cleanup scripts for the test directory are found here a
|
||||
|
||||
Currently `refactor` only supports naive sort of *find and replace* feature set and will not be able to rename identifiers excluisvely to a specific context (such as only renaming member names of a specific struct, etc).
|
||||
|
||||
**Note: The following macros are used with specifiers and token parsing within the library:**
|
||||
|
||||
* global
|
||||
* internal
|
||||
* local_persist
|
||||
* forceinline
|
||||
* neverinline
|
||||
|
||||
IF they are changed the following files would need adjustment:
|
||||
|
||||
* `./project/enums/ESpecifier.csv`
|
||||
* `./project/enums/ETokType.csv`
|
||||
* `./project/helpers/helper.hpp`
|
||||
|
||||
## Build & Run Scripts
|
||||
|
||||
**`clean.ps1`**
|
||||
@ -17,7 +31,7 @@ Remove any generated content from the repository.
|
||||
Generate a version of gencpp where components are inlined directly to `gen.<hpp/cpp>` and `gen. <hpp/cpp>`
|
||||
Any heavily preprocessed code is not inlined and are instead generated using the code in the `helpers` directory.
|
||||
|
||||
**`singlheader.build.ps1`**
|
||||
**`singleheader.ps1`**
|
||||
Generate a single-header version of the library where all code that would normally good in the usual four files (see bootstrap) are inlined into a single `gen.hpp` file.
|
||||
As with the bootstrap, any heavily preprocessed code is not inlined and instead generated with helper code.
|
||||
|
||||
|
@ -10,6 +10,7 @@ $path_test_build = Join-Path $path_test build
|
||||
$path_gen = Join-Path $path_test gen
|
||||
$path_gen_build = Join-Path $path_gen build
|
||||
$path_x64 = Join-Path $path_root x64
|
||||
$path_release = Join-Path $path_root release
|
||||
|
||||
if ( Test-Path $path_project_build)
|
||||
{
|
||||
@ -46,22 +47,10 @@ if ( Test-Path $path_x64)
|
||||
Remove-Item $path_x64 -Recurse
|
||||
}
|
||||
|
||||
# [string[]] $include = 'gen.hpp', 'gen.cpp', 'gen_dep.hpp', 'gen_dep.cpp'
|
||||
# [string[]] $exclude =
|
||||
|
||||
# $files = Get-ChildItem -Recurse -Path $path_project_gen -Include $include -Exclude $exclude
|
||||
|
||||
# if ( $files )
|
||||
# {
|
||||
# Remove-Item $files
|
||||
# }
|
||||
|
||||
# $files = Get-ChildItem -Recurse -Path $path_singleheader_gen -Include $include -Exclude $exclude
|
||||
|
||||
# if ( $files )
|
||||
# {
|
||||
# Remove-Item $files
|
||||
# }
|
||||
if ( Test-Path $path_release )
|
||||
{
|
||||
Remove-Item $path_release -Recurse
|
||||
}
|
||||
|
||||
$include = '*.h', '*.hpp', '*.cpp'
|
||||
$exclude =
|
||||
|
@ -48,8 +48,8 @@
|
||||
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
|
||||
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
|
||||
<Item Name="Capacity">((Header*)((char*)Data - sizeof(Header)))->Capacity</Item>
|
||||
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
</Expand>
|
||||
|
@ -21,8 +21,8 @@
|
||||
// Gen Macro namespace
|
||||
// namespace GEN_, new_namespace_
|
||||
|
||||
// ---------- ZPL Macros
|
||||
|
||||
// ---------- Dependency Macros
|
||||
// Platform
|
||||
// word GEN_ARCH_64_BIT, new_name
|
||||
// word GEN_ARCH_32_BIT, new_name
|
||||
|
||||
@ -43,20 +43,86 @@
|
||||
// word GEN_COMPILER_MINGW, new_name
|
||||
// word GEN_COMPILER_MSVC, new_name
|
||||
|
||||
// word forceinline, new_name
|
||||
// word neverinline, new_name
|
||||
|
||||
// General
|
||||
// word zpl_cast, new_name
|
||||
|
||||
// word global, new_name
|
||||
// word internal, new_name
|
||||
// word local_persist, new_name
|
||||
// word forceinline, new_name
|
||||
// word neverinline, new_name
|
||||
|
||||
// word bit, new_name
|
||||
// word bitfield_is_equal, new_name
|
||||
|
||||
// word ccast, new_name
|
||||
// word pcast, new_name
|
||||
// word rcast, new_name
|
||||
// word scast, new_name
|
||||
|
||||
// word num_args, new_name
|
||||
// word num_args_impl, new_name
|
||||
|
||||
// word stringize, new_name
|
||||
// word stringize_va, new_name
|
||||
|
||||
// word do_once, new_name
|
||||
// word do_once_start, new_name
|
||||
// word do_once_end, new_name
|
||||
// word label_scope_start, new_name
|
||||
// word label_scope_end, new_name
|
||||
|
||||
// word count_of, new_name
|
||||
// word is_between, new_name
|
||||
// word min, new_name
|
||||
// word size_of, new_name
|
||||
// word offset_of, new_name
|
||||
// word swap, new_name
|
||||
|
||||
// Basic Types
|
||||
// word GEN_U8_MIN, new_name
|
||||
// word GEN_U8_MAX, new_name
|
||||
// word GEN_I8_MIN, new_name
|
||||
// word GEN_I8_MAX, new_name
|
||||
|
||||
// word GEN_U16_MIN, new_name
|
||||
// word GEN_U16_MAX, new_name
|
||||
// word GEN_I16_MIN, new_name
|
||||
// word GEN_I16_MAX, new_name
|
||||
|
||||
// word GEN_U32_MIN, new_name
|
||||
// word GEN_U32_MAX, new_name
|
||||
// word GEN_I32_MIN, new_name
|
||||
// word GEN_I32_MAX, new_name
|
||||
|
||||
// word GEN_U64_MIN, new_name
|
||||
// word GEN_U64_MAX, new_name
|
||||
// word GEN_I64_MIN, new_name
|
||||
// word GEN_I64_MAX, new_name
|
||||
|
||||
// word GEN_USIZE_MIN, new_name
|
||||
// word GEN_USIZE_MAX, new_name
|
||||
// word GEN_ISIZE_MIN, new_name
|
||||
// word GEN_ISIZE_MAX, new_name
|
||||
|
||||
// word GEN_F32_MIN, new_name
|
||||
// word GEN_F32_MAX, new_name
|
||||
// word GEN_F64_MIN, new_name
|
||||
// word GEN_F64_MAX, new_name
|
||||
|
||||
// Debug
|
||||
// word GEN_DEBUG_TRAP, new_name
|
||||
// word GEN_ASSERT, new_name
|
||||
// word GEN_ASSERT_MSG, new_name
|
||||
// word GEN_ASSERT_NOT_NULL, new_name
|
||||
// word GEN_PANIC, new_name
|
||||
// word GEN_FATAL, new_name
|
||||
|
||||
// Memory
|
||||
// word kilobytes, new_name
|
||||
// word megabytes, new_name
|
||||
// word gigabytes, new_name
|
||||
// word terabytes, new_name
|
||||
|
||||
// word zero_item, new_name
|
||||
// word zero_array, new_name
|
||||
@ -67,13 +133,11 @@
|
||||
// word malloc, new_name
|
||||
// word mfree, new_name
|
||||
|
||||
// word count_of, new_name
|
||||
// word is_between, new_name
|
||||
// word min, new_name
|
||||
// word size_of, new_name
|
||||
// word swap, new_name
|
||||
// Strings
|
||||
// word txt, new_name
|
||||
// word cast_to_strc, new_name
|
||||
|
||||
// ---------- ZPL Types
|
||||
// ---------- Dependency Types
|
||||
|
||||
// word b8, new_name
|
||||
// word b16, new_name
|
||||
@ -114,11 +178,11 @@
|
||||
// word FileStandardType, new_name
|
||||
// word SeekWhenceType, new_name
|
||||
|
||||
// ---------- ZPL Data
|
||||
// ---------- Dependency Data
|
||||
|
||||
// word default_file_operations, new_name
|
||||
|
||||
// ---------- ZPL Procedures
|
||||
// ---------- Dependency Procedures
|
||||
|
||||
// word align_forward, new_name
|
||||
// word align_fordward_i64, new_name
|
||||
@ -158,6 +222,7 @@
|
||||
// word hex_digit_to_int, new_name
|
||||
// word i64_to_str, new_name
|
||||
// word is_power_of_two, new_name
|
||||
// word log_fmt, new_name
|
||||
// word mem_copy, new_name
|
||||
// word mem_move, new_name
|
||||
// word mem_set, new_name
|
||||
@ -189,22 +254,10 @@
|
||||
|
||||
// ---------- gencpp Macros
|
||||
|
||||
// word bit, new_name
|
||||
// word bitfield_is_equal, new_name
|
||||
// word log_failure, new_name
|
||||
|
||||
// word ccast, new_name
|
||||
// word pcast, new_name
|
||||
// word rcast, new_name
|
||||
// word scast, new_name
|
||||
|
||||
// word do_once, new_name
|
||||
// word do_once_start, new_name
|
||||
// word do_once_end, new_name
|
||||
// word num_args, new_name
|
||||
// word num_args_impl, new_name
|
||||
// word stringize, new_name
|
||||
// word stringize_va, new_name
|
||||
// word txt_StrC, new_name
|
||||
// word NoCode, new_name
|
||||
// word CodeInvalid, new_name
|
||||
|
||||
// ------------ gencpp common
|
||||
|
||||
@ -215,16 +268,13 @@
|
||||
// word StrC, new_name
|
||||
// word String, new_name
|
||||
|
||||
// word log_fmt, new_name
|
||||
// word fatal, new_name
|
||||
// word to_str, new_name
|
||||
// word to_StrC, new_name
|
||||
// word to_str, new_name
|
||||
// word to_type, new_name
|
||||
|
||||
// ------------ gencpp Types & Constants
|
||||
|
||||
// word LogFailType, new_name
|
||||
// word log_failure, new_name
|
||||
|
||||
// word AccessSpec, new_name
|
||||
// word ECode, new_name
|
||||
@ -251,7 +301,6 @@
|
||||
// word Code, new_name
|
||||
// word Code_POD, new_name
|
||||
// word Keyword, new_name
|
||||
// word NoCode, new_name
|
||||
|
||||
// ------------ gencpp API
|
||||
|
||||
@ -277,6 +326,9 @@
|
||||
// word def_attributes, new_name
|
||||
// word def_comment, new_name
|
||||
// word def_class, new_name
|
||||
// word def_constructor, new_name
|
||||
// word def_destructor, new_name
|
||||
// word def_define, new_name
|
||||
// word def_enum, new_name
|
||||
// word def_execution, new_name
|
||||
// word def_extern_link, new_name
|
||||
@ -286,7 +338,10 @@
|
||||
// word def_module, new_name
|
||||
// word def_namespace, new_name
|
||||
// word def_operator, new_name
|
||||
// word def_operator_cast, new_name
|
||||
// word def_param, new_name
|
||||
// word def_pargma, new_name
|
||||
// word def_preprocess_cond, new_name
|
||||
// word def_specifier, new_name
|
||||
// word def_struct, new_name
|
||||
// word def_template, new_name
|
||||
@ -343,21 +398,23 @@
|
||||
// word untyped_fmt, new_name
|
||||
// word untyped_token_fmt, new_name
|
||||
|
||||
// ------------ File Handling
|
||||
// ------------ File Ops
|
||||
|
||||
// word Builder, new_name
|
||||
// word Editor, new_name
|
||||
// word Scanner, new_name
|
||||
|
||||
// ------------ gencpp macros
|
||||
// ------------ gencpp user macros
|
||||
|
||||
// word gen_main, new_name
|
||||
// word GEN_TIME, new_name
|
||||
|
||||
// word __, new_name
|
||||
// word code, new_name
|
||||
// word name, new_name
|
||||
// word code, new_name
|
||||
// word args, new_name
|
||||
// word code_str, new_name
|
||||
// word code_fmt, new_name
|
||||
// word token_fmt, new_name
|
||||
|
||||
// ------------ Type AST namespace
|
||||
|
41
scripts/package_release.ps1
Normal file
41
scripts/package_release.ps1
Normal file
@ -0,0 +1,41 @@
|
||||
cls
|
||||
Invoke-Expression "& $(Join-Path $PSScriptRoot 'bootstrap.ci.ps1')"
|
||||
Invoke-Expression "& $(Join-Path $PSScriptRoot 'singleheader.ci.ps1')"
|
||||
|
||||
$path_root = git rev-parse --show-toplevel
|
||||
$path_docs = Join-Path $path_root docs
|
||||
$path_project = Join-Path $path_root project
|
||||
$path_project_gen = Join-Path $path_project gen
|
||||
$path_singleheader = Join-Path $path_root singleheader
|
||||
$path_singleheader_gen = Join-Path $path_singleheader gen
|
||||
$path_release = Join-Path $path_root release
|
||||
$path_release_content = Join-Path $path_release content
|
||||
|
||||
if ( -not(Test-Path $path_release) ) {
|
||||
New-Item -ItemType Directory -Path $path_release
|
||||
}
|
||||
|
||||
if ( -not(Test-Path $path_release_content) ) {
|
||||
New-Item -ItemType Directory -Path $path_release_content
|
||||
}
|
||||
|
||||
$license = Join-Path $path_root LICENSE
|
||||
$readme_root = Join-Path $path_root Readme.md
|
||||
$readme_docs = Join-Path $path_docs Readme.md
|
||||
$readme_parsing = Join-Path $path_docs Parsing.md
|
||||
|
||||
Copy-Item $license -Destination $(Join-Path $path_release_content "LICENSE")
|
||||
Copy-Item $readme_root -Destination $(Join-Path $path_release_content "Readme.md")
|
||||
Copy-Item $readme_docs -Destination $(Join-Path $path_release_content "Readme_Docs.md")
|
||||
Copy-Item $readme_parsing -Destination $(Join-Path $path_release_content "Parsing.md")
|
||||
|
||||
# Singleheader
|
||||
Copy-Item -Path $path_singleheader_gen\gen.hpp -Destination $path_release_content\gen.hpp
|
||||
Compress-Archive -Path $path_release_content\* -DestinationPath $path_release\gencpp_singleheader.zip -Force
|
||||
Remove-Item -Path $path_release_content\gen.hpp
|
||||
|
||||
# Segmented
|
||||
Copy-Item -Path $path_project_gen\* -Destination $path_release_content
|
||||
Compress-Archive -Path $path_release_content\* -DestinationPath $path_release\gencpp_segmented.zip -Force
|
||||
|
||||
Remove-Item -Path $path_release_content -Recurse
|
@ -3,15 +3,16 @@
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#include "gen.cpp"
|
||||
|
||||
#include "helpers/push_ignores.inline.hpp"
|
||||
#include "helpers/helper.hpp"
|
||||
|
||||
GEN_NS_BEGIN
|
||||
#include "dependencies/parsing.cpp"
|
||||
GEN_NS_END
|
||||
|
||||
#include "file_processors/builder.hpp"
|
||||
#include "file_processors/builder.cpp"
|
||||
#include "file_processors/scanner.hpp"
|
||||
#include "auxillary/builder.hpp"
|
||||
#include "auxillary/builder.cpp"
|
||||
#include "auxillary/scanner.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
@ -19,25 +20,25 @@ constexpr char const* generation_notice =
|
||||
"// This file was generated automatially by gen.bootstrap.cpp "
|
||||
"(See: https://github.com/Ed94/gencpp)\n\n";
|
||||
|
||||
constexpr StrC implementation_guard_start = txt_StrC(R"(
|
||||
constexpr StrC implementation_guard_start = txt(R"(
|
||||
#pragma region GENCPP IMPLEMENTATION GUARD
|
||||
#if defined(GEN_IMPLEMENTATION) && ! defined(GEN_IMPLEMENTED)
|
||||
# define GEN_IMPLEMENTED
|
||||
)");
|
||||
|
||||
constexpr StrC implementation_guard_end = txt_StrC(R"(
|
||||
constexpr StrC implementation_guard_end = txt(R"(
|
||||
#endif
|
||||
#pragma endregion GENCPP IMPLEMENTATION GUARD
|
||||
)");
|
||||
|
||||
constexpr StrC roll_own_dependencies_guard_start = txt_StrC(R"(
|
||||
constexpr StrC roll_own_dependencies_guard_start = txt(R"(
|
||||
//! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file.
|
||||
// Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl
|
||||
#ifndef GEN_ROLL_OWN_DEPENDENCIES
|
||||
|
||||
)");
|
||||
|
||||
constexpr StrC roll_own_dependencies_guard_end = txt_StrC(R"(
|
||||
constexpr StrC roll_own_dependencies_guard_end = txt(R"(
|
||||
// GEN_ROLL_OWN_DEPENDENCIES
|
||||
#endif
|
||||
)");
|
||||
@ -77,8 +78,8 @@ int gen_main()
|
||||
Code printing = scan_file( project_dir "dependencies/printing.hpp" );
|
||||
Code containers = scan_file( project_dir "dependencies/containers.hpp" );
|
||||
Code hashing = scan_file( project_dir "dependencies/hashing.hpp" );
|
||||
Code string = scan_file( project_dir "dependencies/string.hpp" );
|
||||
Code file_handling = scan_file( project_dir "dependencies/file_handling.hpp" );
|
||||
Code strings = scan_file( project_dir "dependencies/strings.hpp" );
|
||||
Code filesystem = scan_file( project_dir "dependencies/filesystem.hpp" );
|
||||
Code timing = scan_file( project_dir "dependencies/timing.hpp" );
|
||||
|
||||
header.print_fmt( roll_own_dependencies_guard_start );
|
||||
@ -93,8 +94,8 @@ int gen_main()
|
||||
header.print( printing );
|
||||
header.print( containers );
|
||||
header.print( hashing );
|
||||
header.print( string );
|
||||
header.print( file_handling );
|
||||
header.print( strings );
|
||||
header.print( filesystem );
|
||||
header.print( timing );
|
||||
|
||||
if ( generate_scanner )
|
||||
@ -106,6 +107,7 @@ int gen_main()
|
||||
|
||||
header.print_fmt( "GEN_NS_END\n" );
|
||||
header.print_fmt( roll_own_dependencies_guard_end );
|
||||
header.print( fmt_newline );
|
||||
}
|
||||
|
||||
Code types = scan_file( project_dir "components/types.hpp" );
|
||||
@ -146,14 +148,14 @@ int gen_main()
|
||||
if ( generate_builder )
|
||||
{
|
||||
header.print_fmt( "#pragma region Builder\n\n" );
|
||||
header.print( scan_file( project_dir "file_processors/builder.hpp" ) );
|
||||
header.print( scan_file( project_dir "auxillary/builder.hpp" ) );
|
||||
header.print_fmt( "#pragma endregion Builder\n\n" );
|
||||
}
|
||||
|
||||
if ( generate_scanner )
|
||||
{
|
||||
header.print_fmt( "#pragma region Scanner\n\n" );
|
||||
header.print( scan_file( project_dir "file_processors/scanner.hpp" ) );
|
||||
header.print( scan_file( project_dir "auxillary/scanner.hpp" ) );
|
||||
header.print_fmt( "#pragma endregion Scanner\n\n" );
|
||||
}
|
||||
|
||||
@ -172,8 +174,8 @@ int gen_main()
|
||||
Code printing = scan_file( project_dir "dependencies/printing.cpp" );
|
||||
Code memory = scan_file( project_dir "dependencies/memory.cpp" );
|
||||
Code hashing = scan_file( project_dir "dependencies/hashing.cpp" );
|
||||
Code string = scan_file( project_dir "dependencies/string.cpp" );
|
||||
Code file_handling = scan_file( project_dir "dependencies/file_handling.cpp" );
|
||||
Code strings = scan_file( project_dir "dependencies/strings.cpp" );
|
||||
Code filesystem = scan_file( project_dir "dependencies/filesystem.cpp" );
|
||||
Code timing = scan_file( project_dir "dependencies/timing.cpp" );
|
||||
|
||||
header.print_fmt( roll_own_dependencies_guard_start );
|
||||
@ -185,8 +187,8 @@ int gen_main()
|
||||
header.print( printing );
|
||||
header.print( memory );
|
||||
header.print( hashing );
|
||||
header.print( string );
|
||||
header.print( file_handling );
|
||||
header.print( strings );
|
||||
header.print( filesystem );
|
||||
header.print( timing );
|
||||
|
||||
if ( generate_scanner )
|
||||
@ -232,7 +234,7 @@ int gen_main()
|
||||
if ( generate_builder )
|
||||
{
|
||||
header.print_fmt( "#pragma region Builder\n\n" );
|
||||
header.print( scan_file( project_dir "file_processors/builder.cpp" ) );
|
||||
header.print( scan_file( project_dir "auxillary/builder.cpp" ) );
|
||||
header.print_fmt( "#pragma endregion Builder\n\n" );
|
||||
}
|
||||
|
||||
@ -240,7 +242,7 @@ int gen_main()
|
||||
if ( generate_scanner )
|
||||
{
|
||||
header.print_fmt( "#pragma region Scanner\n\n" );
|
||||
header.print( scan_file( project_dir "file_processors/scanner.cpp" ) );
|
||||
header.print( scan_file( project_dir "auxillary/scanner.cpp" ) );
|
||||
header.print_fmt( "#pragma endregion Scanner\n\n" );
|
||||
}
|
||||
#endif
|
||||
|
@ -33,7 +33,7 @@ Code gen_SOA( CodeStruct struct_def, s32 num_entries = 0 )
|
||||
if ( struct_mem->Type == ECode::Variable )
|
||||
{
|
||||
CodeType var_type = struct_mem.cast<CodeVar>()->ValueType;
|
||||
StrC num_entries_str = to_StrC( str_fmt_buf( "%d", num_entries ) );
|
||||
StrC num_entries_str = to_str( str_fmt_buf( "%d", num_entries ) );
|
||||
|
||||
CodeVar entry_arr = { nullptr };
|
||||
if ( ! num_entries)
|
||||
@ -124,7 +124,7 @@ void check_SOA()
|
||||
soa_test.print( parse_using( code(
|
||||
using u16 = unsigned short;
|
||||
)));
|
||||
soa_test.print( def_include( txt_StrC("gen.hpp")));
|
||||
soa_test.print( def_include( txt("gen.hpp")));
|
||||
soa_test.print( def_using_namespace( name(gen) ) );
|
||||
|
||||
soa_test.print( gen_SOA(
|
||||
|
@ -255,7 +255,7 @@ u32 gen_array_file()
|
||||
gen_array_file;
|
||||
gen_array_file.open( "array.Parsed.gen.hpp" );
|
||||
|
||||
Code include_gen = def_include( txt_StrC("gen.hpp") );
|
||||
Code include_gen = def_include( txt("gen.hpp") );
|
||||
gen_array_file.print( include_gen );
|
||||
|
||||
gen_array_file.print( def_using_namespace( name(gen)));
|
||||
|
@ -169,7 +169,7 @@ u32 gen_buffer_file()
|
||||
gen_buffer_file;
|
||||
gen_buffer_file.open( "buffer.Parsed.gen.hpp" );
|
||||
|
||||
gen_buffer_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_buffer_file.print( def_include( txt("gen.hpp")) );
|
||||
gen_buffer_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
gen_buffer_file.print( gen__buffer_base() );
|
||||
|
@ -320,9 +320,9 @@ u32 gen_hashtable_file()
|
||||
gen_hashtable_file;
|
||||
gen_hashtable_file.open( "hashtable.Parsed.gen.hpp" );
|
||||
|
||||
gen_hashtable_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt_StrC("Array.Parsed.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt_StrC("array.Parsed.gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt("gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt("Array.Parsed.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt("array.Parsed.gen.hpp")) );
|
||||
|
||||
gen_hashtable_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
|
@ -22,7 +22,7 @@ Code gen__ring( StrC type )
|
||||
name = get_cached_string({ name_len, name_str });
|
||||
};
|
||||
|
||||
StrC buffer_name = to_StrC( str_fmt_buf( "Buffer_%s", type.Ptr ));
|
||||
StrC buffer_name = to_str( str_fmt_buf( "Buffer_%s", type.Ptr ));
|
||||
|
||||
Code ring = parse_struct( token_fmt( "RingName", (StrC)name, "type", type, "BufferName", buffer_name,
|
||||
stringize(
|
||||
@ -138,8 +138,8 @@ u32 gen_ring_file()
|
||||
gen_ring_file;
|
||||
gen_ring_file.open( "ring.Parsed.gen.hpp" );
|
||||
|
||||
gen_ring_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt_StrC("buffer.Parsed.gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt("gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt("buffer.Parsed.gen.hpp")) );
|
||||
// gen_ring_file.print( gen__ring_base() );
|
||||
|
||||
gen_ring_file.print( def_using_namespace( name(gen)));
|
||||
|
@ -14,7 +14,7 @@ u32 gen_sanity()
|
||||
gen_sanity_file;
|
||||
gen_sanity_file.open("./sanity.Parsed.gen.hpp");
|
||||
|
||||
gen_sanity_file.print( def_comment( txt_StrC(
|
||||
gen_sanity_file.print( def_comment( txt(
|
||||
"The following will show a series of base cases for the gen parsed api.\n"
|
||||
)));
|
||||
|
||||
@ -40,7 +40,7 @@ u32 gen_sanity()
|
||||
{};
|
||||
));
|
||||
|
||||
empty_body->Body.append( def_comment( txt_StrC("Empty class body") ) );
|
||||
empty_body->Body.append( def_comment( txt("Empty class body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(empty_body);
|
||||
@ -76,7 +76,7 @@ u32 gen_sanity()
|
||||
|
||||
// External Linkage
|
||||
{
|
||||
CodeComment empty_comment = def_comment( txt_StrC("Empty external linkage") );
|
||||
CodeComment empty_comment = def_comment( txt("Empty external linkage") );
|
||||
|
||||
CodeExtern c_extern = parse_extern_link( code(
|
||||
extern "C"
|
||||
@ -122,7 +122,7 @@ u32 gen_sanity()
|
||||
}
|
||||
));
|
||||
|
||||
def->Body.append( def_comment( txt_StrC("Empty function body") ) );
|
||||
def->Body.append( def_comment( txt("Empty function body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(def);
|
||||
@ -138,7 +138,7 @@ u32 gen_sanity()
|
||||
}
|
||||
));
|
||||
|
||||
def->Body.append( def_comment( txt_StrC("Empty namespace body") ) );
|
||||
def->Body.append( def_comment( txt("Empty namespace body") ) );
|
||||
|
||||
gen_sanity_file.print(def);
|
||||
}
|
||||
@ -205,7 +205,7 @@ u32 gen_sanity()
|
||||
}
|
||||
));
|
||||
|
||||
def->Body.append( def_comment( txt_StrC("Empty function body") ) );
|
||||
def->Body.append( def_comment( txt("Empty function body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(def);
|
||||
@ -241,7 +241,7 @@ u32 gen_sanity()
|
||||
{};
|
||||
));
|
||||
|
||||
empty_body->Body.append( def_comment( txt_StrC("Empty struct body") ) );
|
||||
empty_body->Body.append( def_comment( txt("Empty struct body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(empty_body);
|
||||
@ -257,7 +257,7 @@ u32 gen_sanity()
|
||||
};
|
||||
));
|
||||
|
||||
empty->Body.append( def_comment( txt_StrC("Empty union body") ) );
|
||||
empty->Body.append( def_comment( txt("Empty union body") ) );
|
||||
|
||||
gen_sanity_file.print( parse_typedef( code( typedef unsigned short u16; )) );
|
||||
gen_sanity_file.print( parse_typedef( code( typedef unsigned long u32; )) );
|
||||
@ -334,7 +334,7 @@ u32 gen_sanity()
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
gen_sanity_file.print( def_comment( txt_StrC(
|
||||
gen_sanity_file.print( def_comment( txt(
|
||||
"End of base case tests\n"
|
||||
)));
|
||||
|
||||
|
@ -43,7 +43,7 @@ int gen_main()
|
||||
using u16 = unsigned short;
|
||||
)));
|
||||
|
||||
soa_test.print( def_include( txt_StrC("gen.hpp")));
|
||||
soa_test.print( def_include( txt("gen.hpp")));
|
||||
|
||||
soa_test.print( def_using_namespace( name(gen) ) );
|
||||
|
||||
|
@ -17,7 +17,7 @@ void check_sanity()
|
||||
CodeType t_int_dupe = def_type( name(int) );
|
||||
|
||||
if ( t_int_dupe->Name != t_int->Name )
|
||||
fatal("check_sanity: String caching failed!");
|
||||
GEN_FATAL("check_sanity: String caching failed!");
|
||||
|
||||
|
||||
// Purposefully uses an excessive amount of memory to make sure the the memory backend doesn't break.
|
||||
|
@ -336,7 +336,7 @@ u32 gen_array_file()
|
||||
gen_array_file;
|
||||
gen_array_file.open( "array.Upfront.gen.hpp" );
|
||||
|
||||
CodeInclude include_gen = def_include( txt_StrC("gen.hpp") );
|
||||
CodeInclude include_gen = def_include( txt("gen.hpp") );
|
||||
gen_array_file.print( include_gen );
|
||||
|
||||
gen_array_file.print( def_using_namespace( name(gen)));
|
||||
|
@ -239,7 +239,7 @@ u32 gen_buffer_file()
|
||||
gen_buffer_file;
|
||||
gen_buffer_file.open( "buffer.Upfront.gen.hpp" );
|
||||
|
||||
gen_buffer_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_buffer_file.print( def_include( txt("gen.hpp")) );
|
||||
gen_buffer_file.print( def_using_namespace( name(gen)) );
|
||||
|
||||
gen_buffer_file.print( gen__buffer_base() );
|
||||
|
@ -447,9 +447,9 @@ u32 gen_hashtable_file()
|
||||
gen_hashtable_file;
|
||||
gen_hashtable_file.open( "hashtable.Upfront.gen.hpp" );
|
||||
|
||||
gen_hashtable_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt_StrC("Array.Upfront.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt_StrC("array.Upfront.gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt("gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt("Array.Upfront.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt("array.Upfront.gen.hpp")) );
|
||||
|
||||
gen_hashtable_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
|
@ -192,8 +192,8 @@ u32 gen_ring_file()
|
||||
gen_ring_file;
|
||||
gen_ring_file.open( "ring.Upfront.gen.hpp" );
|
||||
|
||||
gen_ring_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt_StrC("buffer.Upfront.gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt("gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt("buffer.Upfront.gen.hpp")) );
|
||||
|
||||
gen_ring_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
|
@ -11,13 +11,13 @@ u32 gen_sanity_upfront()
|
||||
|
||||
// Comment
|
||||
{
|
||||
CodeComment comment_test = def_comment( txt_StrC("Sanity check: def_comment test") );
|
||||
CodeComment comment_test = def_comment( txt("Sanity check: def_comment test") );
|
||||
|
||||
gen_sanity_file.print(comment_test);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
gen_sanity_file.print( def_comment( txt_StrC(
|
||||
gen_sanity_file.print( def_comment( txt(
|
||||
"The following will show a series of base cases for the gen api.\n"
|
||||
)));
|
||||
|
||||
@ -26,7 +26,7 @@ u32 gen_sanity_upfront()
|
||||
CodeClass fwd = def_class( name(TestEmptyClass) );
|
||||
CodeClass empty_body;
|
||||
{
|
||||
CodeComment cmt = def_comment( txt_StrC("Empty class body") );
|
||||
CodeComment cmt = def_comment( txt("Empty class body") );
|
||||
CodeBody body = def_class_body( args( cmt ) );
|
||||
|
||||
empty_body = def_class( name(TestEmptyClass), body );
|
||||
@ -74,7 +74,7 @@ u32 gen_sanity_upfront()
|
||||
// External Linkage
|
||||
{
|
||||
CodeBody body = def_extern_link_body( 1
|
||||
, def_comment( txt_StrC("Empty extern body") )
|
||||
, def_comment( txt("Empty extern body") )
|
||||
);
|
||||
|
||||
CodeExtern c_extern = def_extern_link( name(C), body );
|
||||
@ -100,7 +100,7 @@ u32 gen_sanity_upfront()
|
||||
CodeFn def;
|
||||
{
|
||||
CodeBody body = def_function_body( 1
|
||||
, def_comment( txt_StrC("Empty function body") )
|
||||
, def_comment( txt("Empty function body") )
|
||||
);
|
||||
|
||||
def = def_function( name(test_function), __, __, body );
|
||||
@ -114,7 +114,7 @@ u32 gen_sanity_upfront()
|
||||
|
||||
// Include
|
||||
{
|
||||
CodeInclude include = def_include( txt_StrC("../DummyInclude.hpp") );
|
||||
CodeInclude include = def_include( txt("../DummyInclude.hpp") );
|
||||
|
||||
gen_sanity_file.print(include);
|
||||
}
|
||||
@ -142,7 +142,7 @@ u32 gen_sanity_upfront()
|
||||
CodeNS namespace_def;
|
||||
{
|
||||
CodeBody body = def_namespace_body( 1
|
||||
, def_comment( txt_StrC("Empty namespace body") )
|
||||
, def_comment( txt("Empty namespace body") )
|
||||
);
|
||||
|
||||
namespace_def = def_namespace( name(TestNamespace), body );
|
||||
@ -213,7 +213,7 @@ u32 gen_sanity_upfront()
|
||||
CodeFn def, def2;
|
||||
{
|
||||
CodeBody body = def_function_body( 1
|
||||
, def_comment( txt_StrC("Empty function body") )
|
||||
, def_comment( txt("Empty function body") )
|
||||
);
|
||||
|
||||
CodeParam params = def_params( args(
|
||||
@ -259,7 +259,7 @@ u32 gen_sanity_upfront()
|
||||
CodeClass fwd = def_class( name(TestEmptyStruct) );
|
||||
CodeClass empty_body;
|
||||
{
|
||||
CodeComment cmt = def_comment( txt_StrC("Empty struct body") );
|
||||
CodeComment cmt = def_comment( txt("Empty struct body") );
|
||||
CodeBody body = def_class_body( args( cmt ) );
|
||||
|
||||
empty_body = def_class( name(TestEmptyStruct), body );
|
||||
@ -274,7 +274,7 @@ u32 gen_sanity_upfront()
|
||||
// Union
|
||||
{
|
||||
CodeBody body = def_union_body( 1
|
||||
, def_comment( txt_StrC("Empty union body") )
|
||||
, def_comment( txt("Empty union body") )
|
||||
);
|
||||
|
||||
CodeUnion def = def_union( name(TestEmptyUnion), body );
|
||||
@ -312,7 +312,7 @@ u32 gen_sanity_upfront()
|
||||
|
||||
CodeTemplate tmpl = def_template( def_param( t_class, name(Type) )
|
||||
, def_function( name(test_template), def_param( t_Type, name(a) ), __
|
||||
, def_function_body(1, def_comment( txt_StrC("Empty template function body")))
|
||||
, def_function_body(1, def_comment( txt("Empty template function body")))
|
||||
)
|
||||
);
|
||||
|
||||
@ -321,7 +321,7 @@ u32 gen_sanity_upfront()
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
gen_sanity_file.print( def_comment( txt_StrC(
|
||||
gen_sanity_file.print( def_comment( txt(
|
||||
"End of base case tests.\n"
|
||||
)));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user