39 Commits

Author SHA1 Message Date
Ed_
16b8a3a164 began to remove usage of code specific types member procs 2024-12-02 04:12:09 -05:00
Ed_
5b0079fb0c ast interface uage reductions 2024-12-02 03:18:52 -05:00
Ed_
9321a04ebc reduction of Code struct member function usage in base lib 2024-12-02 02:38:55 -05:00
Ed_
9b68791e38 fixes for array when not using member features. 2024-12-02 02:11:49 -05:00
Ed_
2dcc968c39 Preparing for reductions on code_types.hpp 2024-12-02 01:56:49 -05:00
Ed_
c38b077c37 Code::set_global reduction 2024-12-02 00:43:57 -05:00
Ed_
f9b5029e64 Code::is_valid rection 2024-12-02 00:41:41 -05:00
Ed_
2b24511f7d Code::is_equal reduction 2024-12-02 00:34:40 -05:00
Ed_
5cd69e1742 Code::is_body reduction 2024-12-02 00:18:54 -05:00
Ed_
007bfa0cb0 Code::duplicate reduction 2024-12-02 00:16:11 -05:00
Ed_
37c33ffb3e reduction on debug_str 2024-12-02 00:10:24 -05:00
Ed_
937235b776 progress (Code) 2024-12-02 00:03:38 -05:00
Ed_
f9c21ebc04 progress 2024-12-01 23:35:58 -05:00
Ed_
fec709cc76 Progresss 2024-12-01 21:59:43 -05:00
Ed_
80cb3f4eca Significant progress reducing c++ feature usage in the library. 2024-12-01 18:50:37 -05:00
Ed_
9e88cb8724 String::is_equal added (bad last commit) 2024-12-01 13:29:33 -05:00
Ed_
f61c1c560d String::is_equal added 2024-12-01 13:29:16 -05:00
Ed_
8ef982003a Added is_body to AST and Code types 2024-12-01 12:48:58 -05:00
Ed_
31691b1466 Fixed issue with HashTable region detection 2024-12-01 05:37:03 -05:00
Ed_
ed0c0422ad Looking into what the library's convention for enums will be.
Most likely will just reduce them to C-enums with underlying type.
Otherwise there has to be a mechanism to drop the defs down to them anyways, and eliminate the namespace wraps.
2024-12-01 05:30:37 -05:00
Ed_
e5acac1d18 String member definitions not longer used in the base project 2024-12-01 03:06:30 -05:00
Ed_
c7b072266f progress on c_library.cpp 2024-12-01 01:40:31 -05:00
Ed_
a96d03eaed brought over the generators of array and hashtable for c-lib gen
From the old genc repo. Still need to fully check that its code is up to date
2024-12-01 01:40:14 -05:00
Ed_
0b4ccac8f9 Removed usage of hashtable member procs 2024-12-01 01:39:21 -05:00
Ed_
31a3609b28 some fixes to c's fixed_arena gen 2024-11-30 23:48:14 -05:00
Ed_
fbdb870986 Finished first pass reviewing memory.hpp for C lib generation 2024-11-30 23:38:27 -05:00
Ed_
6d04165b96 Reduce cpp freatures usage of Array container.
Almost ready to be inter-operable with C
2024-11-30 18:54:19 -05:00
Ed_
cc245cc263 new files 2024-11-30 17:22:06 -05:00
Ed_
06deb1e836 memory.hpp no longer uses memory mappings by default 2024-11-30 17:18:49 -05:00
Ed_
5527a27f7b prepare c_library meta-program a bit 2024-11-30 16:54:03 -05:00
Ed_
a67fdef20a dir restructuring
just making it more organized (gen_ prefix for library generation meta-programs)
2024-11-30 16:50:53 -05:00
Ed_
056a5863b8 for the future... 2024-11-30 14:34:28 -05:00
Ed_
79eb5f1f76 strings done 2024-11-30 14:13:30 -05:00
Ed_
c6cb583518 Hashtable done 2024-11-30 13:31:59 -05:00
Ed_
34eec66f35 Array done 2024-11-30 13:14:47 -05:00
Ed_
4137ebfbd8 pool done (see previous commits for context) 2024-11-30 12:27:54 -05:00
Ed_
5958dd2055 Did arena and fixedarena changes (for reducing usage of member procs) 2024-11-30 12:16:01 -05:00
Ed_
163ad0a511 looking into removing "oop" features from base library
I want to make member functions an optional addition the user can generate a derivative library with.
The purpose is to simplify the implementation as to make generating a C-variant simpiler.

I also want to use it as a study to see how much simpiler it makes the library without having it.
2024-11-29 15:18:06 -05:00
Ed_
e3c2a577ba addded String::contains defs 2024-11-29 14:50:54 -05:00
59 changed files with 5120 additions and 4397 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ project/auxillary/vis_ast/dependencies/temp
test/gen/original test/gen/original
singleheader/gen/scratch.hpp singleheader/gen/scratch.hpp
test/gen/scratch.cpp test/gen/scratch.cpp
gen_c_library/gen

View File

@ -37,7 +37,10 @@
"propidl.h": "c", "propidl.h": "c",
"android_native_app_glue.h": "c", "android_native_app_glue.h": "c",
"raylib.h": "c", "raylib.h": "c",
"*.m": "cpp" "*.m": "cpp",
"atomic": "cpp",
"gen.h": "c",
"string_ops.hpp": "c"
}, },
"C_Cpp.intelliSenseEngineFallback": "disabled", "C_Cpp.intelliSenseEngineFallback": "disabled",
"mesonbuild.configureOnOpen": true, "mesonbuild.configureOnOpen": true,

View File

@ -552,7 +552,7 @@ Serialization:
Fields: Fields:
```cpp ```cpp
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ]; SpecifierT ArrSpecs[ AST_ArrSpecs_Cap ];
CodeSpecifiers NextSpecs; CodeSpecifiers NextSpecs;
Code Prev; Code Prev;
Code Next; Code Next;

View File

@ -25,6 +25,8 @@ This library was written in a subset of C++ where the following are not used at
* Exceptions * Exceptions
Polymorphic & Member-functions are used as an ergonomic choice, along with a conserative use of operator overloads. Polymorphic & Member-functions are used as an ergonomic choice, along with a conserative use of operator overloads.
The base library itself does not use anything but C-like features to allow for generating a derviative compatiable with C (WIP).
There are only 4 template definitions in the entire library. (`Array<Type>`, `Hashtable<Type>`, `swap<Type>`, and `AST/Code::cast<Type>`) There are only 4 template definitions in the entire library. (`Array<Type>`, `Hashtable<Type>`, `swap<Type>`, and `AST/Code::cast<Type>`)
Two generic templated containers are used throughout the library: Two generic templated containers are used throughout the library:
@ -99,7 +101,7 @@ union {
}; };
StringCached Content; // Attributes, Comment, Execution, Include StringCached Content; // Attributes, Comment, Execution, Include
struct { struct {
SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers SpecifierT ArrSpecs[AST_ArrSpecs_Cap]; // Specifiers
AST* NextSpecs; // Specifiers AST* NextSpecs; // Specifiers
}; };
}; };

398
gen_c_library/c_library.cpp Normal file
View File

@ -0,0 +1,398 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_SUPPORT_CPP_MEMBER_FEATURES 1
#define GEN_SUPPORT_CPP_REFERENCES 1
#include "../project/gen.cpp"
#include "helpers/push_ignores.inline.hpp"
#include "helpers/helper.hpp"
GEN_NS_BEGIN
#include "dependencies/parsing.cpp"
GEN_NS_END
#include "auxillary/builder.hpp"
#include "auxillary/builder.cpp"
#include "auxillary/scanner.hpp"
#include <cstdlib> // for system()
#include "components/memory.fixed_arena.hpp"
#include "components/misc.hpp"
#include "components/containers.array.hpp"
#include "components/containers.hashtable.hpp"
using namespace gen;
constexpr char const* generation_notice =
"// This file was generated automatially by gencpp's c_library.cpp"
"(See: https://github.com/Ed94/gencpp)\n\n";
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(R"(
// GEN_ROLL_OWN_DEPENDENCIES
#endif
)");
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(R"(
#endif
#pragma endregion GENCPP IMPLEMENTATION GUARD
)");
void format_file( char const* path )
{
String resolved_path = String::make(GlobalAllocator, to_str(path));
String style_arg = String::make(GlobalAllocator, txt("-style=file:"));
style_arg.append("../scripts/.clang-format ");
// Need to execute clang format on the generated file to get it to match the original.
#define clang_format "clang-format "
#define cf_format_inplace "-i "
#define cf_verbose "-verbose "
String command = String::make( GlobalAllocator, clang_format );
command.append( cf_format_inplace );
command.append( cf_verbose );
command.append( style_arg );
command.append( resolved_path );
log_fmt("\tRunning clang-format on file:\n");
system( command );
log_fmt("\tclang-format finished reformatting.\n");
#undef cf_cmd
#undef cf_format_inplace
#undef cf_style
#undef cf_verbse
}
Code dump_to_scratch_and_retireve( Code code )
{
Builder ecode_file_temp = Builder::open("gen/scratch.hpp");
ecode_file_temp.print(code);
ecode_file_temp.write();
format_file("gen/scratch.hpp");
Code result = scan_file( "gen/scratch.hpp" );
remove("gen/scratch.hpp");
return result;
}
CodeBody parse_file( const char* path )
{
FileContents file = file_read_contents( GlobalAllocator, true, path );
CodeBody code = parse_global_body( { file.size, (char const*)file.data } );
log_fmt("\nParsed: %s\n", path);
return code;
}
int gen_main()
{
#define project_dir "../project/"
gen::init();
Code push_ignores = scan_file( project_dir "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( project_dir "helpers/pop_ignores.inline.hpp" );
Code c_library_header_start = scan_file( "components/header_start.hpp" );
Builder
header = Builder::open( "gen/gen.h" );
header.print_fmt( generation_notice );
header.print_fmt("#pragma once\n\n");
header.print( push_ignores );
// Headers
{
header.print( c_library_header_start );
Code platform = scan_file( project_dir "dependencies/platform.hpp" );
Code macros = scan_file( project_dir "dependencies/macros.hpp" );
Code basic_types = scan_file( project_dir "dependencies/basic_types.hpp" );
Code debug = scan_file( project_dir "dependencies/debug.hpp" );
header.print_fmt( roll_own_dependencies_guard_start );
header.print( platform );
header.print_fmt( "\nGEN_NS_BEGIN\n" );
header.print( macros );
header.print( basic_types );
header.print( debug );
CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" );
CodeBody memory = def_body(ECode::Global_Body);
for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry )
{
switch (entry->Type)
{
case ECode::Using:
{
log_fmt("REPLACE THIS MANUALLY: %S\n", entry->Name);
CodeUsing using_ver = cast(CodeUsing, entry);
CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType);
memory.append(typedef_ver);
}
break;
case ECode::Function_Fwd:
{
CodeFn fn = cast(CodeFn, entry);
if ( fn->Name.is_equal(txt("free")) )
{
fn->Name = get_cached_string(txt("gen_free_ptr"));
}
memory.append(entry);
}
break;
case ECode::Function:
{
CodeFn fn = cast(CodeFn, entry);
s32 constexpr_found = fn->Specs.remove( ESpecifier::Constexpr );
if (constexpr_found > -1) {
log_fmt("Found constexpr: %S\n", entry->to_string());
fn->Specs.append(ESpecifier::Inline);
}
if ( fn->Name.is_equal(txt("free")) )
{
fn->Name = get_cached_string(txt("gen_free_ptr"));
}
memory.append(entry);
}
break;
case ECode::Template:
{
CodeTemplate tmpl = cast(CodeTemplate, entry);
if ( tmpl->Declaration->Name.contains(txt("swap")))
{
CodeBody macro_swap = parse_global_body( txt(R"(
#define swap( a, b ) \
do \
{ \
typeof( a ) temp = ( a ); \
( a ) = ( b ); \
( b ) = temp; \
} while ( 0 )
)"
));
memory.append(macro_swap);
}
}
break;
case ECode::Class:
case ECode::Struct:
{
CodeBody body = entry->Body->operator CodeBody();
CodeBody new_body = def_body( entry->Body->Type );
for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch
(body_entry->Type) {
case ECode::Preprocess_If:
{
ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), body_entry, body );
}
break;
default:
new_body.append(body_entry);
break;
}
entry->Body = rcast(AST*, new_body.ast);
memory.append(entry);
}
break;
case ECode::Preprocess_If:
{
b32 found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), entry, parsed_memory );
if (found) break;
memory.append(entry);
}
break;
case ECode::Preprocess_IfDef:
{
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_memory );
if (found) break;
memory.append(entry);
}
break;
case ECode::Preprocess_Pragma:
{
b32 found = swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory);
if (found) break;
memory.append(entry);
}
break;
default: {
memory.append(entry);
}
break;
}
}
header.print( dump_to_scratch_and_retireve(memory) );
Code string_ops = scan_file( project_dir "dependencies/string_ops.hpp" );
header.print( string_ops );
CodeBody printing_parsed = parse_file( project_dir "dependencies/printing.hpp" );
CodeBody printing = def_body(ECode::Global_Body);
for ( Code entry = printing_parsed.begin(); entry != printing_parsed.end(); ++ entry )
{
switch (entry->Type)
{
case ECode::Preprocess_IfDef:
{
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, printing_parsed );
if (found) break;
printing.append(entry);
}
break;
case ECode::Variable:
{
if (contains(entry->Name, txt("Msg_Invalid_Value")))
{
CodeDefine define = def_define(entry->Name, entry->Value->Content);
printing.append(define);
continue;
}
printing.append(entry);
}
break;
default:
printing.append(entry);
break;
}
}
header.print(dump_to_scratch_and_retireve(printing));
CodeBody containers = def_body(ECode::Global_Body);
{
containers.append( def_pragma(code(region Containers)));
containers.append( gen_array_base() );
containers.append( gen_hashtable_base() );
containers.append( def_pragma(code(endregion Containers)));
}
header.print(fmt_newline);
header.print(dump_to_scratch_and_retireve(containers));
Code hashing = scan_file( project_dir "dependencies/hashing.hpp" );
header.print( hashing );
CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" );
CodeBody strings = def_body(ECode::Global_Body);
for ( Code entry = parsed_strings.begin(); entry != parsed_strings.end(); ++ entry )
{
switch (entry->Type)
{
case ECode::Preprocess_If:
{
ignore_preprocess_cond_block(txt("! GEN_COMPILER_C"), entry, parsed_strings);
}
break;
case ECode::Preprocess_IfDef:
{
ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_strings );
}
break;
case ECode::Struct_Fwd:
{
if ( entry->Name.is_equal(txt("String")) )
{
CodeTypedef c_def = parse_typedef(code( typedef char* String; ));
strings.append(c_def);
strings.append(fmt_newline);
++ entry;
continue;
}
strings.append(entry);
}
break;
case ECode::Struct:
{
CodeBody body = entry->Body->operator CodeBody();
CodeBody new_body = def_body( entry->Body->Type );
for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch
(body_entry->Type) {
case ECode::Preprocess_If:
{
b32 found = ignore_preprocess_cond_block(txt("! GEN_COMPILER_C"), body_entry, body );
if (found) break;
new_body.append(body_entry);
}
break;
default:
new_body.append(body_entry);
break;
}
entry->Body = rcast(AST*, new_body.ast);
strings.append(entry);
}
break;
default:
strings.append(entry);
break;
}
}
header.print(dump_to_scratch_and_retireve(strings));
Code filesystem = scan_file( project_dir "dependencies/filesystem.hpp" );
Code timing = scan_file( project_dir "dependencies/timing.hpp" );
// header.print( filesystem );
// header.print( timing );
header.print_fmt( "\nGEN_NS_END\n" );
header.print_fmt( roll_own_dependencies_guard_end );
Code types = scan_file( project_dir "components/types.hpp" );
Code ast = scan_file( project_dir "components/ast.hpp" );
Code ast_types = scan_file( project_dir "components/ast_types.hpp" );
Code code_types = scan_file( project_dir "components/code_types.hpp" );
Code interface = scan_file( project_dir "components/interface.hpp" );
Code inlines = scan_file( project_dir "components/inlines.hpp" );
Code header_end = scan_file( project_dir "components/header_end.hpp" );
CodeBody ecode = gen_ecode ( project_dir "enums/ECode.csv" );
CodeBody eoperator = gen_eoperator ( project_dir "enums/EOperator.csv" );
CodeBody especifier = gen_especifier( project_dir "enums/ESpecifier.csv" );
CodeBody ast_inlines = gen_ast_inlines();
#if 0
header.print_fmt("#pragma region Types\n");
header.print( types );
header.print( fmt_newline );
header.print( dump_to_scratch_and_retireve( ecode ));
header.print( fmt_newline );
header.print( dump_to_scratch_and_retireve( eoperator ));
header.print( fmt_newline );
header.print( dump_to_scratch_and_retireve( especifier ));
header.print( fmt_newline );
header.print_fmt("#pragma endregion Types\n\n");
#endif
}
header.print( pop_ignores );
header.write();
// format_file( "gen/gen.h" );
gen::deinit();
return 0;
#undef project_dir
}

View File

@ -0,0 +1,295 @@
#pragma once
#include "../project/gen.hpp"
using namespace gen;
CodeBody gen_array_base()
{
CodeTypedef td_header = parse_typedef( code( typedef struct ArrayHeader ArrayHeader; ));
CodeStruct header = parse_struct( code(
struct ArrayHeader
{
AllocatorInfo Allocator;
usize Capacity;
usize Num;
};
));
// Code grow_formula = untyped_str( txt( "#define gen_array_grow_formula( value ) ( 2 * value + 8 )\n" ));
Code get_header = untyped_str( txt( "#define array_get_header( Type, self ) ( (ArrayHeader*)( self ) - 1)\n" ));
return def_global_body( args( fmt_newline, td_header, header, get_header, fmt_newline ) );
};
CodeBody gen_array( StrC type, StrC array_name )
{
String array_type = String::fmt_buf( GlobalAllocator, "%.*s", array_name.Len, array_name.Ptr );
String fn = String::fmt_buf( GlobalAllocator, "%.*s", array_name.Len, array_name.Ptr );
str_to_lower(fn.Data);
#pragma push_macro( "GEN_ASSERT" )
#undef GEN_ASSERT
CodeBody result = parse_global_body( token_fmt( "array_type", (StrC)array_type, "fn", (StrC)fn, "type", (StrC)type
, stringize(
typedef <type>* <array_type>;
<array_type> <fn>_init ( AllocatorInfo allocator );
<array_type> <fn>_init_reserve ( AllocatorInfo allocator, usize capacity );
bool <fn>_append ( <array_type>* self, <type> value );
bool <fn>_append_items ( <array_type>* self, <type>* items, usize item_num );
bool <fn>_append_at ( <array_type>* self, <type> item, usize idx );
bool <fn>_append_items_at( <array_type>* self, <type>* items, usize item_num, usize idx );
<type>* <fn>_back ( <array_type> self );
void <fn>_clear ( <array_type> self );
bool <fn>_fill ( <array_type> self, usize begin, usize end, <type> value );
void <fn>_free ( <array_type> self );
bool <fn>_grow ( <array_type>* self, usize min_capacity );
usize <fn>_num ( <array_type> self );
<type> <fn>_pop ( <array_type> self );
bool <fn>_reserve ( <array_type>* self, usize new_capacity );
bool <fn>_resize ( <array_type>* self, usize num );
bool <fn>_set_capacity ( <array_type>* self, usize new_capacity );
<array_type> <fn>_init( AllocatorInfo allocator )
{
return <fn>_init_reserve( allocator, array_grow_formula( 0 ) );
}
<array_type> <fn>_init_reserve( AllocatorInfo allocator, usize capacity )
{
ArrayHeader* header = cast(ArrayHeader*, alloc( allocator, sizeof(ArrayHeader) + sizeof(<type>) * capacity ) );
if ( header == NULL )
return NULL;
header->Allocator = allocator;
header->Capacity = capacity;
header->Num = 0;
return cast( <type>*, header + 1 );
}
bool <fn>_append( <array_type>* self, <type> value )
{
ArrayHeader* header = get_header( * self );
if ( header->Num == header->Capacity )
{
if ( ! <fn>_grow( self, header->Capacity))
return false;
header = get_header( * self );
}
(* self)[ header->Num ] = value;
header->Num++;
return true;
}
bool <fn>_append_items( <array_type>* self, <type>* items, usize item_num )
{
ArrayHeader* header = get_header( * self );
if ( header->Num + item_num > header->Capacity )
{
if ( ! <fn>_grow( self, header->Capacity + item_num ))
return false;
header = get_header( * self );
}
mem_copy( (* self) + header->Num, items, sizeof(<type>) * item_num );
header->Num += item_num;
return true;
}
bool <fn>_append_at( <array_type>* self, <type> item, usize idx )
{
ArrayHeader* header = get_header( * self );
if ( idx >= header->Num )
idx = header->Num - 1;
if ( idx < 0 )
idx = 0;
if ( header->Capacity < header->Num + 1 )
{
if ( ! <fn>_grow( self, header->Capacity + 1 ) )
return false;
header = get_header( * self );
}
<array_type> target = (* self) + idx;
mem_move( target + 1, target, (header->Num - idx) * sizeof(<type>) );
header->Num++;
return true;
}
bool <fn>_append_items_at( <array_type>* self, <type>* items, usize item_num, usize idx )
{
ArrayHeader* header = get_header( * self );
if ( idx >= header->Num )
{
return <fn>_append_items( self, items, item_num );
}
if ( item_num > header->Capacity )
{
if ( ! <fn>_grow( self, item_num + header->Capacity ) )
return false;
header = get_header( * self );
}
<type>* target = (* self) + idx + item_num;
<type>* src = (* self) + idx;
mem_move( target, src, (header->Num - idx) * sizeof(<type>) );
mem_copy( src, items, item_num * sizeof(<type>) );
header->Num += item_num;
return true;
}
<type>* <fn>_back( <array_type> self )
{
ArrayHeader* header = get_header( self );
if ( header->Num == 0 )
return NULL;
return self + header->Num - 1;
}
void <fn>_clear( <array_type> self )
{
ArrayHeader* header = get_header( self );
header->Num = 0;
}
bool <fn>_fill( <array_type> self, usize begin, usize end, <type> value )
{
ArrayHeader* header = get_header( self );
if ( begin < 0 || end >= header->Num )
return false;
for ( ssize idx = begin; idx < end; idx ++ )
self[ idx ] = value;
return true;
}
void <fn>_free( <array_type> self )
{
ArrayHeader* header = get_header( self );
free( header->Allocator, header );
self = NULL;
}
bool <fn>_grow( <array_type>* self, usize min_capacity )
{
ArrayHeader* header = get_header( *self );
usize new_capacity = array_grow_formula( header->Capacity );
if ( new_capacity < min_capacity )
new_capacity = min_capacity;
return <fn>_set_capacity( self, new_capacity );
}
usize <fn>_num( <array_type> self )
{
return get_header(self)->Num;
}
<type> <fn>_pop( <array_type> self )
{
ArrayHeader* header = get_header( self );
GEN_ASSERT( header->Num > 0 );
<type> result = self[ header->Num - 1 ];
header->Num--;
return result;
}
void <fn>_remove_at( <array_type> self, usize idx )
{
ArrayHeader* header = get_header( self );
GEN_ASSERT( idx < header->Num );
mem_move( self + idx, self + idx + 1, sizeof( <type> ) * ( header->Num - idx - 1 ) );
header->Num--;
}
bool <fn>_reserve( <array_type>* self, usize new_capacity )
{
ArrayHeader* header = get_header( * self );
if ( header->Capacity < new_capacity )
return <fn>_set_capacity( self, new_capacity );
return true;
}
bool <fn>_resize( <array_type>* self, usize num )
{
ArrayHeader* header = get_header( * self );
if ( header->Capacity < num )
{
if ( ! <fn>_grow( self, num ) )
return false;
header = get_header( * self );
}
header->Num = num;
return true;
}
bool <fn>_set_capacity( <array_type>* self, usize new_capacity )
{
ArrayHeader* header = get_header( * self );
if ( new_capacity == header->Capacity )
return true;
if ( new_capacity < header->Num )
header->Num = new_capacity;
usize size = sizeof( ArrayHeader ) + sizeof( <type> ) * new_capacity;
ArrayHeader* new_header = cast( ArrayHeader*, alloc( header->Allocator, size ));
if ( new_header == NULL )
return false;
mem_move( new_header, header, sizeof( ArrayHeader ) + sizeof( <type> ) * header->Num );
free( header->Allocator, & header );
new_header->Capacity = new_capacity;
* self = cast( <type>*, new_header + 1 );
return true;
}
)));
#pragma pop_macro( "GEN_ASSERT" )
return def_global_body( args(
def_pragma( to_str( str_fmt_buf( "region %S", array_type ))),
fmt_newline,
result,
fmt_newline,
def_pragma( to_str( str_fmt_buf( "endregion %S", array_type ))),
fmt_newline
));
};
// CodeBody gen_

View File

@ -0,0 +1,354 @@
#pragma once
#include "../project/gen.hpp"
#include "containers.array.hpp"
using namespace gen;
CodeBody gen_hashtable_base()
{
return parse_global_body( code(
typedef struct HT_FindResult HT_FindResult;
struct HT_FindResult
{
ssize HashIndex;
ssize PrevIndex;
ssize EntryIndex;
};
));
}
CodeBody gen_hashtable( StrC type, StrC hashtable_name )
{
String
fn = String::make_reserve( GlobalAllocator, hashtable_name.Len + sizeof("gen") );
fn.append_fmt( "%.*s", hashtable_name.Len, hashtable_name.Ptr );
str_to_lower(fn.Data);
String
tbl_type = String::make_reserve( GlobalAllocator, hashtable_name.Len + sizeof("gen") );
tbl_type.append_fmt( "%.*s", hashtable_name.Len, hashtable_name.Ptr );
String name_lower = String::make( GlobalAllocator, hashtable_name );
str_to_lower( name_lower.Data );
String hashtable_entry = String::fmt_buf( GlobalAllocator, "HTE_%.*s", hashtable_name.Len, hashtable_name.Ptr );
String entry_array_name = String::fmt_buf( GlobalAllocator, "Arr_HTE_%.*s", hashtable_name.Len, hashtable_name.Ptr );
String entry_array_fn_ns = String::fmt_buf( GlobalAllocator, "arr_hte_%.*s", name_lower.length(), name_lower.Data );
CodeBody hashtable_types = parse_global_body( token_fmt(
"type", (StrC) type,
"tbl_name", (StrC) hashtable_name,
"tbl_type", (StrC) tbl_type,
stringize(
typedef struct HTE_<tbl_name> HTE_<tbl_name>;
struct HTE_<tbl_name>
{
u64 Key;
ssize Next;
<type> Value;
};
typedef void (* <tbl_type>_MapProc) ( <tbl_type> self, u64 key, <type> value );
typedef void (* <tbl_type>_MapMutProc) ( <tbl_type> self, u64 key, <type>* value );
)));
CodeBody entry_array = gen_array( hashtable_entry, entry_array_name );
#pragma push_macro( "GEN_ASSERT" )
#pragma push_macro( "GEN_ASSERT_NOT_NULL" )
#undef GEN_ASSERT
#undef GEN_ASSERT_NOT_NULL
CodeBody hashtable_def = parse_global_body( token_fmt(
"type", (StrC) type,
"tbl_name", (StrC) hashtable_name,
"tbl_type", (StrC) tbl_type,
"fn", (StrC) fn,
"entry_type", (StrC) hashtable_entry,
"array_entry", (StrC) entry_array_name,
"fn_array", (StrC) entry_array_fn_ns,
stringize(
typedef struct <tbl_type> <tbl_type>;
struct <tbl_type>
{
Array_ssize Hashes;
<array_entry> Entries;
};
<tbl_type> <fn>_make ( AllocatorInfo allocator );
<tbl_type> <fn>_make_reserve( AllocatorInfo allocator, ssize num );
void <fn>_clear ( <tbl_type> self );
void <fn>_destroy ( <tbl_type> self );
<type>* <fn>_get ( <tbl_type> self, u64 key );
void <fn>_map ( <tbl_type> self, <tbl_type>_MapProc map_proc );
void <fn>_map_mut ( <tbl_type> self, <tbl_type>_MapMutProc map_proc );
void <fn>_grow ( <tbl_type>* self );
void <fn>_rehash ( <tbl_type>* self, ssize new_num );
void <fn>_rehash_fast ( <tbl_type> self );
void <fn>_remove ( <tbl_type> self, u64 key );
void <fn>_remove_entry( <tbl_type> self, ssize idx );
void <fn>_set ( <tbl_type>* self, u64 key, <type> value );
ssize <fn>_slot ( <tbl_type> self, u64 key );
ssize <fn>__add_entry( <tbl_type> self, u64 key );
HT_FindResult <fn>__find ( <tbl_type> self, u64 key );
b32 <fn>__full ( <tbl_type> self );
<tbl_type> <fn>_make( AllocatorInfo allocator )
{
<tbl_type>
result = { NULL, NULL };
result.Hashes = array_ssize_make( allocator );
result.Entries = <fn_array>_make( allocator );
return result;
}
<tbl_type> <fn>_make_reserve( AllocatorInfo allocator, ssize num )
{
<tbl_type>
result = { NULL, NULL };
result.Hashes = array_ssize_make_reserve( allocator, num );
result.Entries = <fn_array>_make_reserve( allocator, num );
return result;
}
void <fn>_clear( <tbl_type> self )
{
for ( ssize idx = 0; idx < array_header( self.Hashes )->Num; idx++ )
self.Hashes[idx] = -1;
array_ssize_clear( self.Hashes );
<fn_array>_clear( self.Entries );
}
void <fn>_destroy( <tbl_type> self )
{
if ( self.Hashes && self.Entries )
{
array_ssize_free( self.Hashes );
<fn_array>_free( self.Entries );
}
}
<type>* <fn>_get( <tbl_type> self, u64 key )
{
ssize idx = <fn>__find( self, key ).EntryIndex;
if ( idx > 0 )
return & self.Entries[idx].Value;
return NULL;
}
void <fn>_map( <tbl_type> self, <tbl_type>_MapProc map_proc )
{
GEN_ASSERT_NOT_NULL( map_proc );
for ( ssize idx = 0; idx < array_header( self.Entries )->Num; idx++ )
{
map_proc( self, self.Entries[idx].Key, self.Entries[idx].Value );
}
}
void <fn>_map_mut( <tbl_type> self, <tbl_type>_MapMutProc map_proc )
{
GEN_ASSERT_NOT_NULL( map_proc );
for ( ssize idx = 0; idx < array_header( self.Entries )->Num; idx++ )
{
map_proc( self, self.Entries[idx].Key, & self.Entries[idx].Value );
}
}
void <fn>_grow( <tbl_type>* self )
{
ssize new_num = array_grow_formula( array_header( self->Entries )->Num );
<fn>_rehash( self, new_num );
}
void <fn>_rehash( <tbl_type>* self, ssize new_num )
{
ssize idx;
ssize last_added_index;
ArrayHeader* old_hash_header = array_header( self->Hashes );
ArrayHeader* old_entries_header = array_header( self->Entries );
<tbl_type> new_tbl = <fn>_make_reserve( old_hash_header->Allocator, old_hash_header->Num );
ArrayHeader* new_hash_header = array_header( new_tbl.Hashes );
for ( idx = 0; idx < new_hash_header->Num; idx++ )
new_tbl.Hashes[idx] = -1;
for ( idx = 0; idx < old_entries_header->Num; idx++ )
{
<entry_type>* entry;
HT_FindResult find_result;
if ( new_hash_header->Num == 0 )
<fn>_grow( & new_tbl );
entry = & self->Entries[ idx ];
find_result = <fn>__find( new_tbl, entry->Key );
last_added_index = <fn>__add_entry( new_tbl, entry->Key );
if ( find_result.PrevIndex < 0 )
new_tbl.Hashes[ find_result.HashIndex ] = last_added_index;
else
new_tbl.Entries[ find_result.PrevIndex ].Next = last_added_index;
new_tbl.Entries[ last_added_index ].Next = find_result.EntryIndex;
new_tbl.Entries[ last_added_index ].Value = entry->Value;
}
<fn>_destroy( *self );
* self = new_tbl;
}
void <fn>_rehash_fast( <tbl_type> self )
{
ssize idx;
for ( idx = 0; idx < array_header( self.Entries )->Num; idx++ )
self.Entries[ idx ].Next = -1;
for ( idx = 0; idx < array_header( self.Hashes )->Num; idx++ )
self.Hashes[ idx ] = -1;
for ( idx = 0; idx < array_header( self.Entries )->Num; idx++ )
{
<entry_type>* entry;
HT_FindResult find_result;
entry = & self.Entries[ idx ];
find_result = <fn>__find( self, entry->Key );
if ( find_result.PrevIndex < 0 )
self.Hashes[ find_result.HashIndex ] = idx;
else
self.Entries[ find_result.PrevIndex ].Next = idx;
}
}
void <fn>_remove( <tbl_type> self, u64 key )
{
HT_FindResult find_result = <fn>__find( self, key );
if ( find_result.EntryIndex >= 0 )
{
<fn_array>_remove_at( self.Entries, find_result.EntryIndex );
<fn>_rehash_fast( self );
}
}
void <fn>_remove_entry( <tbl_type> self, ssize idx )
{
<fn_array>_remove_at( self.Entries, idx );
}
void <fn>_set( <tbl_type>* self, u64 key, <type> value )
{
ssize idx;
HT_FindResult find_result;
if ( array_header( self->Hashes )->Num == 0 )
<fn>_grow( self );
find_result = <fn>__find( * self, key );
if ( find_result.EntryIndex >= 0 )
{
idx = find_result.EntryIndex;
}
else
{
idx = <fn>__add_entry( * self, key );
if ( find_result.PrevIndex >= 0 )
{
self->Entries[ find_result.PrevIndex ].Next = idx;
}
else
{
self->Hashes[ find_result.HashIndex ] = idx;
}
}
self->Entries[ idx ].Value = value;
if ( <fn>__full( * self ) )
<fn>_grow( self );
}
ssize <fn>_slot( <tbl_type> self, u64 key )
{
for ( ssize idx = 0; idx < array_header( self.Hashes )->Num; ++idx )
if ( self.Hashes[ idx ] == key )
return idx;
return -1;
}
ssize <fn>__add_entry( <tbl_type> self, u64 key )
{
ssize idx;
<entry_type> entry = { key, -1 };
idx = array_header( self.Entries )->Num;
<fn_array>_append( & self.Entries, entry );
return idx;
}
HT_FindResult <fn>__find( <tbl_type> self, u64 key )
{
HT_FindResult result = { -1, -1, -1 };
ArrayHeader* hash_header = array_header( self.Hashes );
if ( hash_header->Num > 0 )
{
result.HashIndex = key % hash_header->Num;
result.EntryIndex = self.Hashes[ result.HashIndex ];
while ( result.EntryIndex >= 0 )
{
if ( self.Entries[ result.EntryIndex ].Key == key )
break;
result.PrevIndex = result.EntryIndex;
result.EntryIndex = self.Entries[ result.EntryIndex ].Next;
}
}
return result;
}
b32 <fn>__full( <tbl_type> self )
{
ArrayHeader* hash_header = array_header( self.Hashes );
ArrayHeader* entries_header = array_header( self.Entries );
return 0.75f * hash_header->Num < entries_header->Num;
}
)));
#pragma pop_macro( "GEN_ASSERT" )
#pragma pop_macro( "GEN_ASSERT_NOT_NULL" )
char const* cmt_str = str_fmt_buf( "Name: %.*s Type: %.*s"
, tbl_type.length(), tbl_type.Data
, type.Len, type.Ptr );
return def_global_body(args(
def_pragma( to_str( str_fmt_buf( "region %S", tbl_type ))),
fmt_newline,
hashtable_types,
fmt_newline,
entry_array,
hashtable_def,
fmt_newline,
def_pragma( to_str( str_fmt_buf( "endregion %S", tbl_type ))),
fmt_newline
));
}

View File

@ -0,0 +1,14 @@
/*
gencpp: An attempt at "simple" staged metaprogramming for c/c++.
See Readme.md for more information from the project repository.
Public Address:
https://github.com/Ed94/gencpp
This is a single header C-Library variant.
Define GEN_IMPLEMENTATION before including this file in a single compilation unit.
*/
#if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME)
# error Gen.hpp : GEN_TIME not defined
#endif

View File

@ -0,0 +1,122 @@
#pragma once
#include "../project/gen.hpp"
using namespace gen;
CodeBody gen_fixed_arenas()
{
CodeBody result = def_body(ECode::Global_Body);
result.append(def_pragma(txt("region FixedArena")));
char const* template_struct = stringize(
struct FixedArena_<Name>
{
char memory[<Size>];
Arena arena;
};
);
char const* template_interface = stringize(
inline
void fixed_arena_init_<Name>(FixedArena_<Name>* result) {
zero_size(& result->memory[0], <Size>);
result->arena = arena_init_from_memory(& result->memory[0], <Size>);
}
inline
ssize fixed_arena_size_remaining_<Name>(FixedArena_<Name>* fixed_arena, ssize alignment) {
return size_remaining(fixed_arena->arena, alignment);
}
);
CodeStruct arena_struct_1kb = parse_struct( token_fmt_impl( 3, "Name", txt("1KB"), "Size", txt("kilobytes(1)"), template_struct ));
CodeStruct arena_struct_4kb = parse_struct( token_fmt_impl( 3, "Name", txt("4KB"), "Size", txt("kilobytes(4)"), template_struct ));
CodeStruct arena_struct_8kb = parse_struct( token_fmt_impl( 3, "Name", txt("8KB"), "Size", txt("kilobytes(8)"), template_struct ));
CodeStruct arena_struct_16kb = parse_struct( token_fmt_impl( 3, "Name", txt("16KB"), "Size", txt("kilobytes(16)"), template_struct ));
CodeStruct arena_struct_32kb = parse_struct( token_fmt_impl( 3, "Name", txt("32KB"), "Size", txt("kilobytes(32)"), template_struct ));
CodeStruct arena_struct_64kb = parse_struct( token_fmt_impl( 3, "Name", txt("64KB"), "Size", txt("kilobytes(64)"), template_struct ));
CodeStruct arena_struct_128kb = parse_struct( token_fmt_impl( 3, "Name", txt("128KB"), "Size", txt("kilobytes(128)"), template_struct ));
CodeStruct arena_struct_256kb = parse_struct( token_fmt_impl( 3, "Name", txt("256KB"), "Size", txt("kilobytes(256)"), template_struct ));
CodeStruct arena_struct_512kb = parse_struct( token_fmt_impl( 3, "Name", txt("512KB"), "Size", txt("kilobytes(512)"), template_struct ));
CodeStruct arena_struct_1mb = parse_struct( token_fmt_impl( 3, "Name", txt("1MB"), "Size", txt("megabytes(1)"), template_struct ));
CodeStruct arena_struct_2mb = parse_struct( token_fmt_impl( 3, "Name", txt("2MB"), "Size", txt("megabytes(2)"), template_struct ));
CodeStruct arena_struct_4mb = parse_struct( token_fmt_impl( 3, "Name", txt("4MB"), "Size", txt("megabytes(4)"), template_struct ));
CodeBody arena_interface_1kb = parse_global_body( token_fmt_impl( 3, "Name", txt("1KB"), "Size", txt("kilobytes(1)"), template_interface ));
CodeBody arena_interface_4kb = parse_global_body( token_fmt_impl( 3, "Name", txt("4KB"), "Size", txt("kilobytes(4)"), template_interface ));
CodeBody arena_interface_8kb = parse_global_body( token_fmt_impl( 3, "Name", txt("8KB"), "Size", txt("kilobytes(8)"), template_interface ));
CodeBody arena_interface_16kb = parse_global_body( token_fmt_impl( 3, "Name", txt("16KB"), "Size", txt("kilobytes(16)"), template_interface ));
CodeBody arena_interface_32kb = parse_global_body( token_fmt_impl( 3, "Name", txt("32KB"), "Size", txt("kilobytes(32)"), template_interface ));
CodeBody arena_interface_64kb = parse_global_body( token_fmt_impl( 3, "Name", txt("64KB"), "Size", txt("kilobytes(64)"), template_interface ));
CodeBody arena_interface_128kb = parse_global_body( token_fmt_impl( 3, "Name", txt("128KB"), "Size", txt("kilobytes(128)"), template_interface ));
CodeBody arena_interface_256kb = parse_global_body( token_fmt_impl( 3, "Name", txt("256KB"), "Size", txt("kilobytes(256)"), template_interface ));
CodeBody arena_interface_512kb = parse_global_body( token_fmt_impl( 3, "Name", txt("512KB"), "Size", txt("kilobytes(512)"), template_interface ));
CodeBody arena_interface_1mb = parse_global_body( token_fmt_impl( 3, "Name", txt("1MB"), "Size", txt("megabytes(1)"), template_interface ));
CodeBody arena_interface_2mb = parse_global_body( token_fmt_impl( 3, "Name", txt("2MB"), "Size", txt("megabytes(2)"), template_interface ));
CodeBody arena_interface_4mb = parse_global_body( token_fmt_impl( 3, "Name", txt("4MB"), "Size", txt("megabytes(4)"), template_interface ));
result.append(arena_struct_1kb);
result.append(arena_struct_4kb);
result.append(arena_struct_8kb);
result.append(arena_struct_16kb);
result.append(arena_struct_32kb);
result.append(arena_struct_128kb);
result.append(arena_struct_256kb);
result.append(arena_struct_512kb);
result.append(arena_struct_1mb);
result.append(arena_struct_2mb);
result.append(arena_struct_4mb);
result.append(arena_interface_1kb);
result.append(arena_interface_4kb);
result.append(arena_interface_8kb);
result.append(arena_interface_16kb);
result.append(arena_interface_32kb);
result.append(arena_interface_128kb);
result.append(arena_interface_256kb);
result.append(arena_interface_512kb);
result.append(arena_interface_1mb);
result.append(arena_interface_2mb);
result.append(arena_interface_4mb);
CodeDefine def = def_define(txt("fixed_arena_allocator_info(fixed_arena)"), code({ arena_allocator_proc, & fixed_arena.arena }) );
result.append(def);
result.append(parse_global_body(txt(R"(
#define fixed_arena_init(expr) _Generic((expr), \
FixedArena_1KB* : fixed_arena_init_1KB, \
FixedArena_4KB* : fixed_arena_init_4KB, \
FixedArena_8KB* : fixed_arena_init_8KB, \
FixedArena_16KB* : fixed_arena_init_16KB, \
FixedArena_32KB* : fixed_arena_init_32KB, \
FixedArena_64KB* : fixed_arena_init_64KB, \
FixedArena_128KB* : fixed_arena_init_128KB, \
FixedArena_256KB* : fixed_arena_init_256KB, \
FixedArena_512KB* : fixed_arena_init_512KB, \
FixedArena_1MB* : fixed_arena_init_1MB, \
FixedArena_2MB* : fixed_arena_init_2MB, \
FixedArena_4MB* : fixed_arena_init_4MB \
)(expr)
#define fixed_arena_size_remaining(expr, alignment) _Generic((expr), \
FixedArena_1KB* : fixed_arena_size_remaining_1KB, \
FixedArena_4KB* : fixed_arena_size_remaining_4KB, \
FixedArena_8KB* : fixed_arena_size_remaining_8KB, \
FixedArena_16KB* : fixed_arena_size_remaining_16KB, \
FixedArena_32KB* : fixed_arena_size_remaining_32KB, \
FixedArena_64KB* : fixed_arena_size_remaining_64KB, \
FixedArena_128KB* : fixed_arena_size_remaining_128KB, \
FixedArena_256KB* : fixed_arena_size_remaining_256KB, \
FixedArena_512KB* : fixed_arena_size_remaining_512KB, \
FixedArena_1MB* : fixed_arena_size_remaining_1MB, \
FixedArena_2MB* : fixed_arena_size_remaining_2MB, \
FixedArena_4MB* : fixed_arena_size_remaining_4MB \
)(expr, alignment)
)"
)));
result.append(def_pragma(txt("endregion FixedArena")));
return result;
}

View File

@ -0,0 +1,72 @@
// #pragma once
// #include "../project/gen.hpp"
// using namespace gen;
using SwapContentProc = CodeBody(void);
b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& body )
{
b32 found = false;
CodePreprocessCond cond = cast(CodePreprocessCond, entry_iter);
if ( cond->Content.contains(cond_sig) )
{
log_fmt("Preprocess cond found: %S\n", cond->Content);
found = true;
s32 depth = 1;
++ entry_iter; for(b32 continue_for = true; continue_for && entry_iter != body.end(); ) switch
(entry_iter->Type) {
case ECode::Preprocess_If:
case ECode::Preprocess_IfDef:
case ECode::Preprocess_IfNotDef:
depth ++;
break;
case ECode::Preprocess_EndIf:
{
depth --;
if (depth == 0) {
continue_for = false;
break;
}
}
break;
default:
++ entry_iter;
break;
}
}
return found;
}
bool swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_content, Code& entry_iter, CodeBody& body )
{
bool found = false;
CodePragma possible_region = cast(CodePragma, entry_iter);
String region_sig = string_fmt_buf(GlobalAllocator, "region %s", region_name.Ptr);
String endregion_sig = string_fmt_buf(GlobalAllocator, "endregion %s", region_name.Ptr);
if ( possible_region->Content.contains(region_sig))
{
found = true;
// body.append(possible_region);
body.append(swap_content());
++ entry_iter; for(b32 continue_for = true; continue_for; ++entry_iter) switch
(entry_iter->Type) {
case ECode::Preprocess_Pragma:
{
CodePragma possible_end_region = cast(CodePragma, entry_iter);
if ( possible_end_region->Content.contains(endregion_sig) ) {
// body.append(possible_end_region);
continue_for = false;
}
}
break;
}
body.append(entry_iter);
}
return found;
}

7
gen_c_library/gen.c Normal file
View File

@ -0,0 +1,7 @@
#define GEN_IMPLEMENTATION
#include "gen/gen.h"
int main()
{
// init();
}

View File

@ -1,4 +1,4 @@
# Singleheader # Singleheader
Creates a single header file version of the library using `gen.singleheader.cpp`. Creates a single header file version of the library using `singleheader.cpp`.
Follows the same convention seen in the gb, stb, and zpl libraries. Follows the same convention seen in the gb, stb, and zpl libraries.

View File

@ -12,12 +12,3 @@
#if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME)
# error Gen.hpp : GEN_TIME not defined # error Gen.hpp : GEN_TIME not defined
#endif #endif
#ifdef GEN_DONT_USE_NAMESPACE
# define GEN_NS_BEGIN
# define GEN_NS_END
#else
# define GEN_NS_BEGIN namespace gen {
# define GEN_NS_END }
#endif

View File

@ -1,6 +1,8 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES #define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND #define GEN_EXPOSE_BACKEND
#define GEN_SUPPORT_CPP_MEMBER_FEATURES 1
#define GEN_SUPPORT_CPP_REFERENCES 0
#include "gen.cpp" #include "gen.cpp"
#include "helpers/push_ignores.inline.hpp" #include "helpers/push_ignores.inline.hpp"

View File

@ -30,6 +30,13 @@ Feature Macros:
* `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves. * `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves.
* `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized. * `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized.
By default the base library implementation strictly uses a C-like interface. This is to allow for the generation of a C-variant of the library using [gen_c_library](../gen_c_library/). However, the library was written in C++ and supports some of its features:
* `GEN_SUPPORT_CPP_REFERENCES` : Will enable support for reference interface on some definitions
* `GEN_SUPPORT_CPP_MEMBER_FEATURES` : Will enable support for definitions to have their interface as members.
*Note: A variant of the C++ library could be generated where those additonal support features are removed (see gen_c_library implementation for an idea of how)*
## On multi-threading ## On multi-threading
Currently unsupported. I want the library to be *stable* and *correct*, with the addition of exhausting all basic single-threaded optimizations before I consider multi-threading. Currently unsupported. I want the library to be *stable* and *correct*, with the addition of exhausting all basic single-threaded optimizations before I consider multi-threading.

View File

@ -13,7 +13,7 @@ Builder Builder::open( char const* path )
return result; return result;
} }
result.Buffer = String::make_reserve( GlobalAllocator, Builder_StrBufferReserve ); result.Buffer = string_make_reserve( GlobalAllocator, Builder_StrBufferReserve );
// log_fmt("$Builder - Opened file: %s\n", result.File.filename ); // log_fmt("$Builder - Opened file: %s\n", result.File.filename );
return result; return result;
@ -21,15 +21,15 @@ Builder Builder::open( char const* path )
void Builder::pad_lines( s32 num ) void Builder::pad_lines( s32 num )
{ {
Buffer.append( "\n" ); append( & Buffer, "\n" );
} }
void Builder::print( Code code ) void Builder::print( Code code )
{ {
String str = code->to_string(); String str = to_string(code);
// const ssize len = str.length(); // const ssize len = str.length();
// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data ); // log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data );
Buffer.append( str ); append( & Buffer, str );
} }
void Builder::print_fmt( char const* fmt, ... ) void Builder::print_fmt( char const* fmt, ... )
@ -43,17 +43,17 @@ void Builder::print_fmt( char const* fmt, ... )
va_end( va ); va_end( va );
// log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf ); // log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf );
Buffer.append( buf, res ); append( & Buffer, buf, res );
} }
void Builder::write() void Builder::write()
{ {
b32 result = file_write( & File, Buffer, Buffer.length() ); b32 result = file_write( & File, Buffer, length(Buffer) );
if ( result == false ) if ( result == false )
log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) );
log_fmt( "Generated: %s\n", File.filename ); log_fmt( "Generated: %s\n", File.filename );
file_close( & File ); file_close( & File );
Buffer.free(); free(& Buffer);
} }

View File

@ -0,0 +1,23 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "../gen.hpp"
#endif
/*
Explicitly generates a resolved definition of a cpp template definition.
TODO(Ed): Needs implementing for the C-library variant.
TODO(Ed): We need a non <token> syntax subst implemtnation for Strings for this to work. It must subst keywords directly based on template parameter names.
This is only meant to be used on relatively trivial templates, where the type or numeric is mostly a 'duck' type.
It cannot parse complex template parameters.
The varadic args should correspond 1:1 with the type of objects the generator expects from the template's parameters.alignas.
*/
CodeOperator gen_operator_template( CodeTemplate template, ... );
CodeFn gen_func_template( CodeTemplate template, ... );
Code gen_class_struct_template( CodeTemplate template, ... );
Code gen_template( CodeTemplate template, ... );
Code gen_template( StrC template, StrC instantiation );

View File

@ -23,9 +23,9 @@ Code scan_file( char const* path )
GEN_FATAL("scan_file: %s is empty", path ); GEN_FATAL("scan_file: %s is empty", path );
} }
String str = String::make_reserve( GlobalAllocator, fsize ); String str = string_make_reserve( GlobalAllocator, fsize );
file_read( & file, str, fsize ); file_read( & file, str, fsize );
str.get_header().Length = fsize; get_header(str)->Length = fsize;
// Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks // Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks
// Its designed so that the directive should be the first thing in the file. // Its designed so that the directive should be the first thing in the file.
@ -97,12 +97,12 @@ Code scan_file( char const* path )
if ( (scanner + 2) >= ( str.Data + fsize ) ) if ( (scanner + 2) >= ( str.Data + fsize ) )
{ {
mem_move( str, scanner, left ); mem_move( str, scanner, left );
str.get_header().Length = left; get_header(str)->Length = left;
break; break;
} }
mem_move( str, scanner, left ); mem_move( str, scanner, left );
str.get_header().Length = left; get_header(str)->Length = left;
break; break;
} }

View File

@ -1,6 +1,8 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES #define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND #define GEN_EXPOSE_BACKEND
#define GEN_SUPPORT_CPP_MEMBER_FEATURES 0
#define GEN_SUPPORT_CPP_REFERENCES 0
#include "gen.cpp" #include "gen.cpp"
#include "helpers/push_ignores.inline.hpp" #include "helpers/push_ignores.inline.hpp"
@ -24,20 +26,20 @@ constexpr char const* generation_notice =
void format_file( char const* path ) void format_file( char const* path )
{ {
String resolved_path = String::make(GlobalAllocator, to_str(path)); String resolved_path = string_make(GlobalAllocator, to_str(path));
String style_arg = String::make(GlobalAllocator, txt("-style=file:")); String style_arg = string_make(GlobalAllocator, txt("-style=file:"));
style_arg.append("../scripts/.clang-format "); append( & style_arg, "../scripts/.clang-format ");
// Need to execute clang format on the generated file to get it to match the original. // Need to execute clang format on the generated file to get it to match the original.
#define clang_format "clang-format " #define clang_format "clang-format "
#define cf_format_inplace "-i " #define cf_format_inplace "-i "
#define cf_verbose "-verbose " #define cf_verbose "-verbose "
String command = String::make( GlobalAllocator, clang_format ); String command = string_make( GlobalAllocator, clang_format );
command.append( cf_format_inplace ); append( & command, cf_format_inplace );
command.append( cf_verbose ); append( & command, cf_verbose );
command.append( style_arg ); append( & command, style_arg );
command.append( resolved_path ); append( & command, resolved_path );
log_fmt("\tRunning clang-format on file:\n"); log_fmt("\tRunning clang-format on file:\n");
system( command ); system( command );
log_fmt("\tclang-format finished reformatting.\n"); log_fmt("\tclang-format finished reformatting.\n");
@ -62,6 +64,8 @@ int gen_main()
{ {
gen::init(); gen::init();
// PreprocessorDefines.append("GEN_NS");
Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp" ); Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( "helpers/pop_ignores.inline.hpp" ); Code pop_ignores = scan_file( "helpers/pop_ignores.inline.hpp" );

File diff suppressed because it is too large Load Diff

View File

@ -73,79 +73,103 @@ struct AST_Union;
struct AST_Using; struct AST_Using;
struct AST_Var; struct AST_Var;
struct Code; #if GEN_COMPILER_C
struct CodeBody; #define Define_Code(Type) typedef AST_##Type* Code##Type
// These are to offer ease of use and optionally strong type safety for the AST. #else
struct CodeAttributes; #define Define_Code(Type) struct Code##Type
// struct CodeBaseClass;
struct CodeComment;
struct CodeClass;
struct CodeConstructor;
struct CodeDefine;
struct CodeDestructor;
struct CodeEnum;
struct CodeExec;
struct CodeExtern;
struct CodeInclude;
struct CodeFriend;
struct CodeFn;
struct CodeModule;
struct CodeNS;
struct CodeOperator;
struct CodeOpCast;
struct CodeParam;
struct CodePreprocessCond;
struct CodePragma;
struct CodeSpecifiers;
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct CodeExpr;
struct CodeExpr_Assign;
struct CodeExpr_Alignof;
struct CodeExpr_Binary;
struct CodeExpr_CStyleCast;
struct CodeExpr_FunctionalCast;
struct CodeExpr_CppCast;
struct CodeExpr_Element;
struct CodeExpr_ProcCall;
struct CodeExpr_Decltype;
struct CodeExpr_Comma;
struct CodeExpr_AMS; // Access Member Symbol
struct CodeExpr_Sizeof;
struct CodeExpr_Subscript;
struct CodeExpr_Ternary;
struct CodeExpr_UnaryPrefix;
struct CodeExpr_UnaryPostfix;
struct CodeStmt;
struct CodeStmt_Break;
struct CodeStmt_Case;
struct CodeStmt_Continue;
struct CodeStmt_Decl;
struct CodeStmt_Do;
struct CodeStmt_Expr;
struct CodeStmt_Else;
struct CodeStmt_If;
struct CodeStmt_For;
struct CodeStmt_Goto;
struct CodeStmt_Label;
struct CodeStmt_Switch;
struct CodeStmt_While;
#endif #endif
struct CodeStruct; #if GEN_COMPILER_C
struct CodeTemplate; typedef AST* code;
struct CodeType; #else
struct CodeTypedef; struct Code;
struct CodeUnion; #endif
struct CodeUsing; Define_Code(Body);
struct CodeVar; // These are to offer ease of use and optionally strong type safety for the AST.
Define_Code(Attributes);
// struct CodeBaseClass;
Define_Code(Comment);
Define_Code(Class);
Define_Code(Constructor);
Define_Code(Define);
Define_Code(Destructor);
Define_Code(Enum);
Define_Code(Exec);
Define_Code(Extern);
Define_Code(Include);
Define_Code(Friend);
Define_Code(Fn);
Define_Code(Module);
Define_Code(NS);
Define_Code(Operator);
Define_Code(OpCast);
Define_Code(Param);
Define_Code(PreprocessCond);
Define_Code(Pragma);
Define_Code(Specifiers);
#if GEN_EXECUTION_EXPRESSION_SUPPORT
Define_Code(Expr);
Define_Code(Expr_Assign);
Define_Code(Expr_Alignof);
Define_Code(Expr_Binary);
Define_Code(Expr_CStyleCast);
Define_Code(Expr_FunctionalCast);
Define_Code(Expr_CppCast);
Define_Code(Expr_Element);
Define_Code(Expr_ProcCall);
Define_Code(Expr_Decltype);
Define_Code(Expr_Comma);
Define_Code(Expr_AMS); // Access Member Symbol
Define_Code(Expr_Sizeof);
Define_Code(Expr_Subscript);
Define_Code(Expr_Ternary);
Define_Code(Expr_UnaryPrefix);
Define_Code(Expr_UnaryPostfix);
Define_Code(Stmt);
Define_Code(Stmt_Break);
Define_Code(Stmt_Case);
Define_Code(Stmt_Continue);
Define_Code(Stmt_Decl);
Define_Code(Stmt_Do);
Define_Code(Stmt_Expr);
Define_Code(Stmt_Else);
Define_Code(Stmt_If);
Define_Code(Stmt_For);
Define_Code(Stmt_Goto);
Define_Code(Stmt_Label);
Define_Code(Stmt_Switch);
Define_Code(Stmt_While);
#endif
Define_Code(Struct);
Define_Code(Template);
Define_Code(Type);
Define_Code(Typedef);
Define_Code(Union);
Define_Code(Using);
Define_Code(Var);
#undef Define_Code
namespace parser namespace parser
{ {
struct Token; struct Token;
} }
#if ! GEN_COMPILER_C
template< class Type> forceinline Type tmpl_cast( Code self ) { return * rcast( Type*, & self ); }
#endif
char const* debug_str (Code code);
Code duplicate (Code code);
bool is_equal (Code code, Code other);
bool is_body (Code code);
bool is_valid (Code code);
void set_global(Code code);
String to_string (Code code);
#if ! GEN_COMPILER_C
/* /*
AST* wrapper AST* wrapper
- Not constantly have to append the '*' as this is written often.. - Not constantly have to append the '*' as this is written often..
@ -153,39 +177,31 @@ namespace parser
*/ */
struct Code struct Code
{ {
# pragma region Statics AST* ast;
// Used to identify ASTs that should always be duplicated. (Global constant ASTs)
static Code Global;
// Used to identify invalid generated code. # define Using_Code( Typename ) \
static Code Invalid; char const* debug_str() { return GEN_NS debug_str(* this); } \
# pragma endregion Statics Code duplicate() { return GEN_NS duplicate(* this); } \
bool is_equal( Code other ) { return GEN_NS is_equal(* this, other); } \
bool is_body() { return GEN_NS is_body(* this); } \
bool is_valid() { return GEN_NS is_valid(* this); } \
void set_global() { return GEN_NS set_global(* this); }
# define Using_Code( Typename ) \ # define Using_CodeOps( Typename ) \
char const* debug_str(); \ Typename& operator = ( AST* other ); \
Code duplicate(); \ Typename& operator = ( Code other ); \
bool is_equal( Code other ); \ bool operator ==( Code other ) { return (AST*)ast == other.ast; } \
bool is_valid(); \ bool operator !=( Code other ) { return (AST*)ast != other.ast; } \
void set_global(); \
String to_string(); \
Typename& operator = ( AST* other ); \
Typename& operator = ( Code other ); \
bool operator ==( Code other ); \
bool operator !=( Code other ); \
operator bool(); operator bool();
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
Using_Code( Code ); Using_Code( Code );
String to_string() { return GEN_NS to_string(* this); }
#endif
template< class Type > Using_CodeOps( Code );
forceinline Type cast()
{
return * rcast( Type*, this );
}
AST* operator ->() AST* operator ->() { return ast; }
{
return ast;
}
Code& operator ++(); Code& operator ++();
// TODO(Ed) : Remove this overload. // TODO(Ed) : Remove this overload.
@ -200,8 +216,6 @@ struct Code
return *this; return *this;
} }
AST* ast;
#ifdef GEN_ENFORCE_STRONG_CODE_TYPES #ifdef GEN_ENFORCE_STRONG_CODE_TYPES
# define operator explicit operator # define operator explicit operator
#endif #endif
@ -236,6 +250,15 @@ struct Code
operator CodeVar() const; operator CodeVar() const;
#undef operator #undef operator
}; };
#endif
#pragma region Statics
// Used to identify ASTs that should always be duplicated. (Global constant ASTs)
extern Code Code_Global;
// Used to identify invalid generated code.
extern Code Code_Invalid;
#pragma endregion Statics
struct Code_POD struct Code_POD
{ {
@ -247,31 +270,63 @@ static_assert( sizeof(Code) == sizeof(Code_POD), "ERROR: Code is not POD" );
// Desired width of the AST data structure. // Desired width of the AST data structure.
constexpr int const AST_POD_Size = 128; constexpr int const AST_POD_Size = 128;
void append ( AST* self, AST* other );
char const* debug_str ( AST* self );
AST* duplicate ( AST* self );
Code* entry ( AST* self, u32 idx );
bool has_entries ( AST* self );
bool is_body ( AST* self );
bool is_equal ( AST* self, AST* other );
String to_string ( AST* self );
void to_string ( AST* self, String* result );
char const* type_str ( AST* self );
bool validate_body( AST* self );
#if GEN_CPP_SUPPORT_REFERENCES
void append ( AST& self, AST& other ) { return append(& self, & other); }
bool is_body ( AST& self ) { return is_body(& self); }
bool is_equal ( AST& self, AST& other ) { return is_equal(& self, & other); }
char const* debug_str( AST& self ) { return debug_str( & self ); }
String to_string( AST& self ) { return to_string( & self ); }
char const* type_str ( AST& self ) { return type_str( & self ); }
#endif
constexpr static
int AST_ArrSpecs_Cap =
(
AST_POD_Size
- sizeof(AST*) * 3
- sizeof(parser::Token*)
- sizeof(AST*)
- sizeof(StringCached)
- sizeof(CodeT)
- sizeof(ModuleFlag)
- sizeof(int)
)
/ sizeof(int) - 1; // -1 for 4 extra bytes
/* /*
Simple AST POD with functionality to seralize into C++ syntax. Simple AST POD with functionality to seralize into C++ syntax.
*/ */
struct AST struct AST
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
# pragma region Member Functions # pragma region Member Functions
void append ( AST* other ); void append ( AST* other ) { GEN_NS append(this, other); }
char const* debug_str (); char const* debug_str () { return GEN_NS debug_str(this); }
AST* duplicate (); AST* duplicate () { return GEN_NS duplicate(this); }
Code& entry ( u32 idx ); Code* entry ( u32 idx ) { return GEN_NS entry(this, idx); }
bool has_entries(); bool has_entries() { return GEN_NS has_entries(this); }
bool is_equal ( AST* other ); bool is_equal ( AST* other ) { return GEN_NS is_equal(this, other); }
char const* type_str(); bool is_body() { return GEN_NS is_body(this); }
bool validate_body(); char const* type_str() { return GEN_NS type_str(this); }
bool validate_body() { return GEN_NS validate_body(this); }
String to_string(); String to_string() { return GEN_NS to_string(this); }
void to_string( String& result ) { return GEN_NS to_string(this, & result); }
neverinline # pragma endregion Member Functions
void to_string( String& result ); #endif
template< class Type >
forceinline Type cast()
{
return * this;
}
operator Code(); operator Code();
operator CodeBody(); operator CodeBody();
@ -303,21 +358,6 @@ struct AST
operator CodeUnion(); operator CodeUnion();
operator CodeUsing(); operator CodeUsing();
operator CodeVar(); operator CodeVar();
# pragma endregion Member Functions
constexpr static
int ArrSpecs_Cap =
(
AST_POD_Size
- sizeof(AST*) * 3
- sizeof(parser::Token*)
- sizeof(AST*)
- sizeof(StringCached)
- sizeof(CodeT)
- sizeof(ModuleFlag)
- sizeof(int)
)
/ sizeof(int) - 1; // -1 for 4 extra bytes
union { union {
struct struct
@ -351,7 +391,7 @@ struct AST
}; };
StringCached Content; // Attributes, Comment, Execution, Include StringCached Content; // Attributes, Comment, Execution, Include
struct { struct {
SpecifierT ArrSpecs[ArrSpecs_Cap]; // Specifiers SpecifierT ArrSpecs[AST_ArrSpecs_Cap]; // Specifiers
AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used. AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used.
}; };
}; };
@ -376,7 +416,8 @@ struct AST
OperatorT Op; OperatorT Op;
AccessSpec ParentAccess; AccessSpec ParentAccess;
s32 NumEntries; s32 NumEntries;
s32 VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression. s32 VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression.
b32 EnumUnderlyingMacro; // Used by enums incase the user wants to wrap underlying type specification in a macro
}; };
}; };
@ -414,7 +455,7 @@ struct AST_POD
}; };
StringCached Content; // Attributes, Comment, Execution, Include StringCached Content; // Attributes, Comment, Execution, Include
struct { struct {
SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers SpecifierT ArrSpecs[AST_ArrSpecs_Cap]; // Specifiers
AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used. AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used.
}; };
}; };
@ -443,13 +484,6 @@ struct AST_POD
}; };
}; };
struct test {
SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers
AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used.
};
constexpr int pls = sizeof(test);
// Its intended for the AST to have equivalent size to its POD. // Its intended for the AST to have equivalent size to its POD.
// All extra functionality within the AST namespace should just be syntatic sugar. // All extra functionality within the AST namespace should just be syntatic sugar.
static_assert( sizeof(AST) == sizeof(AST_POD), "ERROR: AST IS NOT POD" ); static_assert( sizeof(AST) == sizeof(AST_POD), "ERROR: AST IS NOT POD" );
@ -457,4 +491,4 @@ static_assert( sizeof(AST_POD) == AST_POD_Size, "ERROR: AST POD is not size o
// Used when the its desired when omission is allowed in a definition. // Used when the its desired when omission is allowed in a definition.
#define NoCode { nullptr } #define NoCode { nullptr }
#define CodeInvalid (* Code::Invalid.ast) // Uses an implicitly overloaded cast from the AST to the desired code type. #define InvalidCode (* Code_Invalid.ast) // Uses an implicitly overloaded cast from the AST to the desired code type.

View File

@ -12,7 +12,7 @@
struct AST_Body struct AST_Body
{ {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
Code Front; Code Front;
Code Back; Code Back;
parser::Token* Tok; parser::Token* Tok;
@ -27,7 +27,7 @@ static_assert( sizeof(AST_Body) == sizeof(AST), "ERROR: AST_Body is not the same
struct AST_Attributes struct AST_Attributes
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -44,7 +44,7 @@ static_assert( sizeof(AST_Attributes) == sizeof(AST), "ERROR: AST_Attributes is
struct AST_BaseClass struct AST_BaseClass
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
Code Prev; Code Prev;
Code Next; Code Next;
@ -60,7 +60,7 @@ static_assert( sizeof(AST_BaseClass) == sizeof(AST), "ERROR: AST_BaseClass is no
struct AST_Comment struct AST_Comment
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -76,7 +76,7 @@ static_assert( sizeof(AST_Comment) == sizeof(AST), "ERROR: AST_Comment is not th
struct AST_Class struct AST_Class
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; // Only supported by forward declarations CodeComment InlineCmt; // Only supported by forward declarations
@ -102,7 +102,7 @@ static_assert( sizeof(AST_Class) == sizeof(AST), "ERROR: AST_Class is not the sa
struct AST_Constructor struct AST_Constructor
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; // Only supported by forward declarations CodeComment InlineCmt; // Only supported by forward declarations
@ -127,7 +127,7 @@ static_assert( sizeof(AST_Constructor) == sizeof(AST), "ERROR: AST_Constructor i
struct AST_Define struct AST_Define
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -143,7 +143,7 @@ static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the
struct AST_Destructor struct AST_Destructor
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -167,14 +167,14 @@ static_assert( sizeof(AST_Destructor) == sizeof(AST), "ERROR: AST_Destructor is
struct AST_Enum struct AST_Enum
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
CodeAttributes Attributes; CodeAttributes Attributes;
char _PAD_SPEC_ [ sizeof(AST*) ]; char _PAD_SPEC_ [ sizeof(AST*) ];
CodeType UnderlyingType; CodeType UnderlyingType;
char _PAD_PARAMS_[ sizeof(AST*) ]; Code UnderlyingTypeMacro;
CodeBody Body; CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ]; char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
}; };
@ -186,14 +186,14 @@ struct AST_Enum
StringCached Name; StringCached Name;
CodeT Type; CodeT Type;
ModuleFlag ModuleFlags; ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ]; b32 EnumUnderlyingMacro;
}; };
static_assert( sizeof(AST_Enum) == sizeof(AST), "ERROR: AST_Enum is not the same size as AST"); static_assert( sizeof(AST_Enum) == sizeof(AST), "ERROR: AST_Enum is not the same size as AST");
struct AST_Exec struct AST_Exec
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -210,7 +210,7 @@ static_assert( sizeof(AST_Exec) == sizeof(AST), "ERROR: AST_Exec is not the same
struct AST_Expr struct AST_Expr
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -225,7 +225,7 @@ static_assert( sizeof(AST_Expr) == sizeof(AST), "ERROR: AST_Expr is not the same
struct AST_Expr_Assign struct AST_Expr_Assign
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -240,7 +240,7 @@ static_assert( sizeof(AST_Expr_Assign) == sizeof(AST), "ERROR: AST_Expr_Assign i
struct AST_Expr_Alignof struct AST_Expr_Alignof
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -255,7 +255,7 @@ static_assert( sizeof(AST_Expr_Alignof) == sizeof(AST), "ERROR: AST_Expr_Alignof
struct AST_Expr_Binary struct AST_Expr_Binary
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -270,7 +270,7 @@ static_assert( sizeof(AST_Expr_Binary) == sizeof(AST), "ERROR: AST_Expr_Binary i
struct AST_Expr_CStyleCast struct AST_Expr_CStyleCast
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -285,7 +285,7 @@ static_assert( sizeof(AST_Expr_CStyleCast) == sizeof(AST), "ERROR: AST_Expr_CSty
struct AST_Expr_FunctionalCast struct AST_Expr_FunctionalCast
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -300,7 +300,7 @@ static_assert( sizeof(AST_Expr_FunctionalCast) == sizeof(AST), "ERROR: AST_Expr_
struct AST_Expr_CppCast struct AST_Expr_CppCast
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -315,7 +315,7 @@ static_assert( sizeof(AST_Expr_CppCast) == sizeof(AST), "ERROR: AST_Expr_CppCast
struct AST_Expr_ProcCall struct AST_Expr_ProcCall
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -330,7 +330,7 @@ static_assert( sizeof(AST_Expr_ProcCall) == sizeof(AST), "ERROR: AST_Expr_Identi
struct AST_Expr_Decltype struct AST_Expr_Decltype
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -345,7 +345,7 @@ static_assert( sizeof(AST_Expr_Decltype) == sizeof(AST), "ERROR: AST_Expr_Declty
struct AST_Expr_Comma struct AST_Expr_Comma
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -360,7 +360,7 @@ static_assert( sizeof(AST_Expr_Comma) == sizeof(AST), "ERROR: AST_Expr_Comma is
struct AST_Expr_AMS struct AST_Expr_AMS
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -375,7 +375,7 @@ static_assert( sizeof(AST_Expr_AMS) == sizeof(AST), "ERROR: AST_Expr_AMS is not
struct AST_Expr_Sizeof struct AST_Expr_Sizeof
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -390,7 +390,7 @@ static_assert( sizeof(AST_Expr_Sizeof) == sizeof(AST), "ERROR: AST_Expr_Sizeof i
struct AST_Expr_Subscript struct AST_Expr_Subscript
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -405,7 +405,7 @@ static_assert( sizeof(AST_Expr_Subscript) == sizeof(AST), "ERROR: AST_Expr_Subsc
struct AST_Expr_Ternary struct AST_Expr_Ternary
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -420,7 +420,7 @@ static_assert( sizeof(AST_Expr_Ternary) == sizeof(AST), "ERROR: AST_Expr_Ternary
struct AST_Expr_UnaryPrefix struct AST_Expr_UnaryPrefix
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -435,7 +435,7 @@ static_assert( sizeof(AST_Expr_UnaryPrefix) == sizeof(AST), "ERROR: AST_Expr_Una
struct AST_Expr_UnaryPostfix struct AST_Expr_UnaryPostfix
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -450,7 +450,7 @@ static_assert( sizeof(AST_Expr_UnaryPostfix) == sizeof(AST), "ERROR: AST_Expr_Un
struct AST_Expr_Element struct AST_Expr_Element
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -466,7 +466,7 @@ static_assert( sizeof(AST_Expr_Element) == sizeof(AST), "ERROR: AST_Expr_Element
struct AST_Extern struct AST_Extern
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ]; char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ];
@ -487,7 +487,7 @@ static_assert( sizeof(AST_Extern) == sizeof(AST), "ERROR: AST_Extern is not the
struct AST_Include struct AST_Include
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -503,7 +503,7 @@ static_assert( sizeof(AST_Include) == sizeof(AST), "ERROR: AST_Include is not th
struct AST_Friend struct AST_Friend
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -525,7 +525,7 @@ static_assert( sizeof(AST_Friend) == sizeof(AST), "ERROR: AST_Friend is not the
struct AST_Fn struct AST_Fn
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -550,7 +550,7 @@ static_assert( sizeof(AST_Fn) == sizeof(AST), "ERROR: AST_Fn is not the same siz
struct AST_Module struct AST_Module
{ {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
Code Prev; Code Prev;
Code Next; Code Next;
parser::Token* Tok; parser::Token* Tok;
@ -565,7 +565,7 @@ static_assert( sizeof(AST_Module) == sizeof(AST), "ERROR: AST_Module is not the
struct AST_NS struct AST_NS
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct { struct {
char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ]; char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ];
CodeBody Body; CodeBody Body;
@ -586,7 +586,7 @@ static_assert( sizeof(AST_NS) == sizeof(AST), "ERROR: AST_NS is not the same siz
struct AST_Operator struct AST_Operator
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -612,7 +612,7 @@ static_assert( sizeof(AST_Operator) == sizeof(AST), "ERROR: AST_Operator is not
struct AST_OpCast struct AST_OpCast
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -637,7 +637,7 @@ static_assert( sizeof(AST_OpCast) == sizeof(AST), "ERROR: AST_OpCast is not the
struct AST_Param struct AST_Param
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ]; char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ];
@ -662,7 +662,7 @@ static_assert( sizeof(AST_Param) == sizeof(AST), "ERROR: AST_Param is not the sa
struct AST_Pragma struct AST_Pragma
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -678,7 +678,7 @@ static_assert( sizeof(AST_Pragma) == sizeof(AST), "ERROR: AST_Pragma is not the
struct AST_PreprocessCond struct AST_PreprocessCond
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StringCached Content; StringCached Content;
}; };
Code Prev; Code Prev;
@ -693,7 +693,7 @@ static_assert( sizeof(AST_PreprocessCond) == sizeof(AST), "ERROR: AST_Preprocess
struct AST_Specifiers struct AST_Specifiers
{ {
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ]; SpecifierT ArrSpecs[ AST_ArrSpecs_Cap ];
CodeSpecifiers NextSpecs; CodeSpecifiers NextSpecs;
Code Prev; Code Prev;
Code Next; Code Next;
@ -710,7 +710,7 @@ static_assert( sizeof(AST_Specifiers) == sizeof(AST), "ERROR: AST_Specifier is n
struct AST_Stmt struct AST_Stmt
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -725,7 +725,7 @@ static_assert( sizeof(AST_Stmt) == sizeof(AST), "ERROR: AST_Stmt is not the same
struct AST_Stmt_Break struct AST_Stmt_Break
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -740,7 +740,7 @@ static_assert( sizeof(AST_Stmt_Break) == sizeof(AST), "ERROR: AST_Stmt_Break is
struct AST_Stmt_Case struct AST_Stmt_Case
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -755,7 +755,7 @@ static_assert( sizeof(AST_Stmt_Case) == sizeof(AST), "ERROR: AST_Stmt_Case is no
struct AST_Stmt_Continue struct AST_Stmt_Continue
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -770,7 +770,7 @@ static_assert( sizeof(AST_Stmt_Continue) == sizeof(AST), "ERROR: AST_Stmt_Contin
struct AST_Stmt_Decl struct AST_Stmt_Decl
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -785,7 +785,7 @@ static_assert( sizeof(AST_Stmt_Decl) == sizeof(AST), "ERROR: AST_Stmt_Decl is no
struct AST_Stmt_Do struct AST_Stmt_Do
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -800,7 +800,7 @@ static_assert( sizeof(AST_Stmt_Do) == sizeof(AST), "ERROR: AST_Stmt_Do is not th
struct AST_Stmt_Expr struct AST_Stmt_Expr
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -815,7 +815,7 @@ static_assert( sizeof(AST_Stmt_Expr) == sizeof(AST), "ERROR: AST_Stmt_Expr is no
struct AST_Stmt_Else struct AST_Stmt_Else
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -830,7 +830,7 @@ static_assert( sizeof(AST_Stmt_Else) == sizeof(AST), "ERROR: AST_Stmt_Else is no
struct AST_Stmt_If struct AST_Stmt_If
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -845,7 +845,7 @@ static_assert( sizeof(AST_Stmt_If) == sizeof(AST), "ERROR: AST_Stmt_If is not th
struct AST_Stmt_For struct AST_Stmt_For
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -860,7 +860,7 @@ static_assert( sizeof(AST_Stmt_For) == sizeof(AST), "ERROR: AST_Stmt_For is not
struct AST_Stmt_Goto struct AST_Stmt_Goto
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -875,7 +875,7 @@ static_assert( sizeof(AST_Stmt_Goto) == sizeof(AST), "ERROR: AST_Stmt_Goto is no
struct AST_Stmt_Label struct AST_Stmt_Label
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -890,7 +890,7 @@ static_assert( sizeof(AST_Stmt_Label) == sizeof(AST), "ERROR: AST_Stmt_Label is
struct AST_Stmt_Switch struct AST_Stmt_Switch
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -905,7 +905,7 @@ static_assert( sizeof(AST_Stmt_Switch) == sizeof(AST), "ERROR: AST_Stmt_Switch i
struct AST_Stmt_While struct AST_Stmt_While
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
}; };
CodeExpr Prev; CodeExpr Prev;
CodeExpr Next; CodeExpr Next;
@ -921,7 +921,7 @@ static_assert( sizeof(AST_Stmt_While) == sizeof(AST), "ERROR: AST_Stmt_While is
struct AST_Struct struct AST_Struct
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -947,7 +947,7 @@ static_assert( sizeof(AST_Struct) == sizeof(AST), "ERROR: AST_Struct is not the
struct AST_Template struct AST_Template
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ]; char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
@ -972,7 +972,7 @@ static_assert( sizeof(AST_Template) == sizeof(AST), "ERROR: AST_Template is not
struct AST_Type struct AST_Type
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
char _PAD_INLINE_CMT_[ sizeof(AST*) ]; char _PAD_INLINE_CMT_[ sizeof(AST*) ];
@ -1000,7 +1000,7 @@ static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same
struct AST_Type struct AST_Type
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
char _PAD_INLINE_CMT_[ sizeof(AST*) ]; char _PAD_INLINE_CMT_[ sizeof(AST*) ];
@ -1026,7 +1026,7 @@ static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same
struct AST_Typedef struct AST_Typedef
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -1049,7 +1049,7 @@ static_assert( sizeof(AST_Typedef) == sizeof(AST), "ERROR: AST_Typedef is not th
struct AST_Union struct AST_Union
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
char _PAD_INLINE_CMT_[ sizeof(AST*) ]; char _PAD_INLINE_CMT_[ sizeof(AST*) ];
@ -1073,7 +1073,7 @@ static_assert( sizeof(AST_Union) == sizeof(AST), "ERROR: AST_Union is not the sa
struct AST_Using struct AST_Using
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;
@ -1097,7 +1097,7 @@ static_assert( sizeof(AST_Using) == sizeof(AST), "ERROR: AST_Using is not the sa
struct AST_Var struct AST_Var
{ {
union { union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; char _PAD_[ sizeof(SpecifierT) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct struct
{ {
CodeComment InlineCmt; CodeComment InlineCmt;

File diff suppressed because it is too large Load Diff

View File

@ -3,47 +3,45 @@
#include "ast.hpp" #include "ast.hpp"
#endif #endif
void append ( CodeBody body, Code other );
void append ( CodeBody body, CodeBody other );
String to_string ( CodeBody body );
void to_string ( CodeBody body, String* result );
void to_string_export ( CodeBody body, String* result );
void add_interface( CodeClass self, CodeType interface );
String to_string ( CodeClass self );
void to_string_def( CodeClass self, String* result );
void to_string_fwd( CodeClass self, String* result );
#pragma region Code Types #pragma region Code Types
// These structs are not used at all by the C vairant.
#if ! GEN_COMPILER_C
// stati_assert( GEN_COMPILER_C, "This should not be compiled with the C-library" );
struct CodeBody struct CodeBody
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
Using_Code( CodeBody ); Using_Code( CodeBody );
void append( Code other ) void append( Code other ) { return GEN_NS append( *this, other ); }
{ void append( CodeBody body ) { return GEN_NS append(*this, body); }
raw()->append( other.ast ); bool has_entries() { return GEN_NS has_entries(rcast( AST*, ast )); }
}
void append( CodeBody body ) String to_string() { return GEN_NS to_string(* this); }
{ void to_string( String& result ) { return GEN_NS to_string(* this, & result ); }
for ( Code entry : body ) void to_string_export( String& result ) { return GEN_NS to_string_export(* this, & result); }
{ #endif
append( entry );
} Using_CodeOps( CodeBody );
} operator Code() { return * rcast( Code*, this ); }
bool has_entries() AST_Body* operator->() { return ast; }
{
return rcast( AST*, ast )->has_entries();
}
void to_string( String& result );
void to_string_export( String& result );
AST* raw()
{
return rcast( AST*, ast );
}
AST_Body* operator->()
{
return ast;
}
operator Code()
{
return * rcast( Code*, this );
}
#pragma region Iterator #pragma region Iterator
Code begin() Code begin()
{ {
if ( ast ) if ( ast )
return { rcast( AST*, ast)->Front }; return { rcast( AST*, ast)->Front };
return { nullptr }; return { nullptr };
} }
Code end() Code end()
@ -57,21 +55,18 @@ struct CodeBody
struct CodeClass struct CodeClass
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 0
Using_Code( CodeClass ); Using_Code( CodeClass );
void add_interface( CodeType interface ); void add_interface( CodeType interface );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_fwd( String& result );
#endif
AST* raw() Using_CodeOps( CodeClass );
{ operator Code() { return * rcast( Code*, this ); }
return rcast( AST*, ast );
}
operator Code()
{
return * rcast( Code*, this );
}
AST_Class* operator->() AST_Class* operator->()
{ {
if ( ast == nullptr ) if ( ast == nullptr )
@ -86,13 +81,17 @@ struct CodeClass
struct CodeParam struct CodeParam
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeParam ); Using_Code( CodeParam );
void append( CodeParam other ); void append( CodeParam other );
CodeParam get( s32 idx ); CodeParam get( s32 idx );
bool has_entries(); bool has_entries();
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps( CodeParam );
AST* raw() AST* raw()
{ {
return rcast( AST*, ast ); return rcast( AST*, ast );
@ -135,6 +134,7 @@ struct CodeParam
struct CodeSpecifiers struct CodeSpecifiers
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeSpecifiers ); Using_Code( CodeSpecifiers );
bool append( SpecifierT spec ) bool append( SpecifierT spec )
@ -145,9 +145,9 @@ struct CodeSpecifiers
return false; return false;
} }
if ( raw()->NumEntries == AST::ArrSpecs_Cap ) if ( raw()->NumEntries == AST_ArrSpecs_Cap )
{ {
log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST::ArrSpecs_Cap ); log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST_ArrSpecs_Cap );
return false; return false;
} }
@ -165,7 +165,51 @@ struct CodeSpecifiers
return -1; return -1;
} }
void to_string( String& result ); s32 remove( SpecifierT to_remove )
{
if ( ast == nullptr )
{
log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!");
return -1;
}
if ( raw()->NumEntries == AST_ArrSpecs_Cap )
{
log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST_ArrSpecs_Cap );
return -1;
}
s32 result = -1;
s32 curr = 0;
s32 next = 0;
for(; next < raw()->NumEntries; ++ curr, ++ next)
{
SpecifierT spec = raw()->ArrSpecs[next];
if (spec == to_remove)
{
result = next;
next ++;
if (next >= raw()->NumEntries)
break;
spec = raw()->ArrSpecs[next];
}
raw()->ArrSpecs[ curr ] = spec;
}
if (result > -1) {
raw()->NumEntries --;
}
return result;
}
String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeSpecifiers);
AST* raw() AST* raw()
{ {
return rcast( AST*, ast ); return rcast( AST*, ast );
@ -202,13 +246,17 @@ struct CodeSpecifiers
struct CodeStruct struct CodeStruct
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeStruct ); Using_Code( CodeStruct );
void add_interface( CodeType interface ); void add_interface( CodeType interface );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_fwd( String& result );
void to_string_def( String& result );
#endif
Using_CodeOps( CodeStruct );
AST* raw() AST* raw()
{ {
return rcast( AST*, ast ); return rcast( AST*, ast );
@ -229,27 +277,47 @@ struct CodeStruct
AST_Struct* ast; AST_Struct* ast;
}; };
#define Define_CodeType( Typename ) \ struct CodeAttributes
struct Code##Typename \ {
{ \ #if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( Code ## Typename ); \ Using_Code(CodeAttributes);
AST* raw(); \ String to_string();
operator Code(); \ #endif
AST_##Typename* operator->(); \
AST_##Typename* ast; \ Using_CodeOps(CodeAttributes);
} AST *raw();
operator Code();
AST_Attributes *operator->();
AST_Attributes *ast;
};
Define_CodeType( Attributes );
// Define_CodeType( BaseClass ); // Define_CodeType( BaseClass );
Define_CodeType( Comment );
struct CodeComment
{
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code(CodeComment);
String to_string();
#endif
Using_CodeOps(CodeComment);
AST *raw();
operator Code();
AST_Comment *operator->();
AST_Comment *ast;
};
struct CodeConstructor struct CodeConstructor
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeConstructor ); Using_Code( CodeConstructor );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_fwd( String& result );
#endif
Using_CodeOps(CodeConstructor);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Constructor* operator->(); AST_Constructor* operator->();
@ -258,10 +326,14 @@ struct CodeConstructor
struct CodeDefine struct CodeDefine
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeDefine ); Using_Code( CodeDefine );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeDefine);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Define* operator->(); AST_Define* operator->();
@ -270,11 +342,15 @@ struct CodeDefine
struct CodeDestructor struct CodeDestructor
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeDestructor ); Using_Code( CodeDestructor );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_fwd( String& result );
#endif
Using_CodeOps(CodeDestructor);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Destructor* operator->(); AST_Destructor* operator->();
@ -283,20 +359,36 @@ struct CodeDestructor
struct CodeEnum struct CodeEnum
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeEnum ); Using_Code( CodeEnum );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_class_def( String& result ); void to_string_fwd( String& result );
void to_string_class_fwd( String& result ); void to_string_class_def( String& result );
void to_string_class_fwd( String& result );
#endif
Using_CodeOps(CodeEnum);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Enum* operator->(); AST_Enum* operator->();
AST_Enum* ast; AST_Enum* ast;
}; };
Define_CodeType( Exec ); struct CodeExec
{
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code(CodeExec);
String to_string();
#endif
Using_CodeOps(CodeExec);
AST *raw();
operator Code();
AST_Exec *operator->();
AST_Exec *ast;
};
#if GEN_EXECUTION_EXPRESSION_SUPPORT #if GEN_EXECUTION_EXPRESSION_SUPPORT
struct CodeExpr struct CodeExpr
@ -506,10 +598,13 @@ struct CodeExpr_UnaryPostfix
struct CodeExtern struct CodeExtern
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeExtern ); Using_Code( CodeExtern );
void to_string( String& result ); void to_string( String& result );
#endif
Using_CodeOps(CodeExtern);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Extern* operator->(); AST_Extern* operator->();
@ -518,10 +613,14 @@ struct CodeExtern
struct CodeInclude struct CodeInclude
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeInclude ); Using_Code( CodeInclude );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeInclude);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Include* operator->(); AST_Include* operator->();
@ -530,10 +629,14 @@ struct CodeInclude
struct CodeFriend struct CodeFriend
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeFriend ); Using_Code( CodeFriend );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeFriend);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Friend* operator->(); AST_Friend* operator->();
@ -542,11 +645,15 @@ struct CodeFriend
struct CodeFn struct CodeFn
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeFn ); Using_Code( CodeFn );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_fwd( String& result );
#endif
Using_CodeOps(CodeFn);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Fn* operator->(); AST_Fn* operator->();
@ -555,10 +662,14 @@ struct CodeFn
struct CodeModule struct CodeModule
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeModule ); Using_Code( CodeModule );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeModule);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Module* operator->(); AST_Module* operator->();
@ -567,10 +678,14 @@ struct CodeModule
struct CodeNS struct CodeNS
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeNS ); Using_Code( CodeNS );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeNS);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_NS* operator->(); AST_NS* operator->();
@ -579,11 +694,15 @@ struct CodeNS
struct CodeOperator struct CodeOperator
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeOperator ); Using_Code( CodeOperator );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_fwd( String& result );
#endif
Using_CodeOps(CodeOperator);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Operator* operator->(); AST_Operator* operator->();
@ -592,11 +711,15 @@ struct CodeOperator
struct CodeOpCast struct CodeOpCast
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeOpCast ); Using_Code( CodeOpCast );
void to_string_def( String& result ); String to_string();
void to_string_fwd( String& result ); void to_string_def( String& result );
void to_string_fwd( String& result );
#endif
Using_CodeOps(CodeOpCast);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_OpCast* operator->(); AST_OpCast* operator->();
@ -605,10 +728,14 @@ struct CodeOpCast
struct CodePragma struct CodePragma
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodePragma ); Using_Code( CodePragma );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps( CodePragma );
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Pragma* operator->(); AST_Pragma* operator->();
@ -617,15 +744,19 @@ struct CodePragma
struct CodePreprocessCond struct CodePreprocessCond
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodePreprocessCond ); Using_Code( CodePreprocessCond );
void to_string_if( String& result ); String to_string();
void to_string_ifdef( String& result ); void to_string_if( String& result );
void to_string_ifndef( String& result ); void to_string_ifdef( String& result );
void to_string_elif( String& result ); void to_string_ifndef( String& result );
void to_string_else( String& result ); void to_string_elif( String& result );
void to_string_endif( String& result ); void to_string_else( String& result );
void to_string_endif( String& result );
#endif
Using_CodeOps( CodePreprocessCond );
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_PreprocessCond* operator->(); AST_PreprocessCond* operator->();
@ -637,7 +768,8 @@ struct CodeStmt
{ {
Using_Code( CodeStmt ); Using_Code( CodeStmt );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -649,7 +781,8 @@ struct CodeStmt_Break
{ {
Using_Code( CodeStmt_Break ); Using_Code( CodeStmt_Break );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -661,7 +794,8 @@ struct CodeStmt_Case
{ {
Using_Code( CodeStmt_Case ); Using_Code( CodeStmt_Case );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -673,7 +807,8 @@ struct CodeStmt_Continue
{ {
Using_Code( CodeStmt_Continue ); Using_Code( CodeStmt_Continue );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -685,7 +820,8 @@ struct CodeStmt_Decl
{ {
Using_Code( CodeStmt_Decl ); Using_Code( CodeStmt_Decl );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -697,7 +833,8 @@ struct CodeStmt_Do
{ {
Using_Code( CodeStmt_Do ); Using_Code( CodeStmt_Do );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -709,7 +846,8 @@ struct CodeStmt_Expr
{ {
Using_Code( CodeStmt_Expr ); Using_Code( CodeStmt_Expr );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -721,7 +859,8 @@ struct CodeStmt_Else
{ {
Using_Code( CodeStmt_Else ); Using_Code( CodeStmt_Else );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -733,7 +872,8 @@ struct CodeStmt_If
{ {
Using_Code( CodeStmt_If ); Using_Code( CodeStmt_If );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -745,7 +885,8 @@ struct CodeStmt_For
{ {
Using_Code( CodeStmt_For ); Using_Code( CodeStmt_For );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -757,7 +898,8 @@ struct CodeStmt_Goto
{ {
Using_Code( CodeStmt_Goto ); Using_Code( CodeStmt_Goto );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -769,7 +911,8 @@ struct CodeStmt_Label
{ {
Using_Code( CodeStmt_Label ); Using_Code( CodeStmt_Label );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -781,7 +924,8 @@ struct CodeStmt_Switch
{ {
Using_Code( CodeStmt_Switch ); Using_Code( CodeStmt_Switch );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -793,7 +937,8 @@ struct CodeStmt_While
{ {
Using_Code( CodeStmt_While ); Using_Code( CodeStmt_While );
void to_string( String& result ); String to_string();
void to_string( String& result );
AST* raw(); AST* raw();
operator Code(); operator Code();
@ -804,10 +949,14 @@ struct CodeStmt_While
struct CodeTemplate struct CodeTemplate
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeTemplate ); Using_Code( CodeTemplate );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps( CodeTemplate );
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Template* operator->(); AST_Template* operator->();
@ -816,10 +965,14 @@ struct CodeTemplate
struct CodeType struct CodeType
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeType ); Using_Code( CodeType );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps( CodeType );
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Type* operator->(); AST_Type* operator->();
@ -828,10 +981,14 @@ struct CodeType
struct CodeTypedef struct CodeTypedef
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeTypedef ); Using_Code( CodeTypedef );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps( CodeTypedef );
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Typedef* operator->(); AST_Typedef* operator->();
@ -840,10 +997,14 @@ struct CodeTypedef
struct CodeUnion struct CodeUnion
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeUnion ); Using_Code( CodeUnion );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeUnion);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Union* operator->(); AST_Union* operator->();
@ -852,11 +1013,15 @@ struct CodeUnion
struct CodeUsing struct CodeUsing
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeUsing ); Using_Code( CodeUsing );
void to_string( String& result ); String to_string();
void to_string_ns( String& result ); void to_string( String& result );
void to_string_ns( String& result );
#endif
Using_CodeOps(CodeUsing);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Using* operator->(); AST_Using* operator->();
@ -865,10 +1030,14 @@ struct CodeUsing
struct CodeVar struct CodeVar
{ {
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
Using_Code( CodeVar ); Using_Code( CodeVar );
void to_string( String& result ); String to_string();
void to_string( String& result );
#endif
Using_CodeOps(CodeVar);
AST* raw(); AST* raw();
operator Code(); operator Code();
AST_Var* operator->(); AST_Var* operator->();
@ -877,5 +1046,11 @@ struct CodeVar
#undef Define_CodeType #undef Define_CodeType
#undef Using_Code #undef Using_Code
#undef Using_CodeOps
#if GEN_SUPPORT_CPP_REFERENCES
void to_string_export( CodeBody body, String& result ) { return to_string_export(body, & result); };
#endif
#endif //if ! GEN_COMPILER_C
#pragma endregion Code Types #pragma endregion Code Types

File diff suppressed because it is too large Load Diff

View File

@ -133,6 +133,7 @@ extern CodeType t_typename;
#pragma region Macros #pragma region Macros
#ifndef token_fmt
# define gen_main main # define gen_main main
# define __ NoCode # define __ NoCode
@ -151,6 +152,7 @@ extern CodeType t_typename;
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string. // Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
# define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) # define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ )
#endif
#pragma endregion Macros #pragma endregion Macros

View File

@ -4,56 +4,82 @@
#endif #endif
inline inline
void AST::append( AST* other ) void append( AST* self, AST* other )
{ {
GEN_ASSERT(self != nullptr);
GEN_ASSERT(other != nullptr);
if ( other->Parent ) if ( other->Parent )
other = other->duplicate(); other = duplicate(other);
other->Parent = this; other->Parent = self;
if ( Front == nullptr ) if ( self->Front == nullptr )
{ {
Front = other; self->Front = other;
Back = other; self->Back = other;
NumEntries++; self->NumEntries++;
return; return;
} }
AST* AST*
Current = Back; Current = self->Back;
Current->Next = other; Current->Next = other;
other->Prev = Current; other->Prev = Current;
Back = other; self->Back = other;
NumEntries++; self->NumEntries++;
} }
inline inline
Code& AST::entry( u32 idx ) Code* entry( AST* self, u32 idx )
{ {
AST** current = & Front; GEN_ASSERT(self != nullptr);
AST** current = & self->Front;
while ( idx >= 0 && current != nullptr ) while ( idx >= 0 && current != nullptr )
{ {
if ( idx == 0 ) if ( idx == 0 )
return * rcast( Code*, current); return rcast( Code*, current);
current = & ( * current )->Next; current = & ( * current )->Next;
idx--; idx--;
} }
return * rcast( Code*, current); return rcast( Code*, current);
} }
inline inline
bool AST::has_entries() bool has_entries(AST* self)
{ {
return NumEntries > 0; GEN_ASSERT(self != nullptr);
return self->NumEntries > 0;
} }
inline inline
char const* AST::type_str() bool is_body(AST* self)
{ {
return ECode::to_str( Type ); GEN_ASSERT(self != nullptr);
switch (self->Type)
{
case ECode::Enum_Body:
case ECode::Class_Body:
case ECode::Union_Body:
case ECode::Export_Body:
case ECode::Global_Body:
case ECode::Struct_Body:
case ECode::Function_Body:
case ECode::Namespace_Body:
case ECode::Extern_Linkage_Body:
return true;
}
return false;
}
inline
char const* type_str(AST* self)
{
GEN_ASSERT(self != nullptr);
return ECode::to_str( self->Type );
} }
inline inline
@ -62,6 +88,69 @@ AST::operator Code()
return { this }; return { this };
} }
#pragma region Code
inline
char const* debug_str( Code code )
{
if ( code.ast == nullptr )
return "Code::debug_str: AST is null!";
return debug_str( code.ast );
}
inline
Code duplicate( Code code )
{
if ( code.ast == nullptr )
{
log_failure("Code::duplicate: Cannot duplicate code, AST is null!");
return Code_Invalid;
}
return { duplicate(code.ast) };
}
inline
bool is_body(Code code)
{
if ( code.ast == nullptr )
{
return is_body(code.ast);
}
return false;
}
inline
bool is_equal( Code self, Code other )
{
if ( self.ast == nullptr || other.ast == nullptr )
{
// Just check if they're both null.
// log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return self.ast == nullptr && other.ast == nullptr;
}
return is_equal( self.ast, other.ast );
}
inline
bool is_valid(Code self)
{
return self.ast != nullptr && self.ast->Type != CodeT::Invalid;
}
inline
void set_global(Code self)
{
if ( self.ast == nullptr )
{
log_failure("Code::set_global: Cannot set code as global, AST is null!");
return;
}
self->Parent = Code_Global.ast;
}
inline inline
Code& Code::operator ++() Code& Code::operator ++()
{ {
@ -71,14 +160,38 @@ Code& Code::operator ++()
return *this; return *this;
} }
#pragma endregion Code
inline inline
void CodeClass::add_interface( CodeType type ) void append( CodeBody self, Code other )
{ {
CodeType possible_slot = ast->ParentType; GEN_ASSERT(other.ast != nullptr);
if (is_body(other)) {
append( self, cast(CodeBody, other) );
return;
}
append( rcast(AST*, self.ast), other.ast );
}
inline
void append( CodeBody self, CodeBody body )
{
for ( Code entry : body ) {
append( self, entry );
}
}
inline
void add_interface( CodeClass self, CodeType type )
{
GEN_ASSERT(self.ast !=nullptr);
CodeType possible_slot = self->ParentType;
if ( possible_slot.ast ) if ( possible_slot.ast )
{ {
// Were adding an interface to parent type, so we need to make sure the parent type is public. // Were adding an interface to parent type, so we need to make sure the parent type is public.
ast->ParentAccess = AccessSpec::Public; self->ParentAccess = AccessSpec_Public;
// If your planning on adding a proper parent, // If your planning on adding a proper parent,
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. // then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
} }
@ -98,7 +211,7 @@ void CodeParam::append( CodeParam other )
AST* entry = (AST*) other.ast; AST* entry = (AST*) other.ast;
if ( entry->Parent ) if ( entry->Parent )
entry = entry->duplicate(); entry = GEN_NS duplicate( entry );
entry->Parent = self; entry->Parent = self;
@ -151,7 +264,7 @@ void CodeStruct::add_interface( CodeType type )
if ( possible_slot.ast ) if ( possible_slot.ast )
{ {
// Were adding an interface to parent type, so we need to make sure the parent type is public. // Were adding an interface to parent type, so we need to make sure the parent type is public.
ast->ParentAccess = AccessSpec::Public; ast->ParentAccess = AccessSpec_Public;
// If your planning on adding a proper parent, // If your planning on adding a proper parent,
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. // then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
} }
@ -183,7 +296,7 @@ CodeBody def_body( CodeT type )
default: default:
log_failure( "def_body: Invalid type %s", (char const*)ECode::to_str(type) ); log_failure( "def_body: Invalid type %s", (char const*)ECode::to_str(type) );
return (CodeBody)Code::Invalid; return (CodeBody)Code_Invalid;
} }
Code Code

View File

@ -11,7 +11,7 @@ internal void deinit();
internal internal
void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags )
{ {
Arena* last = & Global_AllocatorBuckets.back(); Arena* last = back(& Global_AllocatorBuckets);
switch ( type ) switch ( type )
{ {
@ -19,18 +19,18 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s
{ {
if ( ( last->TotalUsed + size ) > last->TotalSize ) if ( ( last->TotalUsed + size ) > last->TotalSize )
{ {
Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize );
if ( bucket.PhysicalStart == nullptr ) if ( bucket.PhysicalStart == nullptr )
GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets");
if ( ! Global_AllocatorBuckets.append( bucket ) ) if ( ! append( & Global_AllocatorBuckets, bucket ) )
GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets");
last = & Global_AllocatorBuckets.back(); last = back(& Global_AllocatorBuckets);
} }
return alloc_align( * last, size, alignment ); return alloc_align( allocator_info(last), size, alignment );
} }
case EAllocation_FREE: case EAllocation_FREE:
{ {
@ -46,15 +46,15 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s
{ {
if ( last->TotalUsed + size > last->TotalSize ) if ( last->TotalUsed + size > last->TotalSize )
{ {
Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize );
if ( bucket.PhysicalStart == nullptr ) if ( bucket.PhysicalStart == nullptr )
GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets");
if ( ! Global_AllocatorBuckets.append( bucket ) ) if ( ! append( & Global_AllocatorBuckets, bucket ) )
GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets");
last = & Global_AllocatorBuckets.back(); last = back(& Global_AllocatorBuckets);
} }
void* result = alloc_align( last->Backing, size, alignment ); void* result = alloc_align( last->Backing, size, alignment );
@ -74,74 +74,74 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s
internal internal
void define_constants() void define_constants()
{ {
Code::Global = make_code(); Code_Global = make_code();
Code::Global->Name = get_cached_string( txt("Global Code") ); scast(String, Code_Global->Name) = get_cached_string( txt("Global Code") );
Code::Global->Content = Code::Global->Name; scast(String, Code_Global->Content) = Code_Global->Name;
Code::Invalid = make_code(); Code_Invalid = make_code();
Code::Invalid.set_global(); set_global(Code_Invalid);
t_empty = (CodeType) make_code(); t_empty = (CodeType) make_code();
t_empty->Type = ECode::Typename; t_empty->Type = ECode::Typename;
t_empty->Name = get_cached_string( txt("") ); t_empty->Name = get_cached_string( txt("") );
t_empty.set_global(); set_global(t_empty);
access_private = make_code(); access_private = make_code();
access_private->Type = ECode::Access_Private; access_private->Type = ECode::Access_Private;
access_private->Name = get_cached_string( txt("private:\n") ); access_private->Name = get_cached_string( txt("private:\n") );
access_private.set_global(); set_global(access_private);
access_protected = make_code(); access_protected = make_code();
access_protected->Type = ECode::Access_Protected; access_protected->Type = ECode::Access_Protected;
access_protected->Name = get_cached_string( txt("protected:\n") ); access_protected->Name = get_cached_string( txt("protected:\n") );
access_protected.set_global(); set_global(access_protected);
access_public = make_code(); access_public = make_code();
access_public->Type = ECode::Access_Public; access_public->Type = ECode::Access_Public;
access_public->Name = get_cached_string( txt("public:\n") ); access_public->Name = get_cached_string( txt("public:\n") );
access_public.set_global(); set_global(access_public);
attrib_api_export = def_attributes( code(GEN_API_Export_Code)); attrib_api_export = def_attributes( code(GEN_API_Export_Code));
attrib_api_export.set_global(); set_global(attrib_api_export);
attrib_api_import = def_attributes( code(GEN_API_Import_Code)); attrib_api_import = def_attributes( code(GEN_API_Import_Code));
attrib_api_import.set_global(); set_global(attrib_api_import);
module_global_fragment = make_code(); module_global_fragment = make_code();
module_global_fragment->Type = ECode::Untyped; module_global_fragment->Type = ECode::Untyped;
module_global_fragment->Name = get_cached_string( txt("module;") ); module_global_fragment->Name = get_cached_string( txt("module;") );
module_global_fragment->Content = module_global_fragment->Name; module_global_fragment->Content = module_global_fragment->Name;
module_global_fragment.set_global(); set_global(module_global_fragment);
module_private_fragment = make_code(); module_private_fragment = make_code();
module_private_fragment->Type = ECode::Untyped; module_private_fragment->Type = ECode::Untyped;
module_private_fragment->Name = get_cached_string( txt("module : private;") ); module_private_fragment->Name = get_cached_string( txt("module : private;") );
module_private_fragment->Content = module_private_fragment->Name; module_private_fragment->Content = module_private_fragment->Name;
module_private_fragment.set_global(); set_global(module_private_fragment);
fmt_newline = make_code(); fmt_newline = make_code();
fmt_newline->Type = ECode::NewLine; fmt_newline->Type = ECode::NewLine;
fmt_newline.set_global(); set_global(fmt_newline);
pragma_once = (CodePragma) make_code(); pragma_once = (CodePragma) make_code();
pragma_once->Type = ECode::Preprocess_Pragma; pragma_once->Type = ECode::Preprocess_Pragma;
pragma_once->Name = get_cached_string( txt("once") ); pragma_once->Name = get_cached_string( txt("once") );
pragma_once->Content = pragma_once->Name; pragma_once->Content = pragma_once->Name;
pragma_once.set_global(); set_global(pragma_once);
param_varadic = (CodeType) make_code(); param_varadic = (CodeType) make_code();
param_varadic->Type = ECode::Parameters; param_varadic->Type = ECode::Parameters;
param_varadic->Name = get_cached_string( txt("...") ); param_varadic->Name = get_cached_string( txt("...") );
param_varadic->ValueType = t_empty; param_varadic->ValueType = t_empty;
param_varadic.set_global(); set_global(param_varadic);
preprocess_else = (CodePreprocessCond) make_code(); preprocess_else = (CodePreprocessCond) make_code();
preprocess_else->Type = ECode::Preprocess_Else; preprocess_else->Type = ECode::Preprocess_Else;
preprocess_else.set_global(); set_global(preprocess_else);
preprocess_endif = (CodePreprocessCond) make_code(); preprocess_endif = (CodePreprocessCond) make_code();
preprocess_endif->Type = ECode::Preprocess_EndIf; preprocess_endif->Type = ECode::Preprocess_EndIf;
preprocess_endif.set_global(); set_global(preprocess_endif);
# define def_constant_code_type( Type_ ) \ # define def_constant_code_type( Type_ ) \
t_##Type_ = def_type( name(Type_) ); \ t_##Type_ = def_type( name(Type_) ); \
@ -226,6 +226,10 @@ void define_constants()
# pragma pop_macro("local_persist") # pragma pop_macro("local_persist")
# pragma pop_macro("neverinline") # pragma pop_macro("neverinline")
# pragma push_macro("enum_underlying")
# pragma pop_macro("enum_underlying")
# undef def_constant_spec # undef def_constant_spec
} }
@ -235,28 +239,27 @@ void init()
{ {
GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr }; GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr };
Global_AllocatorBuckets = Array<Arena>::init_reserve( heap(), 128 ); Global_AllocatorBuckets = array_init_reserve<Arena>( heap(), 128 );
if ( Global_AllocatorBuckets == nullptr ) if ( Global_AllocatorBuckets == nullptr )
GEN_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 ); Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize );
if ( bucket.PhysicalStart == nullptr ) if ( bucket.PhysicalStart == nullptr )
GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets"); GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets");
Global_AllocatorBuckets.append( bucket ); append( & Global_AllocatorBuckets, bucket );
} }
// Setup the arrays // Setup the arrays
{ {
CodePools = Array<Pool>::init_reserve( Allocator_DataArrays, InitSize_DataArrays ); CodePools = array_init_reserve<Pool>( Allocator_DataArrays, InitSize_DataArrays );
if ( CodePools == nullptr ) if ( CodePools == nullptr )
GEN_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 ); StringArenas = array_init_reserve<Arena>( Allocator_DataArrays, InitSize_DataArrays );
if ( StringArenas == nullptr ) if ( StringArenas == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" ); GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" );
@ -264,33 +267,33 @@ void init()
// Setup the code pool and code entries arena. // Setup the code pool and code entries arena.
{ {
Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) );
if ( code_pool.PhysicalStart == nullptr ) if ( code_pool.PhysicalStart == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the code pool" ); GEN_FATAL( "gen::init: Failed to initialize the code pool" );
CodePools.append( code_pool ); append( & CodePools, code_pool );
LexArena = Arena::init_from_allocator( Allocator_Lexer, LexAllocator_Size ); LexArena = arena_init_from_allocator( Allocator_Lexer, LexAllocator_Size );
Arena string_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); Arena string_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena );
if ( string_arena.PhysicalStart == nullptr ) if ( string_arena.PhysicalStart == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the string arena" ); GEN_FATAL( "gen::init: Failed to initialize the string arena" );
StringArenas.append( string_arena ); append( & StringArenas, string_arena );
} }
// Setup the hash tables // Setup the hash tables
{ {
StringCache = StringTable::init( Allocator_StringTable ); StringCache = hashtable_init<StringCached>(Allocator_StringTable);
if ( StringCache.Entries == nullptr ) if ( StringCache.Entries == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the StringCache"); GEN_FATAL( "gen::init: Failed to initialize the StringCache");
} }
// Preprocessor Defines // Preprocessor Defines
PreprocessorDefines = Array<StringCached>::init_reserve( GlobalAllocator, kilobytes(1) ); PreprocessorDefines = array_init_reserve<StringCached>( GlobalAllocator, kilobytes(1) );
define_constants(); define_constants();
parser::init(); parser::init();
@ -299,62 +302,62 @@ void init()
void deinit() void deinit()
{ {
usize index = 0; usize index = 0;
usize left = CodePools.num(); usize left = num(CodePools);
do do
{ {
Pool* code_pool = & CodePools[index]; Pool* code_pool = & CodePools[index];
code_pool->free(); free(code_pool);
index++; index++;
} }
while ( left--, left ); while ( left--, left );
index = 0; index = 0;
left = StringArenas.num(); left = num(StringArenas);
do do
{ {
Arena* string_arena = & StringArenas[index]; Arena* string_arena = & StringArenas[index];
string_arena->free(); free(string_arena);
index++; index++;
} }
while ( left--, left ); while ( left--, left );
StringCache.destroy(); destroy(& StringCache);
CodePools.free(); free( & CodePools);
StringArenas.free(); free( & StringArenas);
LexArena.free(); free(& LexArena);
PreprocessorDefines.free(); free(& PreprocessorDefines);
index = 0; index = 0;
left = Global_AllocatorBuckets.num(); left = num(Global_AllocatorBuckets);
do do
{ {
Arena* bucket = & Global_AllocatorBuckets[ index ]; Arena* bucket = & Global_AllocatorBuckets[ index ];
bucket->free(); free(bucket);
index++; index++;
} }
while ( left--, left ); while ( left--, left );
Global_AllocatorBuckets.free(); free(Global_AllocatorBuckets);
parser::deinit(); parser::deinit();
} }
void reset() void reset()
{ {
s32 index = 0; s32 index = 0;
s32 left = CodePools.num(); s32 left = num(CodePools);
do do
{ {
Pool* code_pool = & CodePools[index]; Pool* code_pool = & CodePools[index];
code_pool->clear(); clear(* code_pool);
index++; index++;
} }
while ( left--, left ); while ( left--, left );
index = 0; index = 0;
left = StringArenas.num(); left = num(StringArenas);
do do
{ {
Arena* string_arena = & StringArenas[index]; Arena* string_arena = & StringArenas[index];
@ -363,28 +366,28 @@ void reset()
} }
while ( left--, left ); while ( left--, left );
StringCache.clear(); clear(StringCache);
define_constants(); define_constants();
} }
AllocatorInfo get_string_allocator( s32 str_length ) AllocatorInfo get_string_allocator( s32 str_length )
{ {
Arena* last = & StringArenas.back(); Arena* last = back(& StringArenas);
usize size_req = str_length + sizeof(String::Header) + sizeof(char*); usize size_req = str_length + sizeof(StringHeader) + sizeof(char*);
if ( last->TotalUsed + ssize(size_req) > last->TotalSize ) if ( last->TotalUsed + ssize(size_req) > last->TotalSize )
{ {
Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); Arena new_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena );
if ( ! StringArenas.append( new_arena ) ) if ( ! append( & StringArenas, new_arena ) )
GEN_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(); last = back(& StringArenas);
} }
return * last; return allocator_info(last);
} }
// Will either make or retrive a code string. // Will either make or retrive a code string.
@ -393,14 +396,14 @@ StringCached get_cached_string( StrC str )
s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len; s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len;
u64 key = crc32( str.Ptr, hash_length ); u64 key = crc32( str.Ptr, hash_length );
{ {
StringCached* result = StringCache.get( key ); StringCached* result = get(StringCache, key );
if ( result ) if ( result )
return * result; return * result;
} }
String result = String::make( get_string_allocator( str.Len ), str ); String result = string_make( get_string_allocator( str.Len ), str );
StringCache.set( key, result ); set<StringCached>(& StringCache, key, result );
return result; return result;
} }
@ -408,21 +411,21 @@ StringCached get_cached_string( StrC str )
// Used internally to retireve a Code object form the CodePool. // Used internally to retireve a Code object form the CodePool.
Code make_code() Code make_code()
{ {
Pool* allocator = & CodePools.back(); Pool* allocator = back( & CodePools);
if ( allocator->FreeList == nullptr ) if ( allocator->FreeList == nullptr )
{ {
Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) );
if ( code_pool.PhysicalStart == nullptr ) if ( code_pool.PhysicalStart == nullptr )
GEN_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 ) ) if ( ! append( & CodePools, code_pool ) )
GEN_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(); allocator = back( & CodePools);
} }
Code result { rcast( AST*, alloc( * allocator, sizeof(AST) )) }; Code result { rcast( AST*, alloc( allocator_info(allocator), sizeof(AST) )) };
mem_set( result.ast, 0, sizeof(AST) ); mem_set( result.ast, 0, sizeof(AST) );
// result->Type = ECode::Invalid; // result->Type = ECode::Invalid;

View File

@ -44,9 +44,9 @@ CodeComment def_comment ( StrC content );
CodeClass def_class( StrC name CodeClass def_class( StrC name
, Code body = NoCode , Code body = NoCode
, CodeType parent = NoCode, AccessSpec access = AccessSpec::Default , CodeType parent = NoCode, AccessSpec access = AccessSpec_Default
, CodeAttributes attributes = NoCode , CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None , ModuleFlag mflags = ModuleFlag_None
, CodeType* interfaces = nullptr, s32 num_interfaces = 0 ); , CodeType* interfaces = nullptr, s32 num_interfaces = 0 );
CodeConstructor def_constructor( CodeParam params = NoCode, Code initializer_list = NoCode, Code body = NoCode ); CodeConstructor def_constructor( CodeParam params = NoCode, Code initializer_list = NoCode, Code body = NoCode );
@ -56,9 +56,9 @@ CodeDefine def_define( StrC name, StrC content );
CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = NoCode ); CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = NoCode );
CodeEnum def_enum( StrC name CodeEnum def_enum( StrC name
, Code body = NoCode, CodeType type = NoCode , Code body = NoCode, CodeType type = NoCode
, EnumT specifier = EnumRegular, CodeAttributes attributes = NoCode , EnumT specifier = EnumDecl_Regular, CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None ); , ModuleFlag mflags = ModuleFlag_None );
CodeExec def_execution ( StrC content ); CodeExec def_execution ( StrC content );
CodeExtern def_extern_link( StrC name, Code body ); CodeExtern def_extern_link( StrC name, Code body );
@ -67,16 +67,16 @@ CodeFriend def_friend ( Code symbol );
CodeFn def_function( StrC name CodeFn def_function( StrC name
, CodeParam params = NoCode, CodeType ret_type = NoCode, Code body = NoCode , CodeParam params = NoCode, CodeType ret_type = NoCode, Code body = NoCode
, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode , CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None ); , ModuleFlag mflags = ModuleFlag_None );
CodeInclude def_include ( StrC content, bool foreign = false ); CodeInclude def_include ( StrC content, bool foreign = false );
CodeModule def_module ( StrC name, ModuleFlag mflags = ModuleFlag::None ); CodeModule def_module ( StrC name, ModuleFlag mflags = ModuleFlag_None );
CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None ); CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag_None );
CodeOperator def_operator( OperatorT op, StrC nspace CodeOperator def_operator( OperatorT op, StrC nspace
, CodeParam params = NoCode, CodeType ret_type = NoCode, Code body = NoCode , CodeParam params = NoCode, CodeType ret_type = NoCode, Code body = NoCode
, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode , CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None ); , ModuleFlag mflags = ModuleFlag_None );
CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode ); CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode );
@ -89,27 +89,27 @@ CodeSpecifiers def_specifier( SpecifierT specifier );
CodeStruct def_struct( StrC name CodeStruct def_struct( StrC name
, Code body = NoCode , Code body = NoCode
, CodeType parent = NoCode, AccessSpec access = AccessSpec::Default , CodeType parent = NoCode, AccessSpec access = AccessSpec_Default
, CodeAttributes attributes = NoCode , CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None , ModuleFlag mflags = ModuleFlag_None
, CodeType* interfaces = nullptr, s32 num_interfaces = 0 ); , CodeType* interfaces = nullptr, s32 num_interfaces = 0 );
CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag::None ); CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag_None );
CodeType def_type ( StrC name, Code arrayexpr = NoCode, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode ); CodeType def_type ( StrC name, Code arrayexpr = NoCode, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode );
CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag_None );
CodeUnion def_union( StrC name, Code body, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); CodeUnion def_union( StrC name, Code body, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag_None );
CodeUsing def_using( StrC name, CodeType type = NoCode CodeUsing def_using( StrC name, CodeType type = NoCode
, CodeAttributes attributess = NoCode , CodeAttributes attributess = NoCode
, ModuleFlag mflags = ModuleFlag::None ); , ModuleFlag mflags = ModuleFlag_None );
CodeUsing def_using_namespace( StrC name ); CodeUsing def_using_namespace( StrC name );
CodeVar def_variable( CodeType type, StrC name, Code value = NoCode CodeVar def_variable( CodeType type, StrC name, Code value = NoCode
, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode , CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None ); , ModuleFlag mflags = ModuleFlag_None );
// Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries. // Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries.
CodeBody def_body( CodeT type ); CodeBody def_body( CodeT type );

View File

@ -15,7 +15,7 @@ CodeClass parse_class( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
push_scope(); push_scope();
@ -31,7 +31,7 @@ CodeConstructor parse_constructor( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
// TODO(Ed): Constructors can have prefix attributes // TODO(Ed): Constructors can have prefix attributes
@ -61,7 +61,7 @@ CodeConstructor parse_constructor( StrC def )
default : default :
log_failure( "Invalid specifier %s for variable\n%s", ESpecifier::to_str( spec ), Context.to_string() ); log_failure( "Invalid specifier %s for variable\n%s", ESpecifier::to_str( spec ), Context.to_string() );
Context.pop(); Context.pop();
return CodeInvalid; return InvalidCode;
} }
// Every specifier after would be considered part of the type type signature // Every specifier after would be considered part of the type type signature
@ -91,7 +91,7 @@ CodeDestructor parse_destructor( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
// TODO(Ed): Destructors can have prefix attributes // TODO(Ed): Destructors can have prefix attributes
// TODO(Ed): Destructors can have virtual // TODO(Ed): Destructors can have virtual
@ -110,7 +110,7 @@ CodeEnum parse_enum( StrC def )
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
{ {
Context.pop(); Context.pop();
return CodeInvalid; return InvalidCode;
} }
Context.Tokens = toks; Context.Tokens = toks;
@ -124,7 +124,7 @@ CodeBody parse_export_body( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_export_body(); return parse_export_body();
@ -137,7 +137,7 @@ CodeExtern parse_extern_link( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_extern_link(); return parse_extern_link();
@ -150,7 +150,7 @@ CodeFriend parse_friend( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_friend(); return parse_friend();
@ -163,7 +163,7 @@ CodeFn parse_function( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return (CodeFn) parse_function(); return (CodeFn) parse_function();
@ -176,7 +176,7 @@ CodeBody parse_global_body( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
push_scope(); push_scope();
@ -192,7 +192,7 @@ CodeNS parse_namespace( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_namespace(); return parse_namespace();
@ -205,7 +205,7 @@ CodeOperator parse_operator( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return (CodeOperator) parse_operator(); return (CodeOperator) parse_operator();
@ -218,7 +218,7 @@ CodeOpCast parse_operator_cast( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_operator_cast(); return parse_operator_cast();
@ -231,7 +231,7 @@ CodeStruct parse_struct( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
push_scope(); push_scope();
@ -247,7 +247,7 @@ CodeTemplate parse_template( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_template(); return parse_template();
@ -260,7 +260,7 @@ CodeType parse_type( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_type(); return parse_type();
@ -273,7 +273,7 @@ CodeTypedef parse_typedef( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_typedef(); return parse_typedef();
@ -286,7 +286,7 @@ CodeUnion parse_union( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_union(); return parse_union();
@ -299,7 +299,7 @@ CodeUsing parse_using( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_using(); return parse_using();
@ -312,7 +312,7 @@ CodeVar parse_variable( StrC def )
TokArray toks = lex( def ); TokArray toks = lex( def );
if ( toks.Arr == nullptr ) if ( toks.Arr == nullptr )
return CodeInvalid; return InvalidCode;
Context.Tokens = toks; Context.Tokens = toks;
return parse_variable(); return parse_variable();

View File

@ -6,7 +6,7 @@
ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
{ {
char const* buf_begin = buf; char const* buf_begin = buf;
ssize remaining = buf_size; ssize remaining = buf_size;
local_persist local_persist
Arena tok_map_arena; Arena tok_map_arena;
@ -16,8 +16,8 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
local_persist local_persist
char tok_map_mem[ TokenFmt_TokenMap_MemSize ]; char tok_map_mem[ TokenFmt_TokenMap_MemSize ];
tok_map_arena = Arena::init_from_memory( tok_map_mem, sizeof(tok_map_mem) ); tok_map_arena = arena_init_from_memory( tok_map_mem, sizeof(tok_map_mem) );
tok_map = HashTable<StrC>::init( tok_map_arena ); tok_map = hashtable_init<StrC>( allocator_info(& tok_map_arena) );
s32 left = num_tokens - 1; s32 left = num_tokens - 1;
@ -27,8 +27,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
StrC value = va_arg( va, StrC ); StrC value = va_arg( va, StrC );
u32 key = crc32( token, str_len(token) ); u32 key = crc32( token, str_len(token) );
set(& tok_map, key, value );
tok_map.set( key, value );
} }
} }
@ -64,7 +63,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
char const* token = fmt + 1; char const* token = fmt + 1;
u32 key = crc32( token, tok_len ); u32 key = crc32( token, tok_len );
StrC* value = tok_map.get( key ); StrC* value = get(tok_map, key );
if ( value ) if ( value )
{ {
@ -94,8 +93,8 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
} }
} }
tok_map.clear(); clear(tok_map);
tok_map_arena.free(); free(& tok_map_arena);
ssize result = buf_size - remaining; ssize result = buf_size - remaining;
@ -107,7 +106,7 @@ Code untyped_str( StrC content )
if ( content.Len == 0 ) if ( content.Len == 0 )
{ {
log_failure( "untyped_str: empty string" ); log_failure( "untyped_str: empty string" );
return CodeInvalid; return InvalidCode;
} }
Code Code
@ -119,7 +118,7 @@ Code untyped_str( StrC content )
if ( result->Name == nullptr ) if ( result->Name == nullptr )
{ {
log_failure( "untyped_str: could not cache string" ); log_failure( "untyped_str: could not cache string" );
return CodeInvalid; return InvalidCode;
} }
return result; return result;
@ -130,7 +129,7 @@ Code untyped_fmt( char const* fmt, ...)
if ( fmt == nullptr ) if ( fmt == nullptr )
{ {
log_failure( "untyped_fmt: null format string" ); log_failure( "untyped_fmt: null format string" );
return CodeInvalid; return InvalidCode;
} }
local_persist thread_local local_persist thread_local
@ -150,7 +149,7 @@ Code untyped_fmt( char const* fmt, ...)
if ( result->Name == nullptr ) if ( result->Name == nullptr )
{ {
log_failure( "untyped_fmt: could not cache string" ); log_failure( "untyped_fmt: could not cache string" );
return CodeInvalid; return InvalidCode;
} }
return result; return result;
@ -161,7 +160,7 @@ Code untyped_token_fmt( s32 num_tokens, ... )
if ( num_tokens == 0 ) if ( num_tokens == 0 )
{ {
log_failure( "untyped_token_fmt: zero tokens" ); log_failure( "untyped_token_fmt: zero tokens" );
return CodeInvalid; return InvalidCode;
} }
local_persist thread_local local_persist thread_local
@ -181,7 +180,7 @@ Code untyped_token_fmt( s32 num_tokens, ... )
if ( result->Name == nullptr ) if ( result->Name == nullptr )
{ {
log_failure( "untyped_fmt: could not cache string" ); log_failure( "untyped_fmt: could not cache string" );
return CodeInvalid; return InvalidCode;
} }
return result; return result;

File diff suppressed because it is too large Load Diff

View File

@ -89,11 +89,11 @@ struct Token
String to_string() String to_string()
{ {
String result = String::make_reserve( GlobalAllocator, kilobytes(4) ); String result = string_make_reserve( GlobalAllocator, kilobytes(4) );
StrC type_str = ETokType::to_str( Type ); StrC type_str = ETokType::to_str( Type );
result.append_fmt( "Line: %d Column: %d, Type: %.*s Content: %.*s" append_fmt( & result, "Line: %d Column: %d, Type: %.*s Content: %.*s"
, Line, Column , Line, Column
, type_str.Len, type_str.Ptr , type_str.Len, type_str.Ptr
, Length, Text , Length, Text
@ -222,7 +222,7 @@ s32 lex_preprocessor_directive(
, Token& token ) , Token& token )
{ {
char const* hash = scanner; char const* hash = scanner;
Tokens.append( { hash, 1, TokType::Preprocess_Hash, line, column, TF_Preprocess } ); append( & Tokens, { hash, 1, TokType::Preprocess_Hash, line, column, TF_Preprocess } );
move_forward(); move_forward();
SkipWhitespace(); SkipWhitespace();
@ -298,14 +298,14 @@ s32 lex_preprocessor_directive(
token.Length = token.Length + token.Text - hash; token.Length = token.Length + token.Text - hash;
token.Text = hash; token.Text = hash;
Tokens.append( token ); append( & Tokens, token );
return Lex_Continue; // Skip found token, its all handled here. return Lex_Continue; // Skip found token, its all handled here.
} }
if ( token.Type == TokType::Preprocess_Else || token.Type == TokType::Preprocess_EndIf ) if ( token.Type == TokType::Preprocess_Else || token.Type == TokType::Preprocess_EndIf )
{ {
token.Flags |= TF_Preprocess_Cond; token.Flags |= TF_Preprocess_Cond;
Tokens.append( token ); append( & Tokens, token );
end_line(); end_line();
return Lex_Continue; return Lex_Continue;
} }
@ -314,7 +314,7 @@ s32 lex_preprocessor_directive(
token.Flags |= TF_Preprocess_Cond; token.Flags |= TF_Preprocess_Cond;
} }
Tokens.append( token ); append( & Tokens, token );
SkipWhitespace(); SkipWhitespace();
@ -338,10 +338,10 @@ s32 lex_preprocessor_directive(
name.Length++; name.Length++;
} }
Tokens.append( name ); append( & Tokens, name );
u64 key = crc32( name.Text, name.Length ); u64 key = crc32( name.Text, name.Length );
defines.set( key, name ); set<StrC>(& defines, key, name );
} }
Token preprocess_content = { scanner, 0, TokType::Preprocess_Content, line, column, TF_Preprocess }; Token preprocess_content = { scanner, 0, TokType::Preprocess_Content, line, column, TF_Preprocess };
@ -352,7 +352,7 @@ s32 lex_preprocessor_directive(
if ( current != '"' && current != '<' ) if ( current != '"' && current != '<' )
{ {
String directive_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 80, left + preprocess_content.Length ), token.Text ); String directive_str = string_fmt_buf( GlobalAllocator, "%.*s", min( 80, left + preprocess_content.Length ), token.Text );
log_failure( "gen::Parser::lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s" log_failure( "gen::Parser::lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s"
, current , current
@ -384,7 +384,7 @@ s32 lex_preprocessor_directive(
move_forward(); move_forward();
} }
Tokens.append( preprocess_content ); append( & Tokens, preprocess_content );
return Lex_Continue; // Skip found token, its all handled here. return Lex_Continue; // Skip found token, its all handled here.
} }
@ -419,8 +419,8 @@ s32 lex_preprocessor_directive(
} }
else else
{ {
String directive_str = String::make_length( GlobalAllocator, token.Text, token.Length ); String directive_str = string_make_length( GlobalAllocator, token.Text, token.Length );
String content_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 400, left + preprocess_content.Length ), preprocess_content.Text ); String content_str = string_fmt_buf( GlobalAllocator, "%.*s", min( 400, left + preprocess_content.Length ), preprocess_content.Text );
log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)"
" in preprocessor directive '%s' (%d, %d)\n%s" " in preprocessor directive '%s' (%d, %d)\n%s"
@ -446,7 +446,7 @@ s32 lex_preprocessor_directive(
preprocess_content.Length++; preprocess_content.Length++;
} }
Tokens.append( preprocess_content ); append( & Tokens, preprocess_content );
return Lex_Continue; // Skip found token, its all handled here. return Lex_Continue; // Skip found token, its all handled here.
} }
@ -461,7 +461,7 @@ void lex_found_token( StrC& content
{ {
if ( token.Type != TokType::Invalid ) if ( token.Type != TokType::Invalid )
{ {
Tokens.append( token ); append( & Tokens, token );
return; return;
} }
@ -488,7 +488,7 @@ void lex_found_token( StrC& content
} }
token.Type = type; token.Type = type;
Tokens.append( token ); append( & Tokens, token );
return; return;
} }
@ -498,7 +498,7 @@ void lex_found_token( StrC& content
{ {
token.Type = type; token.Type = type;
token.Flags |= TF_Specifier; token.Flags |= TF_Specifier;
Tokens.append( token ); append( & Tokens, token );
return; return;
} }
@ -506,7 +506,7 @@ void lex_found_token( StrC& content
if ( type != TokType::Invalid ) if ( type != TokType::Invalid )
{ {
token.Type = type; token.Type = type;
Tokens.append( token ); append( & Tokens, token );
return; return;
} }
@ -516,7 +516,7 @@ void lex_found_token( StrC& content
else else
key = crc32( token.Text, token.Length ); key = crc32( token.Text, token.Length );
StrC* define = defines.get( key ); StrC* define = get(defines, key );
if ( define ) if ( define )
{ {
token.Type = TokType::Preprocess_Macro; token.Type = TokType::Preprocess_Macro;
@ -558,7 +558,7 @@ void lex_found_token( StrC& content
token.Type = TokType::Identifier; token.Type = TokType::Identifier;
} }
Tokens.append( token ); append( & Tokens, token );
} }
@ -579,14 +579,14 @@ TokArray lex( StrC content )
if ( left <= 0 ) if ( left <= 0 )
{ {
log_failure( "gen::lex: no tokens found (only whitespace provided)" ); log_failure( "gen::lex: no tokens found (only whitespace provided)" );
return { { nullptr }, 0 }; return { {}, 0 };
} }
for ( StringCached entry : PreprocessorDefines ) foreach( StringCached, entry, PreprocessorDefines )
{ {
s32 length = 0; s32 length = 0;
char const* scanner = entry.Data; char const* scanner = entry.Data;
while ( entry.length() > length && (char_is_alphanumeric( *scanner ) || *scanner == '_') ) while ( GEN_NS length(entry) > length && (char_is_alphanumeric( *scanner ) || *scanner == '_') )
{ {
scanner++; scanner++;
length ++; length ++;
@ -597,10 +597,10 @@ TokArray lex( StrC content )
} }
u64 key = crc32( entry.Data, length ); u64 key = crc32( entry.Data, length );
defines.set( key, entry ); set<StrC>(& defines, key, entry );
} }
Tokens.clear(); clear(Tokens);
while (left ) while (left )
{ {
@ -630,7 +630,7 @@ TokArray lex( StrC content )
token.Type = TokType::NewLine; token.Type = TokType::NewLine;
token.Length++; token.Length++;
Tokens.append( token ); append( & Tokens, token );
continue; continue;
} }
} }
@ -652,7 +652,7 @@ TokArray lex( StrC content )
continue; continue;
case Lex_ReturnNull: case Lex_ReturnNull:
return { { nullptr }, 0 }; return { {}, 0 };
} }
} }
case '.': case '.':
@ -678,7 +678,7 @@ TokArray lex( StrC content )
} }
else else
{ {
String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) ); String context_str = string_fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) );
log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", current, line, column, context_str ); log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", current, line, column, context_str );
} }
@ -1099,7 +1099,7 @@ TokArray lex( StrC content )
move_forward(); move_forward();
token.Length++; token.Length++;
} }
Tokens.append( token ); append( & Tokens, token );
continue; continue;
} }
else if ( current == '*' ) else if ( current == '*' )
@ -1135,7 +1135,7 @@ TokArray lex( StrC content )
move_forward(); move_forward();
token.Length++; token.Length++;
} }
Tokens.append( token ); append( & Tokens, token );
// end_line(); // end_line();
continue; continue;
} }
@ -1228,9 +1228,9 @@ TokArray lex( StrC content )
} }
else else
{ {
s32 start = max( 0, Tokens.num() - 100 ); s32 start = max( 0, num(Tokens) - 100 );
log_fmt("\n%d\n", start); log_fmt("\n%d\n", start);
for ( s32 idx = start; idx < Tokens.num(); idx++ ) for ( s32 idx = start; idx < num(Tokens); idx++ )
{ {
log_fmt( "Token %d Type: %s : %.*s\n" log_fmt( "Token %d Type: %s : %.*s\n"
, idx , idx
@ -1239,7 +1239,7 @@ TokArray lex( StrC content )
); );
} }
String context_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 100, left ), scanner ); String context_str = string_fmt_buf( GlobalAllocator, "%.*s", min( 100, left ), scanner );
log_failure( "Failed to lex token '%c' (%d, %d)\n%s", current, line, column, context_str ); log_failure( "Failed to lex token '%c' (%d, %d)\n%s", current, line, column, context_str );
// Skip to next whitespace since we can't know if anything else is valid until then. // Skip to next whitespace since we can't know if anything else is valid until then.
@ -1253,13 +1253,13 @@ TokArray lex( StrC content )
lex_found_token( content, left, scanner, line, column, defines, token ); lex_found_token( content, left, scanner, line, column, defines, token );
} }
if ( Tokens.num() == 0 ) if ( num(Tokens) == 0 )
{ {
log_failure( "Failed to lex any tokens" ); log_failure( "Failed to lex any tokens" );
return { { nullptr }, 0 }; return { {}, 0 };
} }
defines.clear(); clear(defines);
// defines_map_arena.free(); // defines_map_arena.free();
return { Tokens, 0 }; return { Tokens, 0 };
} }

File diff suppressed because it is too large Load Diff

View File

@ -13,63 +13,71 @@ using LogFailType = ssize(*)(char const*, ...);
#define log_failure GEN_FATAL #define log_failure GEN_FATAL
#endif #endif
enum class AccessSpec : u32 enum AccessSpec enum_underlying(u32)
{ {
Default, AccessSpec_Default,
Private, AccessSpec_Private,
Protected, AccessSpec_Protected,
Public, AccessSpec_Public,
Num_AccessSpec, AccessSpec_Num_AccessSpec,
Invalid, AccessSpec_Invalid,
AccessSpec_SizeDef = GEN_U32_MAX,
}; };
static_assert( size_of(AccessSpec) == size_of(u32), "AccessSpec not u32 size" );
inline inline
char const* to_str( AccessSpec type ) char const* to_str( AccessSpec type )
{ {
local_persist local_persist
char const* lookup[ (u32)AccessSpec::Num_AccessSpec ] = { char const* lookup[ (u32)AccessSpec_Num_AccessSpec ] = {
"", "",
"private", "private",
"protected", "protected",
"public", "public",
}; };
if ( type > AccessSpec::Public ) if ( type > AccessSpec_Public )
return "Invalid"; return "Invalid";
return lookup[ (u32)type ]; return lookup[ (u32)type ];
} }
enum CodeFlag enum_underlying(u32)
enum CodeFlag : u32
{ {
None = 0, CodeFlag_None = 0,
FunctionType = bit(0), CodeFlag_FunctionType = bit(0),
ParamPack = bit(1), CodeFlag_ParamPack = bit(1),
Module_Export = bit(2), CodeFlag_Module_Export = bit(2),
Module_Import = bit(3), CodeFlag_Module_Import = bit(3),
CodeFlag_SizeDef = GEN_U32_MAX,
}; };
static_assert( size_of(CodeFlag) == size_of(u32), "CodeFlag not u32 size" );
// Used to indicate if enum definitoin is an enum class or regular enum. // Used to indicate if enum definitoin is an enum class or regular enum.
enum class EnumT : u8 enum EnumDecl enum_underlying(u8)
{ {
Regular, EnumDecl_Regular,
Class EnumDecl_Class,
EnumT_SizeDef = GEN_U8_MAX,
}; };
typedef u8 EnumT;
constexpr EnumT EnumClass = EnumT::Class; enum ModuleFlag enum_underlying(u32)
constexpr EnumT EnumRegular = EnumT::Regular;
enum class ModuleFlag : u32
{ {
None = 0, ModuleFlag_None = 0,
Export = bit(0), ModuleFlag_Export = bit(0),
Import = bit(1), ModuleFlag_Import = bit(1),
Num_ModuleFlags, Num_ModuleFlags,
Invalid, ModuleFlag_Invalid,
ModuleFlag_SizeDef = GEN_U32_MAX,
}; };
static_assert( size_of(ModuleFlag) == size_of(u32), "ModuleFlag not u32 size" );
inline inline
StrC to_str( ModuleFlag flag ) StrC to_str( ModuleFlag flag )
@ -81,7 +89,7 @@ StrC to_str( ModuleFlag flag )
{ sizeof("import"), "import" }, { sizeof("import"), "import" },
}; };
if ( flag > ModuleFlag::Import ) if ( flag > ModuleFlag_Import )
return { sizeof("invalid"), "invalid" }; return { sizeof("invalid"), "invalid" };
return lookup[ (u32)flag ]; return lookup[ (u32)flag ];
@ -93,15 +101,13 @@ ModuleFlag operator|( ModuleFlag A, ModuleFlag B)
return (ModuleFlag)( (u32)A | (u32)B ); return (ModuleFlag)( (u32)A | (u32)B );
} }
enum class EPreprocessCond : u32 enum EPreprocessCond enum_underlying(u32)
{ {
If, PreprocessCond_If,
IfDef, PreprocessCond_IfDef,
IfNotDef, PreprocessCond_IfNotDef,
ElIf PreprocessCond_ElIf,
};
constexpr EPreprocessCond PreprocessCond_If = EPreprocessCond::If; EPreprocessCond_SizeDef = GEN_U32_MAX,
constexpr EPreprocessCond PreprocessCond_IfDef = EPreprocessCond::IfDef; };
constexpr EPreprocessCond PreprocessCond_IfNotDef = EPreprocessCond::IfNotDef; static_assert( size_of(EPreprocessCond) == size_of(u32), "EPreprocessCond not u32 size" );
constexpr EPreprocessCond PreprocessCond_ElIf = EPreprocessCond::ElIf;

View File

@ -1,5 +1,6 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES #ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once # pragma once
# include "platform.hpp"
# include "macros.hpp" # include "macros.hpp"
#endif #endif
@ -122,13 +123,21 @@ typedef s8 b8;
typedef s16 b16; typedef s16 b16;
typedef s32 b32; typedef s32 b32;
using mem_ptr = void*; typedef void* mem_ptr;
using mem_ptr_const = void const*; typedef void const* mem_ptr_const ;
#if ! GEN_COMPILER_C
template<typename Type> uptr to_uptr( Type* ptr ) { return (uptr)ptr; } template<typename Type> uptr to_uptr( Type* ptr ) { return (uptr)ptr; }
template<typename Type> sptr to_sptr( Type* ptr ) { return (sptr)ptr; } template<typename Type> sptr to_sptr( Type* ptr ) { return (sptr)ptr; }
template<typename Type> mem_ptr to_mem_ptr ( Type ptr ) { return (mem_ptr) ptr; } template<typename Type> mem_ptr to_mem_ptr ( Type ptr ) { return (mem_ptr) ptr; }
template<typename Type> mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem_ptr_const)ptr; } template<typename Type> mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem_ptr_const)ptr; }
#else
#define to_utpr( ptr ) ((uptr)(ptr))
#define to_stpr( ptr ) ((sptr)(ptr))
#define to_mem_ptr( ptr) ((mem_ptr)ptr)
#define to_mem_ptr_const( ptr) ((mem_ptr)ptr)
#endif
#pragma endregion Basic Types #pragma endregion Basic Types

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
{ \ { \
if ( ! ( cond ) ) \ if ( ! ( cond ) ) \
{ \ { \
assert_handler( #cond, __FILE__, scast( s64, __LINE__ ), msg, ##__VA_ARGS__ ); \ assert_handler( #cond, __FILE__, scast( s64, __LINE__ ), msg, ##__VA_ARGS__ ); \
GEN_DEBUG_TRAP(); \ GEN_DEBUG_TRAP(); \
} \ } \
} while ( 0 ) } while ( 0 )

View File

@ -505,7 +505,7 @@ b8 file_stream_new( FileInfo* file, AllocatorInfo allocator )
d->allocator = allocator; d->allocator = allocator;
d->flags = EFileStream_CLONE_WRITABLE; d->flags = EFileStream_CLONE_WRITABLE;
d->cap = 0; d->cap = 0;
d->buf = Array<u8>::init( allocator ); d->buf = array_init<u8>( allocator );
if ( ! d->buf ) if ( ! d->buf )
return false; return false;
@ -531,7 +531,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize
d->flags = flags; d->flags = flags;
if ( d->flags & EFileStream_CLONE_WRITABLE ) if ( d->flags & EFileStream_CLONE_WRITABLE )
{ {
Array<u8> arr = Array<u8>::init_reserve( allocator, size ); Array<u8> arr = array_init_reserve<u8>( allocator, size );
d->buf = arr; d->buf = arr;
if ( ! d->buf ) if ( ! d->buf )
@ -540,7 +540,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize
mem_copy( d->buf, buffer, size ); mem_copy( d->buf, buffer, size );
d->cap = size; d->cap = size;
arr.get_header()->Num = size; get_header(arr)->Num = size;
} }
else else
{ {
@ -610,9 +610,9 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write )
{ {
Array<u8> arr = { d->buf }; Array<u8> arr = { d->buf };
if ( arr.get_header()->Capacity < usize(new_cap) ) if ( get_header(arr)->Capacity < usize(new_cap) )
{ {
if ( ! arr.grow( ( s64 )( new_cap ) ) ) if ( ! grow( & arr, ( s64 )( new_cap ) ) )
return false; return false;
d->buf = arr; d->buf = arr;
} }
@ -626,7 +626,7 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write )
mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen ); mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen );
d->cap = new_cap; d->cap = new_cap;
arr.get_header()->Capacity = new_cap; get_header(arr)->Capacity = new_cap;
} }
else else
{ {
@ -647,7 +647,7 @@ GEN_FILE_CLOSE_PROC( _memory_file_close )
if ( d->flags & EFileStream_CLONE_WRITABLE ) if ( d->flags & EFileStream_CLONE_WRITABLE )
{ {
Array<u8> arr = { d->buf }; Array<u8> arr = { d->buf };
arr.free(); free(& arr);
} }
free( allocator, d ); free( allocator, d );

View File

@ -23,17 +23,39 @@
#define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) )
#endif #endif
#ifndef ccast
#define ccast( type, value ) ( const_cast< type >( (value) ) ) #if ! GEN_C_COMPILER
#endif # ifndef cast
#ifndef pcast # define cast( type, value ) (tmpl_cast<type>( value ))
#define pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) ) # endif
#endif # ifndef ccast
#ifndef rcast # define ccast( type, value ) ( const_cast< type >( (value) ) )
#define rcast( type, value ) reinterpret_cast< type >( value ) # endif
#endif # ifndef pcast
#ifndef scast # define pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) )
#define scast( type, value ) static_cast< type >( value ) # endif
# ifndef rcast
# define rcast( type, value ) reinterpret_cast< type >( value )
# endif
# ifndef scast
# define scast( type, value ) static_cast< type >( value )
# endif
#else
# ifndef cast
# define cast( type, value ) ( (type)(value) )
# endif
# ifndef ccast
# define ccast( type, value ) ( (type)(value) )
# endif
# ifndef pcast
# define pcast( type, value ) ( * (type*)(value) )
# endif
# ifndef rcast
# define rcast( type, value ) ( (type)(value) )
# endif
# ifndef scast
# define scast( type, value ) ( (type)(value) )
# endif
#endif #endif
#ifndef stringize #ifndef stringize
@ -123,20 +145,20 @@
#define min( a, b ) ( (a < b) ? (a) : (b) ) #define min( a, b ) ( (a < b) ? (a) : (b) )
#endif #endif
#if defined( _MSC_VER ) || defined( GEN_COMPILER_TINYC ) #if GEN_COMPILER_MSVC || GEN_COMPILER_TINYC
# define offset_of( Type, element ) ( ( GEN_NS( ssize ) ) & ( ( ( Type* )0 )->element ) ) # define offset_of( Type, element ) ( ( GEN_NS( ssize ) ) & ( ( ( Type* )0 )->element ) )
#else #else
# define offset_of( Type, element ) __builtin_offsetof( Type, element ) # define offset_of( Type, element ) __builtin_offsetof( Type, element )
#endif #endif
#ifndef forceinline #ifndef forceinline
# ifdef GEN_COMPILER_MSVC # if GEN_COMPILER_MSVC
# define forceinline __forceinline # define forceinline __forceinline
# define neverinline __declspec( noinline ) # define neverinline __declspec( noinline )
# elif defined(GEN_COMPILER_GCC) # elif GEN_COMPILER_GCC
# define forceinline inline __attribute__((__always_inline__)) # define forceinline inline __attribute__((__always_inline__))
# define neverinline __attribute__( ( __noinline__ ) ) # define neverinline __attribute__( ( __noinline__ ) )
# elif defined(GEN_COMPILER_CLANG) # elif GEN_COMPILER_CLANG
# if __has_attribute(__always_inline__) # if __has_attribute(__always_inline__)
# define forceinline inline __attribute__((__always_inline__)) # define forceinline inline __attribute__((__always_inline__))
# define neverinline __attribute__( ( __noinline__ ) ) # define neverinline __attribute__( ( __noinline__ ) )
@ -151,11 +173,11 @@
#endif #endif
#ifndef neverinline #ifndef neverinline
# ifdef GEN_COMPILER_MSVC # if GEN_COMPILER_MSVC
# define neverinline __declspec( noinline ) # define neverinline __declspec( noinline )
# elif defined(GEN_COMPILER_GCC) # elif GEN_COMPILER_GCC
# define neverinline __attribute__( ( __noinline__ ) ) # define neverinline __attribute__( ( __noinline__ ) )
# elif defined(GEN_COMPILER_CLANG) # elif GEN_COMPILER_CLANG
# if __has_attribute(__always_inline__) # if __has_attribute(__always_inline__)
# define neverinline __attribute__( ( __noinline__ ) ) # define neverinline __attribute__( ( __noinline__ ) )
# else # else
@ -166,4 +188,50 @@
# endif # endif
#endif #endif
#if !defined(GEN_SUPPORT_CPP_REFERENCES) && (GEN_COMPILER_C || __STDC_VERSION__ < 202311L)
# undef GEN_SUPPORT_CPP_REFERENCES
# define GEN_SUPPORT_CPP_REFERENCES 0
#endif
#if !defined(GEN_SUPPORT_CPP_MEMBER_FEATURES) && (GEN_COMPILER_C || __STDC_VERSION__ < 202311L)
# undef GEN_SUPPORT_CPP_MEMBER_FEATURES
# define GEN_SUPPORT_CPP_MEMBER_FEATURES 0
#endif
#if !defined(typeof) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L)
# if ! GEN_COMPILER_C
# define typeof decltype
# elif defined(_MSC_VER)
# define typeof(x) __typeof(x)
# elif defined(__GNUC__) || defined(__clang__)
# define typeof(x) __typeof__(x)
# else
# error "Compiler not supported"
# endif
#endif
// This is intended to only really be used internally or with the C-library variant
// C++ users can just use the for-range directly.
#if GEN_COMPILER_C
# define foreach(Type, entry_id, iterable) for ( Type entry_id = begin(iterable); entry_id != end(iterable); entry_id = next(iterable, entry_id) )
#else
# define foreach(Type, entry_id, iterable) for ( Type entry_id : iterable )
#endif
#if GEN_COMPILER_C
# if __STDC_VERSION__ >= 202311L
# define enum_underlying(type) : type
# else
# define enum_underlying(type)
# endif
#else
# define enum_underlying(type) : type
#endif
#if GEN_COMPILER_C
# ifndef nullptr
# define nullptr NULL
# endif
#endif
#pragma endregion Macros #pragma endregion Macros

View File

@ -334,7 +334,7 @@ ssize virtual_memory_page_size( ssize* alignment_out )
#pragma endregion VirtualMemory #pragma endregion VirtualMemory
void* Arena::allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) void* arena_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags )
{ {
Arena* arena = rcast(Arena*, allocator_data); Arena* arena = rcast(Arena*, allocator_data);
void* ptr = NULL; void* ptr = NULL;
@ -384,7 +384,7 @@ void* Arena::allocator_proc( void* allocator_data, AllocType type, ssize size, s
return ptr; return ptr;
} }
void* Pool::allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) void* pool_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags )
{ {
Pool* pool = rcast( Pool*, allocator_data); Pool* pool = rcast( Pool*, allocator_data);
void* ptr = NULL; void* ptr = NULL;
@ -457,7 +457,7 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, ssize size, ss
return ptr; return ptr;
} }
Pool Pool::init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align ) Pool pool_init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align )
{ {
Pool pool = {}; Pool pool = {};
@ -495,16 +495,16 @@ Pool Pool::init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size
return pool; return pool;
} }
void Pool::clear() void clear(Pool& pool)
{ {
ssize actual_block_size, block_index; ssize actual_block_size, block_index;
void* curr; void* curr;
uptr* end; uptr* end;
actual_block_size = BlockSize + BlockAlign; actual_block_size = pool.BlockSize + pool.BlockAlign;
curr = PhysicalStart; curr = pool.PhysicalStart;
for ( block_index = 0; block_index < NumBlocks - 1; block_index++ ) for ( block_index = 0; block_index < pool.NumBlocks - 1; block_index++ )
{ {
uptr* next = ( uptr* ) curr; uptr* next = ( uptr* ) curr;
*next = ( uptr ) curr + actual_block_size; *next = ( uptr ) curr + actual_block_size;
@ -514,7 +514,7 @@ void Pool::clear()
end = ( uptr* ) curr; end = ( uptr* ) curr;
*end = ( uptr ) NULL; *end = ( uptr ) NULL;
FreeList = PhysicalStart; pool.FreeList = pool.PhysicalStart;
} }
#pragma endregion Memory #pragma endregion Memory

View File

@ -5,7 +5,7 @@
#pragma region Memory #pragma region Memory
#define kilobytes( x ) ( ( x ) * ( s64 )( 1024 ) ) #define kilobytes( x ) ( ( x ) * ( s64 )( 1024 ) )
#define megabytes( x ) ( kilobytes( x ) * ( s64 )( 1024 ) ) #define megabytes( x ) ( kilobytes( x ) * ( s64 )( 1024 ) )
#define gigabytes( x ) ( megabytes( x ) * ( s64 )( 1024 ) ) #define gigabytes( x ) ( megabytes( x ) * ( s64 )( 1024 ) )
#define terabytes( x ) ( gigabytes( x ) * ( s64 )( 1024 ) ) #define terabytes( x ) ( gigabytes( x ) * ( s64 )( 1024 ) )
@ -62,24 +62,23 @@ void zero_size( void* ptr, ssize size );
//! Clears up an array. //! Clears up an array.
#define zero_array( a, count ) zero_size( ( a ), size_of( *( a ) ) * count ) #define zero_array( a, count ) zero_size( ( a ), size_of( *( a ) ) * count )
enum AllocType : u8 enum AllocType_Def //enum_underlying(u8)
{ {
EAllocation_ALLOC, EAllocation_ALLOC,
EAllocation_FREE, EAllocation_FREE,
EAllocation_FREE_ALL, EAllocation_FREE_ALL,
EAllocation_RESIZE, EAllocation_RESIZE,
}; };
typedef enum AllocType_Def AllocType;
using AllocatorProc = void* ( void* allocator_data, AllocType type typedef void*(AllocatorProc)( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
, ssize size, ssize alignment
, void* old_memory, ssize old_size
, u64 flags );
struct AllocatorInfo struct AllocatorInfo_Def
{ {
AllocatorProc* Proc; AllocatorProc* Proc;
void* Data; void* Data;
}; };
typedef struct AllocatorInfo_Def AllocatorInfo;
enum AllocFlag enum AllocFlag
{ {
@ -135,7 +134,7 @@ void* default_resize_align( AllocatorInfo a, void* ptr, ssize old_size, ssize ne
void* heap_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); void* heap_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
//! The heap allocator backed by operating system's memory manager. //! The heap allocator backed by operating system's memory manager.
constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; } constexpr AllocatorInfo heap( void ) { AllocatorInfo allocator = { heap_allocator_proc, nullptr }; return allocator; }
//! Helper to allocate memory using heap allocator. //! Helper to allocate memory using heap allocator.
#define malloc( sz ) alloc( heap(), sz ) #define malloc( sz ) alloc( heap(), sz )
@ -170,121 +169,206 @@ b32 gen_vm_purge( VirtualMemory vm );
//! Retrieve VM's page size and alignment. //! Retrieve VM's page size and alignment.
ssize gen_virtual_memory_page_size( ssize* alignment_out ); ssize gen_virtual_memory_page_size( ssize* alignment_out );
struct Arena #pragma region Arena
{ struct Arena;
static
void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
static AllocatorInfo allocator_info( Arena* arena );
Arena init_from_memory( void* start, ssize size )
{
return
{
{ nullptr, nullptr },
start,
size,
0,
0
};
}
static // Remove static keyword and rename allocator_proc
Arena init_from_allocator( AllocatorInfo backing, ssize size ) void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags);
{
Arena result =
{
backing,
alloc( backing, size),
size,
0,
0
};
return result;
}
static // Add these declarations after the Arena struct
Arena init_sub( Arena& parent, ssize size ) Arena arena_init_from_allocator(AllocatorInfo backing, ssize size);
{ Arena arena_init_from_memory ( void* start, ssize size );
return init_from_allocator( parent.Backing, size );
}
ssize alignment_of( ssize alignment ) Arena init_sub (Arena* parent, ssize size);
{ ssize alignment_of (Arena* arena, ssize alignment);
ssize alignment_offset, result_pointer, mask; void free (Arena* arena);
GEN_ASSERT( is_power_of_two( alignment ) ); ssize size_remaining(Arena* arena, ssize alignment);
alignment_offset = 0;
result_pointer = (ssize) PhysicalStart + TotalUsed;
mask = alignment - 1;
if ( result_pointer & mask )
alignment_offset = alignment - ( result_pointer & mask );
return alignment_offset;
}
// This id is defined by Unreal for asserts // This id is defined by Unreal for asserts
#pragma push_macro("check") #pragma push_macro("check")
#undef check #undef check
void check() void check(Arena* arena);
{
GEN_ASSERT( TempCount == 0 );
}
#pragma pop_macro("check") #pragma pop_macro("check")
void free() struct Arena
{ {
if ( Backing.Proc )
{
gen::free( Backing, PhysicalStart );
PhysicalStart = nullptr;
}
}
ssize size_remaining( ssize alignment )
{
ssize result = TotalSize - ( TotalUsed + alignment_of( alignment ) );
return result;
}
AllocatorInfo Backing; AllocatorInfo Backing;
void* PhysicalStart; void* PhysicalStart;
ssize TotalSize; ssize TotalSize;
ssize TotalUsed; ssize TotalUsed;
ssize TempCount; ssize TempCount;
operator AllocatorInfo() #if GEN_SUPPORT_CPP_MEMBER_FEATURES
{ #pragma region Member Mapping
return { allocator_proc, this }; forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); }
}
forceinline static void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) { return GEN_NS arena_allocator_proc( allocator_data, type, size, alignment, old_memory, old_size, flags ); }
forceinline static Arena init_from_memory( void* start, ssize size ) { return GEN_NS arena_init_from_memory( start, size ); }
forceinline static Arena init_from_allocator( AllocatorInfo backing, ssize size ) { return GEN_NS arena_init_from_allocator( backing, size ); }
forceinline static Arena init_sub( Arena& parent, ssize size ) { return GEN_NS arena_init_from_allocator( parent.Backing, size ); }
forceinline ssize alignment_of( ssize alignment ) { return GEN_NS alignment_of(this, alignment); }
forceinline void free() { return GEN_NS free(this); }
forceinline ssize size_remaining( ssize alignment ) { return GEN_NS size_remaining(this, alignment); }
// This id is defined by Unreal for asserts
#pragma push_macro("check")
#undef check
forceinline void check() { GEN_NS check(this); }
#pragma pop_macro("check")
#pragma endregion Member Mapping
#endif
}; };
#if GEN_SUPPORT_CPP_REFERENCES
forceinline AllocatorInfo allocator_info(Arena& arena ) { return allocator_info(& arena); }
forceinline Arena init_sub (Arena& parent, ssize size) { return init_sub( & parent, size); }
forceinline ssize alignment_of (Arena& arena, ssize alignment) { return alignment_of( & arena, alignment); }
forceinline void free (Arena& arena) { return free(& arena); }
forceinline ssize size_remaining(Arena& arena, ssize alignment) { return size_remaining(& arena, alignment); }
// This id is defined by Unreal for asserts
#pragma push_macro("check")
#undef check
forceinline void check(Arena& arena) { return check(& arena); };
#pragma pop_macro("check")
#endif
inline
AllocatorInfo allocator_info( Arena* arena ) {
GEN_ASSERT(arena != nullptr);
return { arena_allocator_proc, arena };
}
inline
Arena arena_init_from_memory( void* start, ssize size )
{
Arena arena = {
{ nullptr, nullptr },
start,
size,
0,
0
};
return arena;
}
inline
Arena arena_init_from_allocator(AllocatorInfo backing, ssize size) {
Arena result = {
backing,
alloc(backing, size),
size,
0,
0
};
return result;
}
inline
Arena init_sub(Arena* parent, ssize size) {
GEN_ASSERT(parent != nullptr);
return arena_init_from_allocator(parent->Backing, size);
}
inline
ssize alignment_of(Arena* arena, ssize alignment)
{
GEN_ASSERT(arena != nullptr);
ssize alignment_offset, result_pointer, mask;
GEN_ASSERT(is_power_of_two(alignment));
alignment_offset = 0;
result_pointer = (ssize)arena->PhysicalStart + arena->TotalUsed;
mask = alignment - 1;
if (result_pointer & mask)
alignment_offset = alignment - (result_pointer & mask);
return alignment_offset;
}
#pragma push_macro("check")
#undef check
inline
void check(Arena* arena)
{
GEN_ASSERT(arena != nullptr );
GEN_ASSERT(arena->TempCount == 0);
}
#pragma pop_macro("check")
inline
void free(Arena* arena)
{
GEN_ASSERT(arena != nullptr);
if (arena->Backing.Proc)
{
GEN_NS free(arena->Backing, arena->PhysicalStart);
arena->PhysicalStart = nullptr;
}
}
inline
ssize size_remaining(Arena* arena, ssize alignment)
{
GEN_ASSERT(arena != nullptr);
ssize result = arena->TotalSize - (arena->TotalUsed + alignment_of(arena, alignment));
return result;
}
#pragma endregion Arena
#pragma region FixedArena
template<s32 Size>
struct FixedArena;
template<s32 Size> FixedArena<Size> fixed_arena_init();
template<s32 Size> AllocatorInfo allocator_info(FixedArena<Size>* fixed_arena );
template<s32 Size> ssize size_remaining(FixedArena<Size>* fixed_arena, ssize alignment);
#if GEN_SUPPORT_CPP_REFERENCES
template<s32 Size> AllocatorInfo allocator_info( FixedArena<Size>& fixed_arena ) { return allocator_info(& fixed_arena); }
template<s32 Size> ssize size_remaining(FixedArena<Size>& fixed_arena, ssize alignment) { return size_remaining( & fixed_arena, alignment); }
#endif
// Just a wrapper around using an arena with memory associated with its scope instead of from an allocator. // Just a wrapper around using an arena with memory associated with its scope instead of from an allocator.
// Used for static segment or stack allocations. // Used for static segment or stack allocations.
template< s32 Size > template< s32 Size >
struct FixedArena struct FixedArena
{ {
static char memory[Size];
FixedArena init()
{
FixedArena result = { Arena::init_from_memory( result.memory, Size ), {0} };
return result;
}
ssize size_remaining( ssize alignment )
{
return arena.size_remaining( alignment );
}
operator AllocatorInfo()
{
return { Arena::allocator_proc, &arena };
}
Arena arena; Arena arena;
char memory[ Size ];
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
#pragma region Member Mapping
forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); }
forceinline static FixedArena init() { FixedArena result; GEN_NS fixed_arena_init<Size>(result); return result; }
forceinline ssize size_remaining(ssize alignment) { GEN_NS size_remaining(this, alignment); }
#pragma endregion Member Mapping
#endif
}; };
template<s32 Size> inline
AllocatorInfo allocator_info( FixedArena<Size>* fixed_arena ) {
GEN_ASSERT(fixed_arena);
return { arena_allocator_proc, & fixed_arena->arena };
}
template<s32 Size> inline
void fixed_arena_init(FixedArena<Size>* result) {
zero_size(& result->memory[0], Size);
result->arena = arena_init_from_memory(& result->memory[0], Size);
}
template<s32 Size> inline
ssize size_remaining(FixedArena<Size>* fixed_arena, ssize alignment) {
return size_remaining(fixed_arena->arena, alignment);
}
using Arena_1KB = FixedArena< kilobytes( 1 ) >; using Arena_1KB = FixedArena< kilobytes( 1 ) >;
using Arena_4KB = FixedArena< kilobytes( 4 ) >; using Arena_4KB = FixedArena< kilobytes( 4 ) >;
using Arena_8KB = FixedArena< kilobytes( 8 ) >; using Arena_8KB = FixedArena< kilobytes( 8 ) >;
@ -297,31 +381,27 @@ using Arena_512KB = FixedArena< kilobytes( 512 ) >;
using Arena_1MB = FixedArena< megabytes( 1 ) >; using Arena_1MB = FixedArena< megabytes( 1 ) >;
using Arena_2MB = FixedArena< megabytes( 2 ) >; using Arena_2MB = FixedArena< megabytes( 2 ) >;
using Arena_4MB = FixedArena< megabytes( 4 ) >; using Arena_4MB = FixedArena< megabytes( 4 ) >;
#pragma endregion FixedArena
#pragma region Pool
struct Pool;
void* pool_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags);
Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size);
Pool pool_init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align);
AllocatorInfo allocator_info(Pool* pool);
void clear(Pool* pool);
void free(Pool* pool);
#if GEN_SUPPORT_CPP_REFERENCES
AllocatorInfo allocator_info(Pool& pool);
void clear(Pool& pool);
void free(Pool& pool);
#endif
struct Pool struct Pool
{ {
static
void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
static
Pool init( AllocatorInfo backing, ssize num_blocks, ssize block_size )
{
return init_align( backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT );
}
static
Pool init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align );
void clear();
void free()
{
if ( Backing.Proc )
{
gen::free( Backing, PhysicalStart );
}
}
AllocatorInfo Backing; AllocatorInfo Backing;
void* PhysicalStart; void* PhysicalStart;
void* FreeList; void* FreeList;
@ -330,12 +410,36 @@ struct Pool
ssize TotalSize; ssize TotalSize;
ssize NumBlocks; ssize NumBlocks;
operator AllocatorInfo() #if GEN_SUPPORT_CPP_MEMBER_FEATURES
{ #pragma region Member Mapping
return { allocator_proc, this }; forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); }
}
forceinline static void* allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags) { return GEN_NS pool_allocator_proc(allocator_data, type, size, alignment, old_memory, old_size, flags); }
forceinline static Pool init(AllocatorInfo backing, ssize num_blocks, ssize block_size) { return GEN_NS pool_init(backing, num_blocks, block_size); }
forceinline static Pool init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align) { return GEN_NS pool_init_align(backing, num_blocks, block_size, block_align); }
forceinline void clear() { GEN_NS clear( this); }
forceinline void free() { GEN_NS free( this); }
#pragma endregion
#endif
}; };
inline
AllocatorInfo allocator_info(Pool* pool) {
return { pool_allocator_proc, pool };
}
inline
Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size) {
return pool_init_align(backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT);
}
inline
void free(Pool* pool) {
if(pool->Backing.Proc) {
GEN_NS free(pool->Backing, pool->PhysicalStart);
}
}
#pragma endregion Pool
inline inline
b32 is_power_of_two( ssize x ) { b32 is_power_of_two( ssize x ) {

View File

@ -23,7 +23,7 @@ u8 adt_make_branch( ADT_Node* node, AllocatorInfo backing, char const* name, b32
node->type = type; node->type = type;
node->name = name; node->name = name;
node->parent = parent; node->parent = parent;
node->nodes = Array<ADT_Node>::init( backing ); node->nodes = array_init<ADT_Node>( backing );
if ( ! node->nodes ) if ( ! node->nodes )
return EADT_ERROR_OUT_OF_MEMORY; return EADT_ERROR_OUT_OF_MEMORY;
@ -36,12 +36,12 @@ u8 adt_destroy_branch( ADT_Node* node )
GEN_ASSERT_NOT_NULL( node ); GEN_ASSERT_NOT_NULL( node );
if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes ) if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes )
{ {
for ( ssize i = 0; i < scast(ssize, node->nodes.num()); ++i ) for ( ssize i = 0; i < scast(ssize, num(node->nodes)); ++i )
{ {
adt_destroy_branch( node->nodes + i ); adt_destroy_branch( node->nodes + i );
} }
node->nodes.free(); free(& node->nodes);
} }
return 0; return 0;
} }
@ -66,7 +66,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search )
return NULL; return NULL;
} }
for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
{ {
if ( ! str_compare( node->nodes[ i ].name, name ) ) if ( ! str_compare( node->nodes[ i ].name, name ) )
{ {
@ -76,7 +76,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search )
if ( deep_search ) if ( deep_search )
{ {
for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
{ {
ADT_Node* res = adt_find( node->nodes + i, name, deep_search ); ADT_Node* res = adt_find( node->nodes + i, name, deep_search );
@ -132,7 +132,7 @@ internal ADT_Node* _adt_get_value( ADT_Node* node, char const* value )
internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value ) internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value )
{ {
for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
{ {
if ( ! str_compare( node->nodes[ i ].name, name ) ) if ( ! str_compare( node->nodes[ i ].name, name ) )
{ {
@ -207,7 +207,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri )
/* run a value comparison against any child that is an object node */ /* run a value comparison against any child that is an object node */
else if ( node->type == EADT_TYPE_ARRAY ) else if ( node->type == EADT_TYPE_ARRAY )
{ {
for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
{ {
ADT_Node* child = &node->nodes[ i ]; ADT_Node* child = &node->nodes[ i ];
if ( child->type != EADT_TYPE_OBJECT ) if ( child->type != EADT_TYPE_OBJECT )
@ -225,7 +225,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri )
/* [value] */ /* [value] */
else else
{ {
for ( ssize i = 0; i < scast(ssize, node->nodes.num()); i++ ) for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
{ {
ADT_Node* child = &node->nodes[ i ]; ADT_Node* child = &node->nodes[ i ];
if ( _adt_get_value( child, l_b2 ) ) if ( _adt_get_value( child, l_b2 ) )
@ -257,7 +257,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri )
else else
{ {
ssize idx = ( ssize )str_to_i64( buf, NULL, 10 ); ssize idx = ( ssize )str_to_i64( buf, NULL, 10 );
if ( idx >= 0 && idx < scast(ssize, node->nodes.num()) ) if ( idx >= 0 && idx < scast(ssize, num(node->nodes)) )
{ {
found_node = &node->nodes[ idx ]; found_node = &node->nodes[ idx ];
@ -282,15 +282,16 @@ ADT_Node* adt_alloc_at( ADT_Node* parent, ssize index )
if ( ! parent->nodes ) if ( ! parent->nodes )
return NULL; return NULL;
if ( index < 0 || index > scast(ssize, parent->nodes.num()) ) if ( index < 0 || index > scast(ssize, num(parent->nodes)) )
return NULL; return NULL;
ADT_Node o = { 0 }; ADT_Node o = { 0 };
o.parent = parent; o.parent = parent;
if ( ! parent->nodes.append_at( o, index ) ) if ( ! append_at( & parent->nodes, o, index ) )
return NULL; return NULL;
return parent->nodes + index; ADT_Node* node = & parent->nodes[index];
return node;
} }
ADT_Node* adt_alloc( ADT_Node* parent ) ADT_Node* adt_alloc( ADT_Node* parent )
@ -303,7 +304,7 @@ ADT_Node* adt_alloc( ADT_Node* parent )
if ( ! parent->nodes ) if ( ! parent->nodes )
return NULL; return NULL;
return adt_alloc_at( parent, parent->nodes.num() ); return adt_alloc_at( parent, num(parent->nodes) );
} }
b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing ) b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing )
@ -357,7 +358,7 @@ ADT_Node* adt_move_node( ADT_Node* node, ADT_Node* new_parent )
GEN_ASSERT_NOT_NULL( node ); GEN_ASSERT_NOT_NULL( node );
GEN_ASSERT_NOT_NULL( new_parent ); GEN_ASSERT_NOT_NULL( new_parent );
GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT ); GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT );
return adt_move_node_at( node, new_parent, new_parent->nodes.num() ); return adt_move_node_at( node, new_parent, num(new_parent->nodes) );
} }
void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node ) void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node )
@ -381,7 +382,7 @@ void adt_remove_node( ADT_Node* node )
GEN_ASSERT_NOT_NULL( node->parent ); GEN_ASSERT_NOT_NULL( node->parent );
ADT_Node* parent = node->parent; ADT_Node* parent = node->parent;
ssize index = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); ssize index = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) );
parent->nodes.remove_at( index ); remove_at( parent->nodes, index );
} }
ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) ADT_Node* adt_append_obj( ADT_Node* parent, char const* name )
@ -389,7 +390,7 @@ ADT_Node* adt_append_obj( ADT_Node* parent, char const* name )
ADT_Node* o = adt_alloc( parent ); ADT_Node* o = adt_alloc( parent );
if ( ! o ) if ( ! o )
return NULL; return NULL;
if ( adt_set_obj( o, name, parent->nodes.get_header()->Allocator ) ) if ( adt_set_obj( o, name, get_header(parent->nodes)->Allocator ) )
{ {
adt_remove_node( o ); adt_remove_node( o );
return NULL; return NULL;
@ -402,7 +403,9 @@ ADT_Node* adt_append_arr( ADT_Node* parent, char const* name )
ADT_Node* o = adt_alloc( parent ); ADT_Node* o = adt_alloc( parent );
if ( ! o ) if ( ! o )
return NULL; return NULL;
if ( adt_set_arr( o, name, parent->nodes.get_header()->Allocator ) )
ArrayHeader* node_header = get_header(parent->nodes);
if ( adt_set_arr( o, name, node_header->Allocator ) )
{ {
adt_remove_node( o ); adt_remove_node( o );
return NULL; return NULL;
@ -447,7 +450,7 @@ char* adt_parse_number_strict( ADT_Node* node, char* base_str )
while ( *e ) while ( *e )
++e; ++e;
while ( *p && ( str_find( "eE.+-", *p ) || char_is_hex_digit( *p ) ) ) while ( *p && ( char_first_occurence( "eE.+-", *p ) || char_is_hex_digit( *p ) ) )
{ {
++p; ++p;
} }
@ -476,7 +479,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str )
u8 node_props = 0; u8 node_props = 0;
/* skip false positives and special cases */ /* skip false positives and special cases */
if ( ! ! str_find( "eE", *p ) || ( ! ! str_find( ".+-", *p ) && ! char_is_hex_digit( *( p + 1 ) ) && *( p + 1 ) != '.' ) ) if ( ! ! char_first_occurence( "eE", *p ) || ( ! ! char_first_occurence( ".+-", *p ) && ! char_is_hex_digit( *( p + 1 ) ) && *( p + 1 ) != '.' ) )
{ {
return ++base_str; return ++base_str;
} }
@ -552,7 +555,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str )
char expbuf[ 6 ] = { 0 }; char expbuf[ 6 ] = { 0 };
ssize expi = 0; ssize expi = 0;
if ( *e && ! ! str_find( "eE", *e ) ) if ( *e && ! ! char_first_occurence( "eE", *e ) )
{ {
++e; ++e;
if ( *e == '+' || *e == '-' || char_is_digit( *e ) ) if ( *e == '+' || *e == '-' || char_is_digit( *e ) )
@ -748,7 +751,7 @@ ADT_Error adt_print_string( FileInfo* file, ADT_Node* node, char const* escaped_
{ {
p = str_skip_any( p, escaped_chars ); p = str_skip_any( p, escaped_chars );
_adt_fprintf( file, "%.*s", pointer_diff( b, p ), b ); _adt_fprintf( file, "%.*s", pointer_diff( b, p ), b );
if ( *p && ! ! str_find( escaped_chars, *p ) ) if ( *p && ! ! char_first_occurence( escaped_chars, *p ) )
{ {
_adt_fprintf( file, "%s%c", escape_symbol, *p ); _adt_fprintf( file, "%s%c", escape_symbol, *p );
p++; p++;
@ -946,12 +949,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
} }
} }
if ( columnIndex >= scast(ssize, root->nodes.num()) ) if ( columnIndex >= scast(ssize, num(root->nodes)) )
{ {
adt_append_arr( root, NULL ); adt_append_arr( root, NULL );
} }
root->nodes[ columnIndex ].nodes.append( rowItem ); append( & root->nodes[ columnIndex ].nodes, rowItem );
if ( delimiter == delim ) if ( delimiter == delim )
{ {
@ -979,7 +982,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
} }
while ( *currentChar ); while ( *currentChar );
if ( root->nodes.num() == 0 ) if (num( root->nodes) == 0 )
{ {
GEN_CSV_ASSERT( "unexpected end of input. stream is empty." ); GEN_CSV_ASSERT( "unexpected end of input. stream is empty." );
error = ECSV_Error__UNEXPECTED_END_OF_INPUT; error = ECSV_Error__UNEXPECTED_END_OF_INPUT;
@ -989,12 +992,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
/* consider first row as a header. */ /* consider first row as a header. */
if ( has_header ) if ( has_header )
{ {
for ( ssize i = 0; i < scast(ssize, root->nodes.num()); i++ ) for ( ssize i = 0; i < scast(ssize, num(root->nodes)); i++ )
{ {
CSV_Object* col = root->nodes + i; CSV_Object* col = root->nodes + i;
CSV_Object* hdr = col->nodes; CSV_Object* hdr = col->nodes;
col->name = hdr->string; col->name = hdr->string;
col->nodes.remove_at( 0 ); remove_at(col->nodes, 0 );
} }
} }
@ -1057,11 +1060,11 @@ void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delimiter )
GEN_ASSERT_NOT_NULL( file ); GEN_ASSERT_NOT_NULL( file );
GEN_ASSERT_NOT_NULL( obj ); GEN_ASSERT_NOT_NULL( obj );
GEN_ASSERT( obj->nodes ); GEN_ASSERT( obj->nodes );
ssize cols = obj->nodes.num(); ssize cols = num(obj->nodes);
if ( cols == 0 ) if ( cols == 0 )
return; return;
ssize rows = obj->nodes[ 0 ].nodes.num(); ssize rows = num(obj->nodes[ 0 ].nodes);
if ( rows == 0 ) if ( rows == 0 )
return; return;
@ -1102,7 +1105,7 @@ String csv_write_string_delimiter( AllocatorInfo a, CSV_Object* obj, char delimi
ssize fsize; ssize fsize;
u8* buf = file_stream_buf( &tmp, &fsize ); u8* buf = file_stream_buf( &tmp, &fsize );
String output = String::make_length( a, ( char* )buf, fsize ); String output = string_make_length( a, ( char* )buf, fsize );
file_close( &tmp ); file_close( &tmp );
return output; return output;
} }

View File

@ -83,7 +83,7 @@ struct ADT_Node
union union
{ {
char const* string; char const* string;
Array<ADT_Node> nodes; ///< zpl_array Array(ADT_Node) nodes; ///< zpl_array
struct struct
{ {

View File

@ -76,13 +76,18 @@
/* Platform compiler */ /* Platform compiler */
#if defined( _MSC_VER ) #if defined( _MSC_VER )
# define GEN_COMPILER_MSVC 1 # define GEN_COMPILER_CLANG 0
# define GEN_COMPILER_MSVC 1
# define GEN_COMPILER_GCC 0
#elif defined( __GNUC__ ) #elif defined( __GNUC__ )
# define GEN_COMPILER_GCC 1 # define GEN_COMPILER_CLANG 0
# define GEN_COMPILER_MSVC 0
# define GEN_COMPILER_GCC 1
#elif defined( __clang__ ) #elif defined( __clang__ )
# define GEN_COMPILER_CLANG 1 # define GEN_COMPILER_CLANG 1
#elif defined( __MINGW32__ ) # define GEN_COMPILER_MSVC 0
# define GEN_COMPILER_MINGW 1 # define GEN_COMPILER_GCC 1
#else
# error Unknown compiler # error Unknown compiler
#endif #endif
@ -101,6 +106,14 @@
# define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) # define GEN_GCC_VERSION_CHECK(major,minor,patch) (0)
#endif #endif
#ifndef GEN_COMPILER_C
# if defined(__STDC_VERSION__)
# define GEN_COMPILER_C 1
# else
# define GEN_COMPILER_C 0
# endif
#endif
#pragma endregion Platform Detection #pragma endregion Platform Detection
#pragma region Mandatory Includes #pragma region Mandatory Includes
@ -112,13 +125,29 @@
# include <intrin.h> # include <intrin.h>
# endif # endif
#if GEN_COMPILER_C
#include <assert.h>
#endif
#pragma endregion Mandatory Includes #pragma endregion Mandatory Includes
#ifdef GEN_DONT_USE_NAMESPACE #if GEN_DONT_USE_NAMESPACE || GEN_COMPILER_C
# define GEN_NS # if GEN_COMPILER_C
# define GEN_NS_BEGIN # define GEN_NS_ENUM_BEGIN
# define GEN_NS_END # define GEN_NS_ENUM_END
# define GEN_NS
# define GEN_NS_BEGIN
# define GEN_NS_END
# else
# define GEN_NS_ENUM_BEGIN namespace gen_internal_enums {
# define GEN_NS_ENUM_END }
# define GEN_NS ::
# define GEN_NS_BEGIN
# define GEN_NS_END
# endif
#else #else
# define GEN_NS_ENUM_BEGIN namespace gen_internal_enums {
# define GEN_NS_ENUM_END }
# define GEN_NS gen:: # define GEN_NS gen::
# define GEN_NS_BEGIN namespace gen { # define GEN_NS_BEGIN namespace gen {
# define GEN_NS_END } # define GEN_NS_END }

View File

@ -422,7 +422,7 @@ neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_lis
{ {
String gen_str = String { va_arg( va, char*) }; String gen_str = String { va_arg( va, char*) };
info.precision = gen_str.length(); info.precision = length(gen_str);
len = _print_string( text, remaining, &info, gen_str ); len = _print_string( text, remaining, &info, gen_str );
} }
break; break;

View File

@ -6,7 +6,6 @@
#pragma region String Ops #pragma region String Ops
const char* char_first_occurence( const char* str, char c ); const char* char_first_occurence( const char* str, char c );
constexpr auto str_find = &char_first_occurence;
b32 char_is_alpha( char c ); b32 char_is_alpha( char c );
b32 char_is_alphanumeric( char c ); b32 char_is_alphanumeric( char c );

View File

@ -4,20 +4,9 @@
#endif #endif
#pragma region String #pragma region String
String string_make_length( AllocatorInfo allocator, char const* str, ssize length )
String String::fmt( AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ... )
{ {
va_list va; constexpr ssize header_size = sizeof( StringHeader );
va_start( va, fmt );
str_fmt_va( buf, buf_size, fmt, va );
va_end( va );
return make( allocator, buf );
}
String String::make_length( AllocatorInfo allocator, char const* str, ssize length )
{
constexpr ssize header_size = sizeof( Header );
s32 alloc_size = header_size + length + 1; s32 alloc_size = header_size + length + 1;
void* allocation = alloc( allocator, alloc_size ); void* allocation = alloc( allocator, alloc_size );
@ -25,8 +14,8 @@ String String::make_length( AllocatorInfo allocator, char const* str, ssize leng
if ( allocation == nullptr ) if ( allocation == nullptr )
return { nullptr }; return { nullptr };
Header& StringHeader&
header = * rcast(Header*, allocation); header = * rcast(StringHeader*, allocation);
header = { allocator, length, length }; header = { allocator, length, length };
String result = { rcast( char*, allocation) + header_size }; String result = { rcast( char*, allocation) + header_size };
@ -41,9 +30,9 @@ String String::make_length( AllocatorInfo allocator, char const* str, ssize leng
return result; return result;
} }
String String::make_reserve( AllocatorInfo allocator, ssize capacity ) String string_make_reserve( AllocatorInfo allocator, ssize capacity )
{ {
constexpr ssize header_size = sizeof( Header ); constexpr ssize header_size = sizeof( StringHeader );
s32 alloc_size = header_size + capacity + 1; s32 alloc_size = header_size + capacity + 1;
void* allocation = alloc( allocator, alloc_size ); void* allocation = alloc( allocator, alloc_size );
@ -53,8 +42,8 @@ String String::make_reserve( AllocatorInfo allocator, ssize capacity )
mem_set( allocation, 0, alloc_size ); mem_set( allocation, 0, alloc_size );
Header* StringHeader*
header = rcast(Header*, allocation); header = rcast(StringHeader*, allocation);
header->Allocator = allocator; header->Allocator = allocator;
header->Capacity = capacity; header->Capacity = capacity;
header->Length = 0; header->Length = 0;
@ -62,69 +51,4 @@ String String::make_reserve( AllocatorInfo allocator, ssize capacity )
String result = { rcast(char*, allocation) + header_size }; String result = { rcast(char*, allocation) + header_size };
return result; return result;
} }
String String::fmt_buf( AllocatorInfo allocator, char const* fmt, ... )
{
local_persist thread_local
char buf[ GEN_PRINTF_MAXLEN ] = { 0 };
va_list va;
va_start( va, fmt );
str_fmt_va( buf, GEN_PRINTF_MAXLEN, fmt, va );
va_end( va );
return make( allocator, buf );
}
bool String::append_fmt( char const* fmt, ... )
{
ssize res;
char buf[ GEN_PRINTF_MAXLEN ] = { 0 };
va_list va;
va_start( va, fmt );
res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1;
va_end( va );
return append( buf, res );
}
bool String::make_space_for( char const* str, ssize add_len )
{
ssize available = avail_space();
// NOTE: Return if there is enough space left
if ( available >= add_len )
{
return true;
}
else
{
ssize new_len, old_size, new_size;
void* ptr;
void* new_ptr;
AllocatorInfo allocator = get_header().Allocator;
Header* header = nullptr;
new_len = grow_formula( length() + add_len );
ptr = & get_header();
old_size = size_of( Header ) + length() + 1;
new_size = size_of( Header ) + new_len + 1;
new_ptr = resize( allocator, ptr, old_size, new_size );
if ( new_ptr == nullptr )
return false;
header = rcast( Header*, new_ptr);
header->Allocator = allocator;
header->Capacity = new_len;
Data = rcast( char*, header + 1 );
return true;
}
}
#pragma endregion String #pragma endregion String

View File

@ -8,19 +8,20 @@
// Constant string with length. // Constant string with length.
struct StrC struct StrC
{ {
ssize Len; ssize Len;
char const* Ptr; char const* Ptr;
#if ! GEN_COMPILER_C
operator char const* () const { return Ptr; } operator char const* () const { return Ptr; }
char const& operator[]( ssize index ) const { return Ptr[index]; } char const& operator[]( ssize index ) const { return Ptr[index]; }
#endif
}; };
#define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) ) #define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) )
#define txt( text ) StrC { sizeof( text ) - 1, ( text ) } #define txt( text ) StrC { sizeof( text ) - 1, ( text ) }
inline inline
StrC to_str( char const* str ) StrC to_str( char const* str ) {
{
return { str_len( str ), str }; return { str_len( str ), str };
} }
@ -28,388 +29,572 @@ StrC to_str( char const* str )
// This is directly based off the ZPL string api. // This is directly based off the ZPL string api.
// They used a header pattern // They used a header pattern
// I kept it for simplicty of porting but its not necessary to keep it that way. // I kept it for simplicty of porting but its not necessary to keep it that way.
#pragma region String
struct StringHeader;
struct String;
usize string_grow_formula(usize value);
String string_make (AllocatorInfo allocator, char const* str);
String string_make (AllocatorInfo allocator, StrC str);
String string_make_reserve (AllocatorInfo allocator, ssize capacity);
String string_make_length (AllocatorInfo allocator, char const* str, ssize length);
String string_fmt (AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...);
String string_fmt_buf (AllocatorInfo allocator, char const* fmt, ...);
String string_join (AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue);
bool are_equal (String const lhs, String const rhs);
bool are_equal (String const lhs, StrC rhs);
bool make_space_for (String* str, char const* to_append, ssize add_len);
bool append (String* str, char c);
bool append (String* str, char const* str_to_append);
bool append (String* str, char const* str_to_append, ssize length);
bool append (String* str, StrC str_to_append);
bool append (String* str, String const other);
bool append_fmt (String* str, char const* fmt, ...);
ssize avail_space (String const str);
char* back (String str);
bool contains (String const str, StrC substring);
bool contains (String const str, String const substring);
ssize capacity (String const str);
void clear (String str);
String duplicate (String const str, AllocatorInfo allocator);
void free (String* str);
StringHeader* get_header (String str);
ssize length (String const str);
b32 starts_with (String const str, StrC substring);
b32 starts_with (String const str, String substring);
void skip_line (String str);
void strip_space (String str);
void trim (String str, char const* cut_set);
void trim_space (String str);
String visualize_whitespace(String const str);
struct StringHeader {
AllocatorInfo Allocator;
ssize Capacity;
ssize Length;
};
#if ! GEN_COMPILER_C
struct String struct String
{ {
struct Header char* Data;
{
AllocatorInfo Allocator;
ssize Capacity;
ssize Length;
};
static forceinline operator bool() { return Data != nullptr; }
usize grow_formula( usize value ) forceinline operator char*() { return Data; }
{ forceinline operator char const*() const { return Data; }
// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. forceinline operator StrC() const { return { GEN_NS length(* this), Data }; }
return 4 * value + 8;
}
static String const& operator=(String const& other) const {
String make( AllocatorInfo allocator, char const* str ) if (this == &other)
{
ssize length = str ? str_len( str ) : 0;
return make_length( allocator, str, length );
}
static
String make( AllocatorInfo allocator, StrC str )
{
return make_length( allocator, str.Ptr, str.Len );
}
static
String make_reserve( AllocatorInfo allocator, ssize capacity );
static
String make_length( AllocatorInfo allocator, char const* str, ssize length );
static
String fmt( AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ... );
static
String fmt_buf( AllocatorInfo allocator, char const* fmt, ... );
static
String join( AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue )
{
String result = make( allocator, "" );
for ( ssize idx = 0; idx < num_parts; ++idx )
{
result.append( parts[ idx ] );
if ( idx < num_parts - 1 )
result.append( glue );
}
return result;
}
static
bool are_equal( String lhs, String rhs )
{
if ( lhs.length() != rhs.length() )
return false;
for ( ssize idx = 0; idx < lhs.length(); ++idx )
if ( lhs[ idx ] != rhs[ idx ] )
return false;
return true;
}
static
bool are_equal( String lhs, StrC rhs )
{
if ( lhs.length() != (rhs.Len) )
return false;
for ( ssize idx = 0; idx < lhs.length(); ++idx )
if ( lhs[idx] != rhs[idx] )
return false;
return true;
}
bool make_space_for( char const* str, ssize add_len );
bool append( char c )
{
return append( & c, 1 );
}
bool append( char const* str )
{
return append( str, str_len( str ) );
}
bool append( char const* str, ssize length )
{
if ( sptr(str) > 0 )
{
ssize curr_len = this->length();
if ( ! make_space_for( str, length ) )
return false;
Header& header = get_header();
mem_copy( Data + curr_len, str, length );
Data[ curr_len + length ] = '\0';
header.Length = curr_len + length;
}
return str != nullptr;
}
bool append( StrC str)
{
return append( str.Ptr, str.Len );
}
bool append( const String other )
{
return append( other.Data, other.length() );
}
bool append_fmt( char const* fmt, ... );
ssize avail_space() const
{
Header const&
header = * rcast( Header const*, Data - sizeof( Header ));
return header.Capacity - header.Length;
}
char& back()
{
return Data[ length() - 1 ];
}
ssize capacity() const
{
Header const&
header = * rcast( Header const*, Data - sizeof( Header ));
return header.Capacity;
}
void clear()
{
get_header().Length = 0;
}
String duplicate( AllocatorInfo allocator ) const
{
return make_length( allocator, Data, length() );
}
void free()
{
if ( ! Data )
return;
Header& header = get_header();
gen::free( header.Allocator, & header );
}
Header& get_header()
{
return *(Header*)(Data - sizeof(Header));
}
ssize length() const
{
Header const&
header = * rcast( Header const*, Data - sizeof( Header ));
return header.Length;
}
b32 starts_with( StrC substring ) const
{
if (substring.Len > length())
return false;
b32 result = str_compare(Data, substring.Ptr, substring.Len ) == 0;
return result;
}
b32 starts_with( String substring ) const
{
if (substring.length() > length())
return false;
b32 result = str_compare(Data, substring, substring.length() - 1 ) == 0;
return result;
}
void skip_line()
{
#define current (*scanner)
char* scanner = Data;
while ( current != '\r' && current != '\n' )
{
++ scanner;
}
s32 new_length = scanner - Data;
if ( current == '\r' )
{
new_length += 1;
}
mem_move( Data, scanner, new_length );
Header* header = & get_header();
header->Length = new_length;
#undef current
}
void strip_space()
{
char* write_pos = Data;
char* read_pos = Data;
while ( * read_pos)
{
if ( ! char_is_space( *read_pos ))
{
*write_pos = *read_pos;
write_pos++;
}
read_pos++;
}
write_pos[0] = '\0'; // Null-terminate the modified string
// Update the length if needed
get_header().Length = write_pos - Data;
}
void trim( char const* cut_set )
{
ssize len = 0;
char* start_pos = Data;
char* end_pos = Data + length() - 1;
while ( start_pos <= end_pos && char_first_occurence( cut_set, *start_pos ) )
start_pos++;
while ( end_pos > start_pos && char_first_occurence( cut_set, *end_pos ) )
end_pos--;
len = scast( ssize, ( start_pos > end_pos ) ? 0 : ( ( end_pos - start_pos ) + 1 ) );
if ( Data != start_pos )
mem_move( Data, start_pos, len );
Data[ len ] = '\0';
get_header().Length = len;
}
void trim_space()
{
return trim( " \t\r\n\v\f" );
}
// Debug function that provides a copy of the string with whitespace characters visualized.
String visualize_whitespace() const
{
Header* header = (Header*)(Data - sizeof(Header));
String result = make_reserve(header->Allocator, length() * 2); // Assume worst case for space requirements.
for ( char c : *this )
{
switch ( c )
{
case ' ':
result.append( txt("·") );
break;
case '\t':
result.append( txt("") );
break;
case '\n':
result.append( txt("") );
break;
case '\r':
result.append( txt("") );
break;
case '\v':
result.append( txt("") );
break;
case '\f':
result.append( txt("") );
break;
default:
result.append(c);
break;
}
}
return result;
}
// For-range support
char* begin() const
{
return Data;
}
char* end() const
{
Header const&
header = * rcast( Header const*, Data - sizeof( Header ));
return Data + header.Length;
}
operator bool()
{
return Data != nullptr;
}
operator char* ()
{
return Data;
}
operator char const* () const
{
return Data;
}
operator StrC() const
{
return { length(), Data };
}
// Used with cached strings
// Essentially makes the string a string view.
String const& operator = ( String const& other ) const
{
if ( this == & other )
return *this; return *this;
String* String* this_ = ccast(String*, this);
this_ = ccast(String*, this);
this_->Data = other.Data; this_->Data = other.Data;
return *this; return *this;
} }
char& operator [] ( ssize index ) forceinline char& operator[](ssize index) { return Data[index]; }
{ forceinline char const& operator[](ssize index) const { return Data[index]; }
return Data[ index ];
forceinline char* begin() const { return Data; }
forceinline char* end() const { return Data + GEN_NS length(* this); }
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
#pragma region Member Mapping
forceinline static String make(AllocatorInfo allocator, char const* str) { return GEN_NS string_make(allocator, str); }
forceinline static String make(AllocatorInfo allocator, StrC str) { return GEN_NS string_make(allocator, str); }
forceinline static String make_reserve(AllocatorInfo allocator, ssize cap) { return GEN_NS string_make_reserve(allocator, cap); }
forceinline static String make_length(AllocatorInfo a, char const* s, ssize l) { return GEN_NS string_make_length(a, s, l); }
forceinline static String join(AllocatorInfo a, char const** p, ssize n, char const* g) { return GEN_NS string_join(a, p, n, g); }
forceinline static usize grow_formula(usize value) { return GEN_NS string_grow_formula(value); }
static
String fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) {
va_list va;
va_start(va, fmt);
str_fmt_va(buf, buf_size, fmt, va);
va_end(va);
return GEN_NS string_make(allocator, buf);
} }
char const& operator [] ( ssize index ) const static
{ String fmt_buf(AllocatorInfo allocator, char const* fmt, ...) {
return Data[ index ]; local_persist thread_local
char buf[GEN_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va);
va_end(va);
return GEN_NS string_make(allocator, buf);
} }
char* Data; forceinline bool make_space_for(char const* str, ssize add_len) { return GEN_NS make_space_for(this, str, add_len); }
forceinline bool append(char c) { return GEN_NS append(this, c); }
forceinline bool append(char const* str) { return GEN_NS append(this, str); }
forceinline bool append(char const* str, ssize length) { return GEN_NS append(this, str, length); }
forceinline bool append(StrC str) { return GEN_NS append(this, str); }
forceinline bool append(const String other) { return GEN_NS append(this, other); }
forceinline ssize avail_space() const { return GEN_NS avail_space(* this); }
forceinline char* back() { return GEN_NS back(* this); }
forceinline bool contains(StrC substring) const { return GEN_NS contains(* this, substring); }
forceinline bool contains(String const& substring) const { return GEN_NS contains(* this, substring); }
forceinline ssize capacity() const { return GEN_NS capacity(* this); }
forceinline void clear() { GEN_NS clear(* this); }
forceinline String duplicate(AllocatorInfo allocator) const { return GEN_NS duplicate(* this, allocator); }
forceinline void free() { GEN_NS free(this); }
forceinline bool is_equal(String const& other) const { return GEN_NS are_equal(* this, other); }
forceinline bool is_equal(StrC other) const { return GEN_NS are_equal(* this, other); }
forceinline ssize length() const { return GEN_NS length(* this); }
forceinline b32 starts_with(StrC substring) const { return GEN_NS starts_with(* this, substring); }
forceinline b32 starts_with(String substring) const { return GEN_NS starts_with(* this, substring); }
forceinline void skip_line() { GEN_NS skip_line(* this); }
forceinline void strip_space() { GEN_NS strip_space(* this); }
forceinline void trim(char const* cut_set) { GEN_NS trim(* this, cut_set); }
forceinline void trim_space() { GEN_NS trim_space(* this); }
forceinline String visualize_whitespace() const { return GEN_NS visualize_whitespace(* this); }
forceinline StringHeader& get_header() { return * GEN_NS get_header(* this); }
bool append_fmt(char const* fmt, ...) {
ssize res;
char buf[GEN_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1;
va_end(va);
return GEN_NS append(this, buf, res);
}
#pragma endregion Member Mapping
#endif
}; };
#endif
struct String_POD #if GEN_SUPPORT_CPP_REFERENCES
bool make_space_for(String& str, char const* to_append, ssize add_len);
bool append(String& str, char c);
bool append(String& str, char const* str_to_append);
bool append(String& str, char const* str_to_append, ssize length);
bool append(String& str, StrC str_to_append);
bool append(String& str, const String other);
bool append_fmt(String& str, char const* fmt, ...);
char& back(String& str);
void clear(String& str);
void free(String& str);
#endif
inline char* begin(String& str) { return str; }
inline char* end(String& str) { return scast(char*, str) + length(str); }
inline char* next(String& str) { return scast(char*, str) + 1; }
inline
usize string_grow_formula(usize value) {
// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library.
return 4 * value + 8;
}
inline
String string_make(AllocatorInfo allocator, char const* str) {
ssize length = str ? str_len(str) : 0;
return string_make_length(allocator, str, length);
}
inline
String string_make(AllocatorInfo allocator, StrC str) {
return string_make_length(allocator, str.Ptr, str.Len);
}
inline
String string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) {
va_list va;
va_start(va, fmt);
str_fmt_va(buf, buf_size, fmt, va);
va_end(va);
return string_make(allocator, buf);
}
inline
String string_fmt_buf(AllocatorInfo allocator, char const* fmt, ...)
{ {
local_persist thread_local
char buf[GEN_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va);
va_end(va);
return string_make(allocator, buf);
}
inline
String string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue)
{
String result = string_make(allocator, "");
for (ssize idx = 0; idx < num_parts; ++idx)
{
append(& result, parts[idx]);
if (idx < num_parts - 1)
append(& result, glue);
}
return result;
}
inline
bool append(String* str, char c) {
GEN_ASSERT(str != nullptr);
return append(str, &c, 1);
}
inline
bool append(String* str, char const* str_to_append) {
GEN_ASSERT(str != nullptr);
return append(str, str_to_append, str_len(str_to_append));
}
inline
bool append(String* str, char const* str_to_append, ssize append_length)
{
GEN_ASSERT(str != nullptr);
if (sptr(str_to_append) > 0)
{
ssize curr_len = length(* str);
if ( ! make_space_for(str, str_to_append, append_length))
return false;
StringHeader* header = get_header(* str);
char* Data = * str;
mem_copy( Data + curr_len, str_to_append, append_length);
Data[curr_len + append_length] = '\0';
header->Length = curr_len + append_length;
}
return str_to_append != nullptr;
}
inline
bool append(String* str, StrC str_to_append) {
GEN_ASSERT(str != nullptr);
return append(str, str_to_append.Ptr, str_to_append.Len);
}
inline
bool append(String* str, const String other) {
GEN_ASSERT(str != nullptr);
return append(str, other, length(other));
}
bool append_fmt(String* str, char const* fmt, ...) {
GEN_ASSERT(str != nullptr);
ssize res;
char buf[GEN_PRINTF_MAXLEN] = { 0 };
va_list va;
va_start(va, fmt);
res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1;
va_end(va);
return append(str, buf, res);
}
inline
bool are_equal(String const lhs, String const rhs)
{
if (length(lhs) != length(rhs))
return false;
for (ssize idx = 0; idx < length(lhs); ++idx)
if (lhs[idx] != rhs[idx])
return false;
return true;
}
inline
bool are_equal(String const lhs, StrC rhs)
{
if (length(lhs) != (rhs.Len))
return false;
for (ssize idx = 0; idx < length(lhs); ++idx)
if (lhs[idx] != rhs.Ptr[idx])
return false;
return true;
}
inline
ssize avail_space(String const str) {
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
return header->Capacity - header->Length;
}
inline
char* back(String* str) {
return & (*str)[length(* str) - 1];
}
inline
bool contains(String const str, StrC substring)
{
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
if (substring.Len > header->Length)
return false;
ssize main_len = header->Length;
ssize sub_len = substring.Len;
for (ssize idx = 0; idx <= main_len - sub_len; ++idx)
{
if (str_compare(str + idx, substring.Ptr, sub_len) == 0)
return true;
}
return false;
}
inline
bool contains(String const str, String const substring)
{
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
if (length(substring) > header->Length)
return false;
ssize main_len = header->Length;
ssize sub_len = length(substring);
for (ssize idx = 0; idx <= main_len - sub_len; ++idx)
{
if (str_compare(str + idx, substring, sub_len) == 0)
return true;
}
return false;
}
inline
ssize capacity(String const str) {
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
return header->Capacity;
}
inline
void clear(String str) {
get_header(str)->Length = 0;
}
inline
String duplicate(String const str, AllocatorInfo allocator) {
return string_make_length(allocator, str, length(str));
}
inline
void free(String* str) {
GEN_ASSERT(str != nullptr);
if (! (* str))
return;
StringHeader* header = get_header(* str);
GEN_NS free(header->Allocator, header);
}
inline
StringHeader* get_header(String str) {
return (StringHeader*)(scast(char*, str) - sizeof(StringHeader));
}
inline
ssize length(String const str)
{
StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
return header.Length;
}
inline
bool make_space_for(String* str, char const* to_append, ssize add_len)
{
ssize available = avail_space(* str);
if (available >= add_len) {
return true;
}
else
{
ssize new_len, old_size, new_size;
void* ptr;
void* new_ptr;
AllocatorInfo allocator = get_header(* str)->Allocator;
StringHeader* header = nullptr;
new_len = string_grow_formula(length(* str) + add_len);
ptr = get_header(* str);
old_size = size_of(StringHeader) + length(* str) + 1;
new_size = size_of(StringHeader) + new_len + 1;
new_ptr = resize(allocator, ptr, old_size, new_size);
if (new_ptr == nullptr)
return false;
header = rcast(StringHeader*, new_ptr);
header->Allocator = allocator;
header->Capacity = new_len;
char** Data = rcast(char**, str);
* Data = rcast(char*, header + 1);
return true;
}
}
inline
b32 starts_with(String const str, StrC substring) {
if (substring.Len > length(str))
return false;
b32 result = str_compare(str.Data, substring.Ptr, substring.Len) == 0;
return result;
}
inline
b32 starts_with(String const str, String substring) {
if (length(substring) > length(str))
return false;
b32 result = str_compare(str.Data, substring.Data, length(substring) - 1) == 0;
return result;
}
inline
void skip_line(String str)
{
#define current (*scanner)
char* scanner = str.Data;
while (current != '\r' && current != '\n') {
++scanner;
}
s32 new_length = scanner - str.Data;
if (current == '\r') {
new_length += 1;
}
mem_move(str.Data, scanner, new_length);
StringHeader* header = get_header(str);
header->Length = new_length;
#undef current
}
inline
void strip_space(String str)
{
char* write_pos = str;
char* read_pos = str;
while (* read_pos)
{
if (! char_is_space(* read_pos))
{
* write_pos = * read_pos;
write_pos++;
}
read_pos++;
}
write_pos[0] = '\0'; // Null-terminate the modified string
// Update the length if needed
get_header(str)->Length = write_pos - str.Data;
}
inline
void trim(String str, char const* cut_set)
{
ssize len = 0;
char* start_pos = str.Data;
char* end_pos = str.Data + length(str) - 1;
while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos))
start_pos++;
while (end_pos > start_pos && char_first_occurence(cut_set, *end_pos))
end_pos--;
len = scast(ssize, (start_pos > end_pos) ? 0 : ((end_pos - start_pos) + 1));
if (str.Data != start_pos)
mem_move(str.Data, start_pos, len);
str.Data[len] = '\0';
get_header(str)->Length = len;
}
inline
void trim_space(String str) {
trim(str, " \t\r\n\v\f");
}
inline
String visualize_whitespace(String const str)
{
StringHeader* header = (StringHeader*)(scast(char const*, str) - sizeof(StringHeader));
String result = string_make_reserve(header->Allocator, length(str) * 2); // Assume worst case for space requirements.
for (auto c : str) switch (c)
{
case ' ':
append(& result, txt("·"));
break;
case '\t':
append(& result, txt(""));
break;
case '\n':
append(& result, txt(""));
break;
case '\r':
append(& result, txt(""));
break;
case '\v':
append(& result, txt(""));
break;
case '\f':
append(& result, txt(""));
break;
default:
append(& result, c);
break;
}
return result;
}
#pragma endregion String
struct String_POD {
char* Data; char* Data;
}; };
static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" );
// Implements basic string interning. Data structure is based off the ZPL Hashtable. // Implements basic string interning. Data structure is based off the ZPL Hashtable.
using StringTable = HashTable<String const>; typedef HashTable<String const> StringTable;
// Represents strings cached with the string table. // Represents strings cached with the string table.
// Should never be modified, if changed string is desired, cache_string( str ) another. // Should never be modified, if changed string is desired, cache_string( str ) another.
using StringCached = String const; typedef String const StringCached;
#pragma endregion Strings #pragma endregion Strings

View File

@ -11,23 +11,24 @@ using namespace gen;
CodeBody gen_ecode( char const* path ) CodeBody gen_ecode( char const* path )
{ {
char scratch_mem[kilobytes(1)]; char scratch_mem[kilobytes(1)];
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( scratch, zero_terminate, path ); file_read_contents( allocator_info( & scratch), zero_terminate, path );
CSV_Object csv_nodes; CSV_Object csv_nodes;
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
for ( ADT_Node node : enum_strs ) for ( ADT_Node& node : enum_strs )
{ {
char const* code = node.string; char const* code = node.string;
enum_entries.append_fmt( "%s,\n", code );
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); append_fmt( & enum_entries, "%s,\n", code );
append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", code, code );
} }
CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", (StrC)enum_entries, "enum Type : u32 { <entries> NumTypes };")); CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", (StrC)enum_entries, "enum Type : u32 { <entries> NumTypes };"));
@ -57,9 +58,9 @@ CodeBody gen_ecode( char const* path )
CodeBody gen_eoperator( char const* path ) CodeBody gen_eoperator( char const* path )
{ {
char scratch_mem[kilobytes(4)]; char scratch_mem[kilobytes(4)];
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( scratch, zero_terminate, path ); file_read_contents( allocator_info(& scratch), zero_terminate, path );
CSV_Object csv_nodes; CSV_Object csv_nodes;
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
@ -67,16 +68,16 @@ CodeBody gen_eoperator( char const* path )
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes; Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes;
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
for (usize idx = 0; idx < enum_strs.num(); idx++) for (usize idx = 0; idx < num(enum_strs); idx++)
{ {
char const* enum_str = enum_strs[idx].string; char const* enum_str = enum_strs[idx].string;
char const* entry_to_str = str_strs [idx].string; char const* entry_to_str = str_strs [idx].string;
enum_entries.append_fmt( "%s,\n", enum_str ); append_fmt( & enum_entries, "%s,\n", enum_str );
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
} }
CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize(
@ -113,9 +114,9 @@ CodeBody gen_eoperator( char const* path )
CodeBody gen_especifier( char const* path ) CodeBody gen_especifier( char const* path )
{ {
char scratch_mem[kilobytes(4)]; char scratch_mem[kilobytes(4)];
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
file_read_contents( scratch, zero_terminate, path ); file_read_contents( allocator_info(& scratch), zero_terminate, path );
CSV_Object csv_nodes; CSV_Object csv_nodes;
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
@ -123,16 +124,16 @@ CodeBody gen_especifier( char const* path )
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes; Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes;
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) );
for (usize idx = 0; idx < enum_strs.num(); idx++) for (usize idx = 0; idx < num(enum_strs); idx++)
{ {
char const* enum_str = enum_strs[idx].string; char const* enum_str = enum_strs[idx].string;
char const* entry_to_str = str_strs [idx].string; char const* entry_to_str = str_strs [idx].string;
enum_entries.append_fmt( "%s,\n", enum_str ); append_fmt( & enum_entries, "%s,\n", enum_str );
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
} }
CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize(
@ -218,14 +219,16 @@ CodeBody gen_especifier( char const* path )
CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) CodeBody gen_etoktype( char const* etok_path, char const* attr_path )
{ {
char scratch_mem[kilobytes(16)]; char scratch_mem[kilobytes(16)];
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) );
FileContents enum_content = file_read_contents( scratch, zero_terminate, etok_path ); AllocatorInfo scratch_info = allocator_info(& scratch);
FileContents enum_content = file_read_contents( scratch_info, zero_terminate, etok_path );
CSV_Object csv_enum_nodes; CSV_Object csv_enum_nodes;
csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false ); csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false );
FileContents attrib_content = file_read_contents( scratch, zero_terminate, attr_path ); FileContents attrib_content = file_read_contents( scratch_info, zero_terminate, attr_path );
CSV_Object csv_attr_nodes; CSV_Object csv_attr_nodes;
csv_parse( &csv_attr_nodes, rcast(char*, attrib_content.data), GlobalAllocator, false ); csv_parse( &csv_attr_nodes, rcast(char*, attrib_content.data), GlobalAllocator, false );
@ -235,34 +238,34 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path )
Array<ADT_Node> attribute_strs = csv_attr_nodes.nodes[0].nodes; Array<ADT_Node> attribute_strs = csv_attr_nodes.nodes[0].nodes;
Array<ADT_Node> attribute_str_strs = csv_attr_nodes.nodes[1].nodes; Array<ADT_Node> attribute_str_strs = csv_attr_nodes.nodes[1].nodes;
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(2) ); String enum_entries = string_make_reserve( GlobalAllocator, kilobytes(2) );
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(4) ); String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(4) );
String attribute_entries = String::make_reserve( GlobalAllocator, kilobytes(2) ); String attribute_entries = string_make_reserve( GlobalAllocator, kilobytes(2) );
String to_str_attributes = String::make_reserve( GlobalAllocator, kilobytes(4) ); String to_str_attributes = string_make_reserve( GlobalAllocator, kilobytes(4) );
String attribute_define_entries = String::make_reserve( GlobalAllocator, kilobytes(4) ); String attribute_define_entries = string_make_reserve( GlobalAllocator, kilobytes(4) );
for (usize idx = 0; idx < enum_strs.num(); idx++) for (usize idx = 0; idx < num(enum_strs); idx++)
{ {
char const* enum_str = enum_strs[idx].string; char const* enum_str = enum_strs[idx].string;
char const* entry_to_str = enum_str_strs [idx].string; char const* entry_to_str = enum_str_strs [idx].string;
enum_entries.append_fmt( "%s,\n", enum_str ); append_fmt( & enum_entries, "%s,\n", enum_str );
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
} }
for ( usize idx = 0; idx < attribute_strs.num(); idx++ ) for ( usize idx = 0; idx < num(attribute_strs); idx++ )
{ {
char const* attribute_str = attribute_strs[idx].string; char const* attribute_str = attribute_strs[idx].string;
char const* entry_to_str = attribute_str_strs [idx].string; char const* entry_to_str = attribute_str_strs [idx].string;
attribute_entries.append_fmt( "Attribute_%s,\n", attribute_str ); append_fmt( & attribute_entries, "Attribute_%s,\n", attribute_str );
to_str_attributes.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); append_fmt( & to_str_attributes, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
attribute_define_entries.append_fmt( "Entry( Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); append_fmt( & attribute_define_entries, "Entry( Attribute_%s, \"%s\" )", attribute_str, entry_to_str );
if ( idx < attribute_strs.num() - 1 ) if ( idx < num(attribute_strs) - 1 )
attribute_define_entries.append( " \\\n"); append( & attribute_define_entries, " \\\n");
else else
attribute_define_entries.append( "\n"); append( & attribute_define_entries, "\n");
} }
#pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS")
@ -340,64 +343,22 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path )
CodeBody gen_ast_inlines() CodeBody gen_ast_inlines()
{ {
#pragma push_macro("GEN_NS")
#pragma push_macro("rcast") #pragma push_macro("rcast")
#pragma push_macro("log_failure") #pragma push_macro("log_failure")
#pragma push_macro("CodeInvalid")
#undef GEN_NS
#undef rcast #undef rcast
#undef log_failure #undef log_failure
#undef CodeInvalid
char const* code_impl_tmpl = stringize( char const* code_impl_tmpl = stringize(
\n \n
inline inline
char const* <typename>::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast(AST*, ast)->debug_str();
}
inline
Code <typename>::duplicate()
{
if ( ast == nullptr )
{
log_failure("Code::duplicate: Cannot duplicate code, AST is null!");
return Code::Invalid;
}
return { rcast(AST*, ast)->duplicate() };
}
inline
bool <typename>::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
// Just check if they're both null.
// log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return ast == nullptr && other.ast == nullptr;
}
return rcast(AST*, ast)->is_equal( other.ast );
}
inline
bool <typename>::is_valid()
{
return (AST*) ast != nullptr && rcast( AST*, ast)->Type != CodeT::Invalid;
}
inline
void <typename>::set_global()
{
if ( ast == nullptr )
{
log_failure("Code::set_global: Cannot set code as global, AST is null!");
return;
}
rcast(AST*, ast)->Parent = Code::Global.ast;
}
inline
<typename>& <typename>::operator =( Code other ) <typename>& <typename>::operator =( Code other )
{ {
if ( other.ast && other->Parent ) if ( other.ast && other->Parent )
{ {
ast = rcast( decltype(ast), other.ast->duplicate() ); ast = rcast( decltype(ast), GEN_NS duplicate(other.ast) );
rcast( AST*, ast)->Parent = nullptr; rcast( AST*, ast)->Parent = nullptr;
} }
@ -405,16 +366,6 @@ CodeBody gen_ast_inlines()
return *this; return *this;
} }
inline inline
bool <typename>::operator ==( Code other )
{
return (AST*) ast == other.ast;
}
inline
bool <typename>::operator !=( Code other )
{
return (AST*) ast != other.ast;
}
inline
<typename>::operator bool() <typename>::operator bool()
{ {
return ast != nullptr; return ast != nullptr;
@ -444,6 +395,8 @@ CodeBody gen_ast_inlines()
} }
\n \n
); );
#pragma pop_macro("GEN_NS")
#pragma pop_macro("CodeInvalid")
CodeBody impl_code = parse_global_body( token_fmt( "typename", StrC name(Code), code_impl_tmpl )); CodeBody impl_code = parse_global_body( token_fmt( "typename", StrC name(Code), code_impl_tmpl ));
CodeBody impl_code_body = parse_global_body( token_fmt( "typename", StrC name(CodeBody), code_impl_tmpl )); CodeBody impl_code_body = parse_global_body( token_fmt( "typename", StrC name(CodeBody), code_impl_tmpl ));
@ -475,29 +428,29 @@ CodeBody gen_ast_inlines()
CodeBody impl_code_using = parse_global_body( token_fmt( "typename", StrC name(CodeUsing), code_impl_tmpl )); CodeBody impl_code_using = parse_global_body( token_fmt( "typename", StrC name(CodeUsing), code_impl_tmpl ));
CodeBody impl_code_var = parse_global_body( token_fmt( "typename", StrC name(CodeVar), code_impl_tmpl )); CodeBody impl_code_var = parse_global_body( token_fmt( "typename", StrC name(CodeVar), code_impl_tmpl ));
impl_code_attr. append( parse_global_body( token_fmt( "typename", StrC name(Attributes), codetype_impl_tmpl ))); append(impl_code_attr, parse_global_body( token_fmt( "typename", StrC name(Attributes), codetype_impl_tmpl )));
impl_code_cmt. append( parse_global_body( token_fmt( "typename", StrC name(Comment), codetype_impl_tmpl ))); append(impl_code_cmt, parse_global_body( token_fmt( "typename", StrC name(Comment), codetype_impl_tmpl )));
impl_code_constr. append( parse_global_body( token_fmt( "typename", StrC name(Constructor), codetype_impl_tmpl ))); append(impl_code_constr, parse_global_body( token_fmt( "typename", StrC name(Constructor), codetype_impl_tmpl )));
impl_code_define. append( parse_global_body( token_fmt( "typename", StrC name(Define), codetype_impl_tmpl ))); append(impl_code_define, parse_global_body( token_fmt( "typename", StrC name(Define), codetype_impl_tmpl )));
impl_code_destruct.append( parse_global_body( token_fmt( "typename", StrC name(Destructor), codetype_impl_tmpl ))); append(impl_code_destruct, parse_global_body( token_fmt( "typename", StrC name(Destructor), codetype_impl_tmpl )));
impl_code_enum. append( parse_global_body( token_fmt( "typename", StrC name(Enum), codetype_impl_tmpl ))); append(impl_code_enum, parse_global_body( token_fmt( "typename", StrC name(Enum), codetype_impl_tmpl )));
impl_code_exec. append( parse_global_body( token_fmt( "typename", StrC name(Exec), codetype_impl_tmpl ))); append(impl_code_exec, parse_global_body( token_fmt( "typename", StrC name(Exec), codetype_impl_tmpl )));
impl_code_extern. append( parse_global_body( token_fmt( "typename", StrC name(Extern), codetype_impl_tmpl ))); append(impl_code_extern, parse_global_body( token_fmt( "typename", StrC name(Extern), codetype_impl_tmpl )));
impl_code_include. append( parse_global_body( token_fmt( "typename", StrC name(Include), codetype_impl_tmpl ))); append(impl_code_include, parse_global_body( token_fmt( "typename", StrC name(Include), codetype_impl_tmpl )));
impl_code_friend. append( parse_global_body( token_fmt( "typename", StrC name(Friend), codetype_impl_tmpl ))); append(impl_code_friend, parse_global_body( token_fmt( "typename", StrC name(Friend), codetype_impl_tmpl )));
impl_code_fn. append( parse_global_body( token_fmt( "typename", StrC name(Fn), codetype_impl_tmpl ))); append(impl_code_fn, parse_global_body( token_fmt( "typename", StrC name(Fn), codetype_impl_tmpl )));
impl_code_module. append( parse_global_body( token_fmt( "typename", StrC name(Module), codetype_impl_tmpl ))); append(impl_code_module, parse_global_body( token_fmt( "typename", StrC name(Module), codetype_impl_tmpl )));
impl_code_ns. append( parse_global_body( token_fmt( "typename", StrC name(NS), codetype_impl_tmpl ))); append(impl_code_ns, parse_global_body( token_fmt( "typename", StrC name(NS), codetype_impl_tmpl )));
impl_code_op. append( parse_global_body( token_fmt( "typename", StrC name(Operator), codetype_impl_tmpl ))); append(impl_code_op, parse_global_body( token_fmt( "typename", StrC name(Operator), codetype_impl_tmpl )));
impl_code_opcast. append( parse_global_body( token_fmt( "typename", StrC name(OpCast), codetype_impl_tmpl ))); append(impl_code_opcast, parse_global_body( token_fmt( "typename", StrC name(OpCast), codetype_impl_tmpl )));
impl_code_pragma . append( parse_global_body( token_fmt( "typename", StrC name(Pragma), codetype_impl_tmpl ))); append(impl_code_pragma, parse_global_body( token_fmt( "typename", StrC name(Pragma), codetype_impl_tmpl )));
impl_code_precond. append( parse_global_body( token_fmt( "typename", StrC name(PreprocessCond), codetype_impl_tmpl ))); append(impl_code_precond, parse_global_body( token_fmt( "typename", StrC name(PreprocessCond), codetype_impl_tmpl )));
impl_code_tmpl. append( parse_global_body( token_fmt( "typename", StrC name(Template), codetype_impl_tmpl ))); append(impl_code_tmpl, parse_global_body( token_fmt( "typename", StrC name(Template), codetype_impl_tmpl )));
impl_code_type. append( parse_global_body( token_fmt( "typename", StrC name(Type), codetype_impl_tmpl ))); append(impl_code_type, parse_global_body( token_fmt( "typename", StrC name(Type), codetype_impl_tmpl )));
impl_code_typedef. append( parse_global_body( token_fmt( "typename", StrC name(Typedef), codetype_impl_tmpl ))); append(impl_code_typedef, parse_global_body( token_fmt( "typename", StrC name(Typedef), codetype_impl_tmpl )));
impl_code_union. append( parse_global_body( token_fmt( "typename", StrC name(Union), codetype_impl_tmpl ))); append(impl_code_union, parse_global_body( token_fmt( "typename", StrC name(Union), codetype_impl_tmpl )));
impl_code_using. append( parse_global_body( token_fmt( "typename", StrC name(Using), codetype_impl_tmpl ))); append(impl_code_using, parse_global_body( token_fmt( "typename", StrC name(Using), codetype_impl_tmpl )));
impl_code_var. append( parse_global_body( token_fmt( "typename", StrC name(Var), codetype_impl_tmpl ))); append(impl_code_var, parse_global_body( token_fmt( "typename", StrC name(Var), codetype_impl_tmpl )));
char const* cast_tmpl = stringize( char const* cast_tmpl = stringize(
inline AST::operator Code<typename>() inline AST::operator Code<typename>()

View File

@ -0,0 +1,10 @@
#pragma once
#include "gen.hpp"
GEN_NS_BEGIN
#include "dependencies/parsing.hpp"
GEN_NS_END
using namespace gen;

View File

@ -44,6 +44,7 @@ Push-Location $path_root
$verbose = $false $verbose = $false
[bool] $bootstrap = $false [bool] $bootstrap = $false
[bool] $singleheader = $false [bool] $singleheader = $false
[bool] $c_library = $false
[bool] $unreal = $false [bool] $unreal = $false
[bool] $test = $false [bool] $test = $false
@ -59,6 +60,7 @@ if ( $args ) { $args | ForEach-Object {
"debug" { $release = $false } "debug" { $release = $false }
"bootstrap" { $bootstrap = $true } "bootstrap" { $bootstrap = $true }
"singleheader" { $singleheader = $true } "singleheader" { $singleheader = $true }
"c_library" { $c_library = $true }
"unreal" { $unreal = $true } "unreal" { $unreal = $true }
"test" { $test = $true } "test" { $test = $true }
} }
@ -88,7 +90,7 @@ else {
$optimize = $true $optimize = $true
} }
if ( $bootstrap -eq $false -and $singleheader -eq $false -and $unreal -eq $false -and $test -eq $false ) { if ( $bootstrap -eq $false -and $singleheader -eq $false -and $c_library -eq $false -and $unreal -eq $false -and $test -eq $false ) {
throw "No build target specified. One must be specified, this script will not assume one" throw "No build target specified. One must be specified, this script will not assume one"
} }
@ -103,8 +105,9 @@ write-host "Build Type: $(if ($release) {"Release"} else {"Debug"} )"
$path_build = Join-Path $path_root build $path_build = Join-Path $path_root build
$path_project = Join-Path $path_root project $path_project = Join-Path $path_root project
$path_scripts = Join-Path $path_root scripts $path_scripts = Join-Path $path_root scripts
$path_singleheader = Join-Path $path_root singleheader $path_c_library = join-Path $path_root gen_c_library
$path_unreal = Join-Path $path_root unreal_engine $path_singleheader = Join-Path $path_root gen_singleheader
$path_unreal = Join-Path $path_root gen_unreal_engine
$path_test = Join-Path $path_root test $path_test = Join-Path $path_root test
if ( $bootstrap ) if ( $bootstrap )
@ -187,6 +190,68 @@ if ( $singleheader )
Pop-Location Pop-Location
} }
if ( $c_library )
{
$path_build = join-path $path_c_library build
$path_gen = join-path $path_c_library gen
if ( -not(Test-Path($path_build) )) {
New-Item -ItemType Directory -Path $path_build
}
if ( -not(Test-Path($path_gen) )) {
New-Item -ItemType Directory -Path $path_gen
}
$includes = @( $path_project )
$unit = join-path $path_c_library "c_library.cpp"
$executable = join-path $path_build "c_library.exe"
$compiler_args = @()
$compiler_args += ( $flag_define + 'GEN_TIME' )
$linker_args = @(
$flag_link_win_subsystem_console
)
build-simple $path_build $includes $compiler_args $linker_args $unit $executable
Push-Location $path_c_library
if ( Test-Path( $executable ) ) {
write-host "`nRunning c_library generator"
$time_taken = Measure-Command { & $executable
| ForEach-Object {
write-host `t $_ -ForegroundColor Green
}
}
write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms"
}
Pop-Location
$unit = join-path $path_c_library "gen.c"
$executable = join-path $path_build "gen_c_library_test.exe"
if ($vendor -eq "clang") {
$compiler_args += "-x"
$compiler_args += "c"
} elseif ($vendor -eq "msvc") {
$compiler_args += "/TC"
}
build-simple $path_build $includes $compiler_args $linker_args $unit $executable
Push-Location $path_c_library
if ( Test-Path( $executable ) ) {
write-host "`nRunning c_library test"
$time_taken = Measure-Command { & $executable
| ForEach-Object {
write-host `t $_ -ForegroundColor Green
}
}
write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms"
}
Pop-Location
}
if ( $unreal ) if ( $unreal )
{ {
$path_build = join-path $path_unreal build $path_build = join-path $path_unreal build

View File

@ -0,0 +1,24 @@
__VERSION 1
// This is a example template to be used with the refactor program
// Use it to refactor the naming convention of this library to your own.
// Can be used as an aid to help use use your project's implementation if it fullfills the dependencies of this project.
// Example: Most likely have a memory and string library already, just rename the functions and make sure the args are the same.
// Program: https://github.com/Ed94/refactor
// NOTE: Due to the current limitations of the program, not every symbol in the library can be renamed.
// This is due to the program not actually parsing C/C++.
// not : Ignore
// include : #includes
// word : Alphanumeric or underscore
// namespace : Prefix search and replace (c-namspaces).
// regex : Unavailable in __VERSION 1.
// Precedence (highest to lowest):
// word, namespace, regex
// Gen Macro namespace
// namespace GEN_, new_namespace_
// TODO(Ed): This will be large as nearly all symbols will need to optionally support getting prefixed with gen_ or something else the user wants.

View File