mirror of
https://github.com/Ed94/gencpp.git
synced 2025-07-01 03:11:03 -07:00
Compare commits
39 Commits
v0.19-Alph
...
16b8a3a164
Author | SHA1 | Date | |
---|---|---|---|
16b8a3a164 | |||
5b0079fb0c | |||
9321a04ebc | |||
9b68791e38 | |||
2dcc968c39 | |||
c38b077c37 | |||
f9b5029e64 | |||
2b24511f7d | |||
5cd69e1742 | |||
007bfa0cb0 | |||
37c33ffb3e | |||
937235b776 | |||
f9c21ebc04 | |||
fec709cc76 | |||
80cb3f4eca | |||
9e88cb8724 | |||
f61c1c560d | |||
8ef982003a | |||
31691b1466 | |||
ed0c0422ad | |||
e5acac1d18 | |||
c7b072266f | |||
a96d03eaed | |||
0b4ccac8f9 | |||
31a3609b28 | |||
fbdb870986 | |||
6d04165b96 | |||
cc245cc263 | |||
06deb1e836 | |||
5527a27f7b | |||
a67fdef20a | |||
056a5863b8 | |||
79eb5f1f76 | |||
c6cb583518 | |||
34eec66f35 | |||
4137ebfbd8 | |||
5958dd2055 | |||
163ad0a511 | |||
e3c2a577ba |
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||||
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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
398
gen_c_library/c_library.cpp
Normal 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
|
||||||
|
}
|
295
gen_c_library/components/containers.array.hpp
Normal file
295
gen_c_library/components/containers.array.hpp
Normal 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_
|
354
gen_c_library/components/containers.hashtable.hpp
Normal file
354
gen_c_library/components/containers.hashtable.hpp
Normal 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
|
||||||
|
));
|
||||||
|
}
|
14
gen_c_library/components/header_start.hpp
Normal file
14
gen_c_library/components/header_start.hpp
Normal 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
|
122
gen_c_library/components/memory.fixed_arena.hpp
Normal file
122
gen_c_library/components/memory.fixed_arena.hpp
Normal 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;
|
||||||
|
}
|
72
gen_c_library/components/misc.hpp
Normal file
72
gen_c_library/components/misc.hpp
Normal 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
7
gen_c_library/gen.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#define GEN_IMPLEMENTATION
|
||||||
|
#include "gen/gen.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// init();
|
||||||
|
}
|
@ -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.
|
@ -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
|
|
||||||
|
|
@ -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"
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
23
project/auxillary/gen_template.hpp
Normal file
23
project/auxillary/gen_template.hpp
Normal 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 );
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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.
|
|
||||||
static Code Invalid;
|
|
||||||
# pragma endregion Statics
|
|
||||||
|
|
||||||
# define Using_Code( Typename ) \
|
# define Using_Code( Typename ) \
|
||||||
char const* debug_str(); \
|
char const* debug_str() { return GEN_NS debug_str(* this); } \
|
||||||
Code duplicate(); \
|
Code duplicate() { return GEN_NS duplicate(* this); } \
|
||||||
bool is_equal( Code other ); \
|
bool is_equal( Code other ) { return GEN_NS is_equal(* this, other); } \
|
||||||
bool is_valid(); \
|
bool is_body() { return GEN_NS is_body(* this); } \
|
||||||
void set_global(); \
|
bool is_valid() { return GEN_NS is_valid(* this); } \
|
||||||
String to_string(); \
|
void set_global() { return GEN_NS set_global(* this); }
|
||||||
|
|
||||||
|
# define Using_CodeOps( Typename ) \
|
||||||
Typename& operator = ( AST* other ); \
|
Typename& operator = ( AST* other ); \
|
||||||
Typename& operator = ( Code other ); \
|
Typename& operator = ( Code other ); \
|
||||||
bool operator ==( Code other ); \
|
bool operator ==( Code other ) { return (AST*)ast == other.ast; } \
|
||||||
bool operator !=( Code other ); \
|
bool operator !=( Code other ) { return (AST*)ast != other.ast; } \
|
||||||
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.
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -377,6 +417,7 @@ struct AST
|
|||||||
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.
|
||||||
|
@ -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
@ -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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( 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();
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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;
|
||||||
}
|
}
|
||||||
|
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 );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( String& result );
|
void to_string_fwd( String& result );
|
||||||
void to_string_class_def( String& result );
|
void to_string_class_def( String& result );
|
||||||
void to_string_class_fwd( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_def( String& result );
|
void to_string_def( String& result );
|
||||||
void to_string_fwd( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string_if( String& result );
|
void to_string_if( String& result );
|
||||||
void to_string_ifdef( String& result );
|
void to_string_ifdef( String& result );
|
||||||
void to_string_ifndef( String& result );
|
void to_string_ifndef( String& result );
|
||||||
void to_string_elif( String& result );
|
void to_string_elif( String& result );
|
||||||
void to_string_else( String& result );
|
void to_string_else( String& result );
|
||||||
void to_string_endif( 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,6 +768,7 @@ struct CodeStmt
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt );
|
Using_Code( CodeStmt );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -649,6 +781,7 @@ struct CodeStmt_Break
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Break );
|
Using_Code( CodeStmt_Break );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -661,6 +794,7 @@ struct CodeStmt_Case
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Case );
|
Using_Code( CodeStmt_Case );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -673,6 +807,7 @@ struct CodeStmt_Continue
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Continue );
|
Using_Code( CodeStmt_Continue );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -685,6 +820,7 @@ struct CodeStmt_Decl
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Decl );
|
Using_Code( CodeStmt_Decl );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -697,6 +833,7 @@ struct CodeStmt_Do
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Do );
|
Using_Code( CodeStmt_Do );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -709,6 +846,7 @@ struct CodeStmt_Expr
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Expr );
|
Using_Code( CodeStmt_Expr );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -721,6 +859,7 @@ struct CodeStmt_Else
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Else );
|
Using_Code( CodeStmt_Else );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -733,6 +872,7 @@ struct CodeStmt_If
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_If );
|
Using_Code( CodeStmt_If );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -745,6 +885,7 @@ struct CodeStmt_For
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_For );
|
Using_Code( CodeStmt_For );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -757,6 +898,7 @@ struct CodeStmt_Goto
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Goto );
|
Using_Code( CodeStmt_Goto );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -769,6 +911,7 @@ struct CodeStmt_Label
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Label );
|
Using_Code( CodeStmt_Label );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -781,6 +924,7 @@ struct CodeStmt_Switch
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_Switch );
|
Using_Code( CodeStmt_Switch );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -793,6 +937,7 @@ struct CodeStmt_While
|
|||||||
{
|
{
|
||||||
Using_Code( CodeStmt_While );
|
Using_Code( CodeStmt_While );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
|
|
||||||
AST* raw();
|
AST* raw();
|
||||||
@ -804,10 +949,14 @@ struct CodeStmt_While
|
|||||||
|
|
||||||
struct CodeTemplate
|
struct CodeTemplate
|
||||||
{
|
{
|
||||||
|
#if GEN_SUPPORT_CPP_MEMBER_FEATURES || 1
|
||||||
Using_Code( CodeTemplate );
|
Using_Code( CodeTemplate );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
void to_string( String& result );
|
||||||
void to_string_ns( 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 );
|
||||||
|
|
||||||
|
String to_string();
|
||||||
void to_string( String& result );
|
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
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 );
|
||||||
@ -57,8 +57,8 @@ CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = N
|
|||||||
|
|
||||||
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 );
|
||||||
|
@ -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();
|
||||||
|
@ -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
@ -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
@ -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;
|
|
||||||
|
@ -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
|
||||||
|
@ -13,26 +13,118 @@ template<class TType, usize Size> struct RemoveConst<const TType[Size]> { typede
|
|||||||
template<class TType>
|
template<class TType>
|
||||||
using TRemoveConst = typename RemoveConst<TType>::Type;
|
using TRemoveConst = typename RemoveConst<TType>::Type;
|
||||||
|
|
||||||
template<class Type>
|
#pragma region Array
|
||||||
struct Array
|
#define Array(Type) Array<Type>
|
||||||
{
|
|
||||||
struct Header
|
// #define array_init(Type, ...) array_init <Type>(__VA_ARGS__)
|
||||||
{
|
// #define array_init_reserve(Type, ...) array_init_reserve<Type>(__VA_ARGS__)
|
||||||
|
|
||||||
|
struct ArrayHeader;
|
||||||
|
|
||||||
|
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||||
|
template<class Type> struct Array;
|
||||||
|
#else
|
||||||
|
template<class Type> using Array = Type*;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
usize array_grow_formula(ssize value);
|
||||||
|
|
||||||
|
template<class Type> Array(Type) array_init (AllocatorInfo allocator);
|
||||||
|
template<class Type> Array(Type) array_init_reserve(AllocatorInfo allocator, ssize capacity);
|
||||||
|
template<class Type> bool append (Array(Type)* array, Array(Type) other);
|
||||||
|
template<class Type> bool append (Array(Type)* array, Type value);
|
||||||
|
template<class Type> bool append (Array(Type)* array, Type* items, usize item_num);
|
||||||
|
template<class Type> bool append_at (Array(Type)* array, Type item, usize idx);
|
||||||
|
template<class Type> bool append_at (Array(Type)* array, Type* items, usize item_num, usize idx);
|
||||||
|
template<class Type> Type* back (Array(Type) array);
|
||||||
|
template<class Type> void clear (Array(Type) array);
|
||||||
|
template<class Type> bool fill (Array(Type) array, usize begin, usize end, Type value);
|
||||||
|
template<class Type> void free (Array(Type)* array);
|
||||||
|
template<class Type> bool grow (Array(Type)* array, usize min_capacity);
|
||||||
|
template<class Type> usize num (Array(Type) array);
|
||||||
|
template<class Type> void pop (Array(Type) array);
|
||||||
|
template<class Type> void remove_at (Array(Type) array, usize idx);
|
||||||
|
template<class Type> bool reserve (Array(Type)* array, usize new_capacity);
|
||||||
|
template<class Type> bool resize (Array(Type)* array, usize num);
|
||||||
|
template<class Type> bool set_capacity (Array(Type)* array, usize new_capacity);
|
||||||
|
template<class Type> ArrayHeader* get_header (Array(Type) array);
|
||||||
|
|
||||||
|
struct ArrayHeader {
|
||||||
AllocatorInfo Allocator;
|
AllocatorInfo Allocator;
|
||||||
usize Capacity;
|
usize Capacity;
|
||||||
usize Num;
|
usize Num;
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||||
Array init( AllocatorInfo allocator )
|
template<class Type>
|
||||||
|
struct Array
|
||||||
{
|
{
|
||||||
return init_reserve( allocator, grow_formula(0) );
|
Type* Data;
|
||||||
|
|
||||||
|
#pragma region Member Mapping
|
||||||
|
forceinline static Array init(AllocatorInfo allocator) { return GEN_NS array_init<Type>(allocator); }
|
||||||
|
forceinline static Array init_reserve(AllocatorInfo allocator, ssize capacity) { return GEN_NS array_init_reserve<Type>(allocator, capacity); }
|
||||||
|
forceinline static usize grow_formula(ssize value) { return GEN_NS array_grow_formula<Type>(value); }
|
||||||
|
|
||||||
|
forceinline bool append(Array other) { return GEN_NS append<Type>(this, other); }
|
||||||
|
forceinline bool append(Type value) { return GEN_NS append<Type>(this, value); }
|
||||||
|
forceinline bool append(Type* items, usize item_num) { return GEN_NS append<Type>(this, items, item_num); }
|
||||||
|
forceinline bool append_at(Type item, usize idx) { return GEN_NS append_at<Type>(this, item, idx); }
|
||||||
|
forceinline bool append_at(Type* items, usize item_num, usize idx) { return GEN_NS append_at<Type>(this, items, item_num, idx); }
|
||||||
|
forceinline Type* back() { return GEN_NS back<Type>(* this); }
|
||||||
|
forceinline void clear() { GEN_NS clear<Type>(* this); }
|
||||||
|
forceinline bool fill(usize begin, usize end, Type value) { return GEN_NS fill<Type>(* this, begin, end, value); }
|
||||||
|
forceinline void free() { GEN_NS free<Type>(this); }
|
||||||
|
forceinline ArrayHeader* get_header() { return GEN_NS get_header<Type>(* this); }
|
||||||
|
forceinline bool grow(usize min_capacity) { return GEN_NS grow<Type>(this, min_capacity); }
|
||||||
|
forceinline usize num() { return GEN_NS num<Type>(*this); }
|
||||||
|
forceinline void pop() { GEN_NS pop<Type>(* this); }
|
||||||
|
forceinline void remove_at(usize idx) { GEN_NS remove_at<Type>(* this, idx); }
|
||||||
|
forceinline bool reserve(usize new_capacity) { return GEN_NS reserve<Type>(this, new_capacity); }
|
||||||
|
forceinline bool resize(usize num) { return GEN_NS resize<Type>(this, num); }
|
||||||
|
forceinline bool set_capacity(usize new_capacity) { return GEN_NS set_capacity<Type>(this, new_capacity); }
|
||||||
|
#pragma endregion Member Mapping
|
||||||
|
|
||||||
|
forceinline operator Type*() { return Data; }
|
||||||
|
forceinline operator Type const*() const { return Data; }
|
||||||
|
forceinline Type* begin() { return Data; }
|
||||||
|
forceinline Type* end() { return Data + get_header()->Num; }
|
||||||
|
|
||||||
|
forceinline Type& operator[](ssize index) { return Data[index]; }
|
||||||
|
forceinline Type const& operator[](ssize index) const { return Data[index]; }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GEN_SUPPORT_CPP_REFERENCES
|
||||||
|
template<class Type> bool append(Array<Type>& array, Array<Type> other) { return GEN_NS append( & array, other ); }
|
||||||
|
template<class Type> bool append(Array<Type>& array, Type value) { return GEN_NS append( & array, value ); }
|
||||||
|
template<class Type> bool append(Array<Type>& array, Type* items, usize item_num) { return GEN_NS append( & array, items, item_num ); }
|
||||||
|
template<class Type> bool append_at(Array<Type>& array, Type item, usize idx) { return GEN_NS append_at( & array, item, idx ); }
|
||||||
|
template<class Type> bool append_at(Array<Type>& array, Type* items, usize item_num, usize idx) { return GEN_NS append_at( & array, items, item_num, idx ); }
|
||||||
|
template<class Type> void free(Array<Type>& array) { return GEN_NS free( & array ); }
|
||||||
|
template<class Type> bool grow(Array<Type>& array, usize min_capacity) { return GEN_NS grow( & array, min_capacity); }
|
||||||
|
template<class Type> bool reserve(Array<Type>& array, usize new_capacity) { return GEN_NS reserve( & array, new_capacity); }
|
||||||
|
template<class Type> bool resize(Array<Type>& array, usize num) { return GEN_NS resize( & array, num); }
|
||||||
|
template<class Type> bool set_capacity(Array<Type>& array, usize new_capacity) { return GEN_NS set_capacity( & array, new_capacity); }
|
||||||
|
|
||||||
|
template<class Type> forceinline Type* begin(Array<Type>& array) { return array; }
|
||||||
|
template<class Type> forceinline Type* end(Array<Type>& array) { return array + get_header(array)->Num; }
|
||||||
|
template<class Type> forceinline Type* next(Array<Type>& array, Type* entry) { return entry + 1; }
|
||||||
|
#else
|
||||||
|
template<class Type> forceinline Type* begin(Array<Type> array) { return array; }
|
||||||
|
template<class Type> forceinline Type* end(Array<Type> array) { return array + get_header(array)->Num; }
|
||||||
|
template<class Type> forceinline Type* next(Array<Type> array, Type* entry) { return entry + 1; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class Type> inline
|
||||||
|
Array<Type> array_init(AllocatorInfo allocator) {
|
||||||
|
return array_init_reserve<Type>(allocator, array_grow_formula(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
template<class Type> inline
|
||||||
Array init_reserve( AllocatorInfo allocator, ssize capacity )
|
Array<Type> array_init_reserve(AllocatorInfo allocator, ssize capacity)
|
||||||
{
|
{
|
||||||
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) * capacity ));
|
ArrayHeader* header = rcast(ArrayHeader*, alloc(allocator, sizeof(ArrayHeader) + sizeof(Type) * capacity));
|
||||||
|
|
||||||
if (header == nullptr)
|
if (header == nullptr)
|
||||||
return {nullptr};
|
return {nullptr};
|
||||||
@ -44,98 +136,101 @@ struct Array
|
|||||||
return {rcast(Type*, header + 1)};
|
return {rcast(Type*, header + 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
usize array_grow_formula(ssize value) {
|
||||||
usize grow_formula( usize value )
|
|
||||||
{
|
|
||||||
return 2 * value + 8;
|
return 2 * value + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append( Array other )
|
template<class Type> inline
|
||||||
{
|
bool append(Array<Type>* array, Array<Type> other) {
|
||||||
return append( other, other.num() );
|
return append(array, other, num(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append( Type value )
|
template<class Type> inline
|
||||||
|
bool append(Array<Type>* array, Type value)
|
||||||
{
|
{
|
||||||
Header* header = get_header();
|
ArrayHeader* header = get_header(* array);
|
||||||
|
|
||||||
if (header->Num == header->Capacity)
|
if (header->Num == header->Capacity)
|
||||||
{
|
{
|
||||||
if ( ! grow( header->Capacity ))
|
if (!grow(array, header->Capacity))
|
||||||
return false;
|
return false;
|
||||||
|
header = get_header(* array);
|
||||||
header = get_header();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Data[ header->Num ] = value;
|
(*array)[ header->Num] = value;
|
||||||
header->Num++;
|
header->Num++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append( Type* items, usize item_num )
|
template<class Type> inline
|
||||||
|
bool append(Array<Type>* array, Type* items, usize item_num)
|
||||||
{
|
{
|
||||||
Header* header = get_header();
|
ArrayHeader* header = get_header(array);
|
||||||
|
|
||||||
if (header->Num + item_num > header->Capacity)
|
if (header->Num + item_num > header->Capacity)
|
||||||
{
|
{
|
||||||
if ( ! grow( header->Capacity + item_num ))
|
if (!grow(array, header->Capacity + item_num))
|
||||||
return false;
|
return false;
|
||||||
|
header = get_header(array);
|
||||||
header = get_header();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_copy( Data + header->Num, items, item_num * sizeof(Type) );
|
mem_copy(array.Data + header->Num, items, item_num * sizeof(Type));
|
||||||
header->Num += item_num;
|
header->Num += item_num;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append_at( Type item, usize idx )
|
template<class Type> inline
|
||||||
|
bool append_at(Array<Type>* array, Type item, usize idx)
|
||||||
{
|
{
|
||||||
Header* header = get_header();
|
ArrayHeader* header = get_header(* array);
|
||||||
|
|
||||||
if ( idx >= header->Num )
|
ssize slot = idx;
|
||||||
idx = header->Num - 1;
|
if (slot >= header->Num)
|
||||||
|
slot = header->Num - 1;
|
||||||
|
|
||||||
if ( idx < 0 )
|
if (slot < 0)
|
||||||
idx = 0;
|
slot = 0;
|
||||||
|
|
||||||
if (header->Capacity < header->Num + 1)
|
if (header->Capacity < header->Num + 1)
|
||||||
{
|
{
|
||||||
if ( ! grow( header->Capacity + 1 ))
|
if ( ! grow(array, header->Capacity + 1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
header = get_header();
|
header = get_header(* array);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* target = Data + idx;
|
Type* target = &(*array)[slot];
|
||||||
|
|
||||||
mem_move( target + 1, target, (header->Num - idx) * sizeof(Type) );
|
mem_move(target + 1, target, (header->Num - slot) * sizeof(Type));
|
||||||
header->Num++;
|
header->Num++;
|
||||||
|
|
||||||
|
header = get_header(* array);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append_at( Type* items, usize item_num, usize idx )
|
template<class Type> inline
|
||||||
|
bool append_at(Array<Type>* array, Type* items, usize item_num, usize idx)
|
||||||
{
|
{
|
||||||
Header* header = get_header();
|
ArrayHeader* header = get_header(array);
|
||||||
|
|
||||||
if (idx >= header->Num)
|
if (idx >= header->Num)
|
||||||
{
|
{
|
||||||
return append( items, item_num );
|
return append(array, items, item_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item_num > header->Capacity)
|
if (item_num > header->Capacity)
|
||||||
{
|
{
|
||||||
if ( ! grow( header->Capacity + item_num ) )
|
if (! grow(array, header->Capacity + item_num))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
header = get_header();
|
header = get_header(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* target = Data + idx + item_num;
|
Type* target = array.Data + idx + item_num;
|
||||||
Type* src = Data + idx;
|
Type* src = array.Data + idx;
|
||||||
|
|
||||||
mem_move(target, src, (header->Num - idx) * sizeof(Type));
|
mem_move(target, src, (header->Num - idx) * sizeof(Type));
|
||||||
mem_copy(src, items, item_num * sizeof(Type));
|
mem_copy(src, items, item_num * sizeof(Type));
|
||||||
@ -144,268 +239,304 @@ struct Array
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type& back( void )
|
template<class Type> inline
|
||||||
|
Type* back(Array<Type>* array)
|
||||||
{
|
{
|
||||||
Header& header = * get_header();
|
GEN_ASSERT(array != nullptr);
|
||||||
return Data[ header.Num - 1 ];
|
|
||||||
|
ArrayHeader* header = get_header(* array);
|
||||||
|
if (header->Num <= 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return & (*array)[header->Num - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear( void )
|
template<class Type> inline
|
||||||
{
|
void clear(Array<Type> array) {
|
||||||
Header& header = * get_header();
|
ArrayHeader* header = get_header(array);
|
||||||
header.Num = 0;
|
header->Num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fill( usize begin, usize end, Type value )
|
template<class Type> inline
|
||||||
|
bool fill(Array<Type> array, usize begin, usize end, Type value)
|
||||||
{
|
{
|
||||||
Header& header = * get_header();
|
ArrayHeader* header = get_header(array);
|
||||||
|
|
||||||
if ( begin < 0 || end > header.Num )
|
if (begin < 0 || end > header->Num)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ssize idx = ssize(begin); idx < ssize(end); idx++)
|
for (ssize idx = ssize(begin); idx < ssize(end); idx++)
|
||||||
{
|
{
|
||||||
Data[ idx ] = value;
|
array[idx] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free( void )
|
template<class Type> inline
|
||||||
{
|
void free(Array<Type>* array) {
|
||||||
Header& header = * get_header();
|
GEN_ASSERT(array != nullptr);
|
||||||
gen::free( header.Allocator, &header );
|
ArrayHeader* header = get_header(* array);
|
||||||
Data = nullptr;
|
GEN_NS free(header->Allocator, header);
|
||||||
|
Type** Data = (Type**)array;
|
||||||
|
*Data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Header* get_header( void )
|
template<class Type> forceinline
|
||||||
{
|
ArrayHeader* get_header(Array<Type> array) {
|
||||||
|
Type* Data = array;
|
||||||
|
|
||||||
using NonConstType = TRemoveConst<Type>;
|
using NonConstType = TRemoveConst<Type>;
|
||||||
return rcast( Header*, const_cast<NonConstType*>(Data) ) - 1 ;
|
return rcast(ArrayHeader*, const_cast<NonConstType*>(Data)) - 1;
|
||||||
}
|
}
|
||||||
|
template<class Type> inline
|
||||||
bool grow( usize min_capacity )
|
bool grow(Array<Type>* array, usize min_capacity)
|
||||||
{
|
{
|
||||||
Header& header = * get_header();
|
ArrayHeader* header = get_header(* array);
|
||||||
usize new_capacity = grow_formula( header.Capacity );
|
usize new_capacity = array_grow_formula(header->Capacity);
|
||||||
|
|
||||||
if (new_capacity < min_capacity)
|
if (new_capacity < min_capacity)
|
||||||
new_capacity = min_capacity;
|
new_capacity = min_capacity;
|
||||||
|
|
||||||
return set_capacity( new_capacity );
|
return set_capacity(array, new_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
usize num( void )
|
template<class Type> inline
|
||||||
{
|
usize num(Array<Type> array) {
|
||||||
return get_header()->Num;
|
return get_header(array)->Num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop( void )
|
template<class Type> inline
|
||||||
{
|
void pop(Array<Type> array) {
|
||||||
Header& header = * get_header();
|
ArrayHeader* header = get_header(array);
|
||||||
|
GEN_ASSERT(header->Num > 0);
|
||||||
GEN_ASSERT( header.Num > 0 );
|
|
||||||
header.Num--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_at( usize idx )
|
|
||||||
{
|
|
||||||
Header* header = get_header();
|
|
||||||
GEN_ASSERT( idx < header->Num );
|
|
||||||
|
|
||||||
mem_move( header + idx, header + idx + 1, sizeof( Type ) * ( header->Num - idx - 1 ) );
|
|
||||||
header->Num--;
|
header->Num--;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reserve( usize new_capacity )
|
template<class Type> inline
|
||||||
|
void remove_at(Array<Type> array, usize idx)
|
||||||
{
|
{
|
||||||
Header& header = * get_header();
|
ArrayHeader* header = get_header(array);
|
||||||
|
GEN_ASSERT(idx < header->Num);
|
||||||
|
|
||||||
if ( header.Capacity < new_capacity )
|
mem_move(array + idx, array + idx + 1, sizeof(Type) * (header->Num - idx - 1));
|
||||||
return set_capacity( new_capacity );
|
header->Num--;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type> inline
|
||||||
|
bool reserve(Array<Type>* array, usize new_capacity)
|
||||||
|
{
|
||||||
|
ArrayHeader* header = get_header(array);
|
||||||
|
|
||||||
|
if (header->Capacity < new_capacity)
|
||||||
|
return set_capacity(array, new_capacity);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resize( usize num )
|
template<class Type> inline
|
||||||
|
bool resize(Array<Type>* array, usize num)
|
||||||
{
|
{
|
||||||
Header* header = get_header();
|
ArrayHeader* header = get_header(* array);
|
||||||
|
|
||||||
if ( header->Capacity < num )
|
if (header->Capacity < num) {
|
||||||
{
|
if (! grow( array, num))
|
||||||
if ( ! grow( num ) )
|
|
||||||
return false;
|
return false;
|
||||||
|
header = get_header(* array);
|
||||||
header = get_header();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header->Num = num;
|
header->Num = num;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_capacity( usize new_capacity )
|
template<class Type> inline
|
||||||
|
bool set_capacity(Array<Type>* array, usize new_capacity)
|
||||||
{
|
{
|
||||||
Header& header = * get_header();
|
ArrayHeader* header = get_header(* array);
|
||||||
|
|
||||||
if ( new_capacity == header.Capacity )
|
if (new_capacity == header->Capacity)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ( new_capacity < header.Num )
|
if (new_capacity < header->Num)
|
||||||
{
|
{
|
||||||
// Already have the memory, mine as well keep it.
|
header->Num = new_capacity;
|
||||||
header.Num = new_capacity;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize size = sizeof( Header ) + sizeof( Type ) * new_capacity;
|
ssize size = sizeof(ArrayHeader) + sizeof(Type) * new_capacity;
|
||||||
Header* new_header = rcast( Header*, alloc( header.Allocator, size ) );
|
ArrayHeader* new_header = rcast(ArrayHeader*, alloc(header->Allocator, size));
|
||||||
|
|
||||||
if (new_header == nullptr)
|
if (new_header == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mem_move( new_header, &header, sizeof( Header ) + sizeof( Type ) * header.Num );
|
mem_move(new_header, header, sizeof(ArrayHeader) + sizeof(Type) * header->Num);
|
||||||
|
|
||||||
new_header->Capacity = new_capacity;
|
new_header->Capacity = new_capacity;
|
||||||
|
|
||||||
gen::free( header.Allocator, &header );
|
GEN_NS free(header->Allocator, header);
|
||||||
|
|
||||||
Data = rcast( Type*, new_header + 1);
|
Type** Data = (Type**)array;
|
||||||
|
* Data = rcast(Type*, new_header + 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* Data;
|
#pragma endregion Array
|
||||||
|
|
||||||
operator Type*()
|
|
||||||
{
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator Type const*() const
|
|
||||||
{
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For-range based support
|
|
||||||
|
|
||||||
Type* begin()
|
|
||||||
{
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type* end()
|
|
||||||
{
|
|
||||||
return Data + get_header()->Num;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO(Ed) : This thing needs ALOT of work.
|
// TODO(Ed) : This thing needs ALOT of work.
|
||||||
|
|
||||||
template<typename Type>
|
#pragma region HashTable
|
||||||
struct HashTable
|
template<class Type> struct HashTable;
|
||||||
{
|
|
||||||
struct FindResult
|
struct HashTableFindResult {
|
||||||
{
|
|
||||||
ssize HashIndex;
|
ssize HashIndex;
|
||||||
ssize PrevIndex;
|
ssize PrevIndex;
|
||||||
ssize EntryIndex;
|
ssize EntryIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Entry
|
template<class Type>
|
||||||
{
|
struct HashTableEntry {
|
||||||
u64 Key;
|
u64 Key;
|
||||||
ssize Next;
|
ssize Next;
|
||||||
Type Value;
|
Type Value;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr f32 CriticalLoadScale = 0.7f;
|
#define HashTableEntry(Type) HashTableEntry<Type>
|
||||||
|
|
||||||
static
|
template<class Type> HashTable<Type> hashtable_init(AllocatorInfo allocator);
|
||||||
HashTable init( AllocatorInfo allocator )
|
template<class Type> HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num);
|
||||||
|
template<class Type> void clear (HashTable<Type> table);
|
||||||
|
template<class Type> void destroy (HashTable<Type>* table);
|
||||||
|
template<class Type> Type* get (HashTable<Type> table, u64 key);
|
||||||
|
template<class Type> void grow (HashTable<Type>* table);
|
||||||
|
template<class Type> void rehash (HashTable<Type>* table, ssize new_num);
|
||||||
|
template<class Type> void rehash_fast (HashTable<Type> table);
|
||||||
|
template<class Type> void remove (HashTable<Type> table, u64 key);
|
||||||
|
template<class Type> void remove_entry (HashTable<Type> table, ssize idx);
|
||||||
|
template<class Type> void set (HashTable<Type>* table, u64 key, Type value);
|
||||||
|
template<class Type> ssize slot (HashTable<Type> table, u64 key);
|
||||||
|
template<class Type> ssize add_entry (HashTable<Type>* table, u64 key);
|
||||||
|
template<class Type> HashTableFindResult find (HashTable<Type> table, u64 key);
|
||||||
|
template<class Type> bool full (HashTable<Type> table);
|
||||||
|
template<class Type> void map (HashTable<Type> table, void (*map_proc)(u64 key, Type value));
|
||||||
|
template<class Type> void map_mut (HashTable<Type> table, void (*map_proc)(u64 key, Type* value));
|
||||||
|
|
||||||
|
static constexpr f32 HashTable_CriticalLoadScale = 0.7f;
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
struct HashTable
|
||||||
{
|
{
|
||||||
HashTable<Type> result = init_reserve(allocator, 8);
|
Array<ssize> Hashes;
|
||||||
|
Array<HashTableEntry<Type>> Entries;
|
||||||
|
|
||||||
|
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||||
|
#pragma region Member Mapping
|
||||||
|
forceinline static HashTable init(AllocatorInfo allocator) { return GEN_NS hashtable_init<Type>(allocator); }
|
||||||
|
forceinline static HashTable init_reserve(AllocatorInfo allocator, usize num) { return GEN_NS hashtable_init_reserve<Type>(allocator, num); }
|
||||||
|
|
||||||
|
forceinline void clear() { GEN_NS clear<Type>(*this); }
|
||||||
|
forceinline void destroy() { GEN_NS destroy<Type>(*this); }
|
||||||
|
forceinline Type* get(u64 key) { return GEN_NS get<Type>(*this, key); }
|
||||||
|
forceinline void grow() { GEN_NS grow<Type>(*this); }
|
||||||
|
forceinline void rehash(ssize new_num) { GEN_NS rehash<Type>(*this, new_num); }
|
||||||
|
forceinline void rehash_fast() { GEN_NS rehash_fast<Type>(*this); }
|
||||||
|
forceinline void remove(u64 key) { GEN_NS remove<Type>(*this, key); }
|
||||||
|
forceinline void remove_entry(ssize idx) { GEN_NS remove_entry<Type>(*this, idx); }
|
||||||
|
forceinline void set(u64 key, Type value) { GEN_NS set<Type>(*this, key, value); }
|
||||||
|
forceinline ssize slot(u64 key) { return GEN_NS slot<Type>(*this, key); }
|
||||||
|
forceinline void map(void (*proc)(u64, Type)) { GEN_NS map<Type>(*this, proc); }
|
||||||
|
forceinline void map_mut(void (*proc)(u64, Type*)) { GEN_NS map_mut<Type>(*this, proc); }
|
||||||
|
#pragma endregion Member Mapping
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if GEN_SUPPORT_CPP_REFERENCES
|
||||||
|
template<class Type> void destroy (HashTable<Type>& table) { destroy(& table); }
|
||||||
|
template<class Type> void grow (HashTable<Type>& table) { grow(& table); }
|
||||||
|
template<class Type> void rehash (HashTable<Type>& table, ssize new_num) { rehash(& table, new_num); }
|
||||||
|
template<class Type> void set (HashTable<Type>& table, u64 key, Type value) { set(& table, key, value); }
|
||||||
|
template<class Type> ssize add_entry(HashTable<Type>& table, u64 key) { add_entry(& table, key); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename Type> inline
|
||||||
|
HashTable<Type> hashtable_init(AllocatorInfo allocator) {
|
||||||
|
HashTable<Type> result = hashtable_init_reserve<Type>(allocator, 8);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
template<typename Type> inline
|
||||||
HashTable init_reserve( AllocatorInfo allocator, usize num )
|
HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num)
|
||||||
{
|
{
|
||||||
HashTable<Type> result = { { nullptr }, { nullptr } };
|
HashTable<Type> result = { { nullptr }, { nullptr } };
|
||||||
|
|
||||||
result.Hashes = Array<ssize>::init_reserve( allocator, num );
|
result.Hashes = array_init_reserve<ssize>(allocator, num);
|
||||||
result.Hashes.get_header()->Num = num;
|
get_header(result.Hashes)->Num = num;
|
||||||
result.Hashes.resize( num );
|
resize(& result.Hashes, num);
|
||||||
result.Hashes.fill( 0, num, -1);
|
fill<ssize>(result.Hashes, 0, num, -1);
|
||||||
|
|
||||||
result.Entries = Array<Entry>::init_reserve( allocator, num );
|
result.Entries = array_init_reserve<HashTableEntry<Type>>(allocator, num);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear( void )
|
template<typename Type> inline
|
||||||
{
|
void clear(HashTable<Type> table) {
|
||||||
Entries.clear();
|
clear(table.Entries);
|
||||||
Hashes.fill( 0, Hashes.num(), -1);
|
fill<ssize>(table.Hashes, 0, num(table.Hashes), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy( void )
|
template<typename Type> inline
|
||||||
{
|
void destroy(HashTable<Type>* table) {
|
||||||
if ( Hashes && Hashes.get_header()->Capacity )
|
if (table->Hashes && get_header(table->Hashes)->Capacity) {
|
||||||
{
|
free(& table->Hashes);
|
||||||
Hashes.free();
|
free(& table->Entries);
|
||||||
Entries.free();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* get( u64 key )
|
template<typename Type> inline
|
||||||
{
|
Type* get(HashTable<Type> table, u64 key) {
|
||||||
ssize idx = find( key ).EntryIndex;
|
ssize idx = find(table, key).EntryIndex;
|
||||||
if (idx >= 0)
|
if (idx >= 0)
|
||||||
return & Entries[ idx ].Value;
|
return & table.Entries[idx].Value;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
using MapProc = void (*)( u64 key, Type value );
|
template<typename Type> inline
|
||||||
|
void map(HashTable<Type> table, void (*map_proc)(u64 key, Type value)) {
|
||||||
void map( MapProc map_proc )
|
|
||||||
{
|
|
||||||
GEN_ASSERT_NOT_NULL(map_proc);
|
GEN_ASSERT_NOT_NULL(map_proc);
|
||||||
|
|
||||||
for ( ssize idx = 0; idx < ssize(Entries.num()); ++idx )
|
for (ssize idx = 0; idx < ssize(num(table.Entries)); ++idx) {
|
||||||
{
|
map_proc(table.Entries[idx].Key, table.Entries[idx].Value);
|
||||||
map_proc( Entries[ idx ].Key, Entries[ idx ].Value );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using MapMutProc = void (*)( u64 key, Type* value );
|
template<typename Type> inline
|
||||||
|
void map_mut(HashTable<Type> table, void (*map_proc)(u64 key, Type* value)) {
|
||||||
void map_mut( MapMutProc map_proc )
|
|
||||||
{
|
|
||||||
GEN_ASSERT_NOT_NULL(map_proc);
|
GEN_ASSERT_NOT_NULL(map_proc);
|
||||||
|
|
||||||
for ( ssize idx = 0; idx < ssize(Entries.num()); ++idx )
|
for (ssize idx = 0; idx < ssize(num(table.Entries)); ++idx) {
|
||||||
{
|
map_proc(table.Entries[idx].Key, & table.Entries[idx].Value);
|
||||||
map_proc( Entries[ idx ].Key, & Entries[ idx ].Value );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void grow()
|
template<typename Type> inline
|
||||||
{
|
void grow(HashTable<Type>* table) {
|
||||||
ssize new_num = Array<Entry>::grow_formula( Entries.num() );
|
ssize new_num = array_grow_formula(num(table->Entries));
|
||||||
rehash( new_num );
|
rehash(table, new_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rehash( ssize new_num )
|
template<typename Type> inline
|
||||||
|
void rehash(HashTable<Type>* table, ssize new_num)
|
||||||
{
|
{
|
||||||
ssize last_added_index;
|
ssize last_added_index;
|
||||||
|
HashTable<Type> new_ht = hashtable_init_reserve<Type>(get_header(table->Hashes)->Allocator, new_num);
|
||||||
|
|
||||||
HashTable<Type> new_ht = init_reserve( Hashes.get_header()->Allocator, new_num );
|
for (ssize idx = 0; idx < ssize(num(table->Entries)); ++idx)
|
||||||
for ( ssize idx = 0; idx < ssize(Entries.num()); ++idx )
|
|
||||||
{
|
{
|
||||||
FindResult find_result;
|
HashTableFindResult find_result;
|
||||||
|
HashTableEntry<Type>& entry = table->Entries[idx];
|
||||||
|
|
||||||
Entry& entry = Entries[ idx ];
|
find_result = find(new_ht, entry.Key);
|
||||||
find_result = new_ht.find( entry.Key );
|
last_added_index = add_entry(& new_ht, entry.Key);
|
||||||
last_added_index = new_ht.add_entry( entry.Key );
|
|
||||||
|
|
||||||
if (find_result.PrevIndex < 0)
|
if (find_result.PrevIndex < 0)
|
||||||
new_ht.Hashes[find_result.HashIndex] = last_added_index;
|
new_ht.Hashes[find_result.HashIndex] = last_added_index;
|
||||||
@ -416,136 +547,149 @@ struct HashTable
|
|||||||
new_ht.Entries[last_added_index].Value = entry.Value;
|
new_ht.Entries[last_added_index].Value = entry.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy();
|
destroy(table);
|
||||||
*this = new_ht;
|
* table = new_ht;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rehash_fast()
|
template<typename Type> inline
|
||||||
|
void rehash_fast(HashTable<Type> table)
|
||||||
{
|
{
|
||||||
ssize idx;
|
ssize idx;
|
||||||
|
|
||||||
for ( idx = 0; idx < ssize(Entries.num()); idx++ )
|
for (idx = 0; idx < ssize(num(table.Entries)); idx++)
|
||||||
Entries[ idx ].Next = -1;
|
table.Entries[idx].Next = -1;
|
||||||
|
|
||||||
for ( idx = 0; idx < ssize(Hashes.num()); idx++ )
|
for (idx = 0; idx < ssize(num(table.Hashes)); idx++)
|
||||||
Hashes[ idx ] = -1;
|
table.Hashes[idx] = -1;
|
||||||
|
|
||||||
for ( idx = 0; idx < ssize(Entries.num()); idx++ )
|
for (idx = 0; idx < ssize(num(table.Entries)); idx++)
|
||||||
{
|
{
|
||||||
Entry* entry;
|
HashTableEntry<Type>* entry;
|
||||||
FindResult find_result;
|
HashTableFindResult find_result;
|
||||||
|
|
||||||
entry = & Entries[ idx ];
|
entry = &table.Entries[idx];
|
||||||
find_result = find( entry->Key );
|
find_result = find(table, entry->Key);
|
||||||
|
|
||||||
if (find_result.PrevIndex < 0)
|
if (find_result.PrevIndex < 0)
|
||||||
Hashes[ find_result.HashIndex ] = idx;
|
table.Hashes[find_result.HashIndex] = idx;
|
||||||
else
|
else
|
||||||
Entries[ find_result.PrevIndex ].Next = idx;
|
table.Entries[find_result.PrevIndex].Next = idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove( u64 key )
|
template<typename Type> inline
|
||||||
{
|
void remove(HashTable<Type> table, u64 key) {
|
||||||
FindResult find_result = find( key);
|
HashTableFindResult find_result = find(table, key);
|
||||||
|
|
||||||
if ( find_result.EntryIndex >= 0 )
|
if (find_result.EntryIndex >= 0) {
|
||||||
{
|
remove_at(table.Entries, find_result.EntryIndex);
|
||||||
Entries.remove_at( find_result.EntryIndex );
|
rehash_fast(table);
|
||||||
rehash_fast();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_entry( ssize idx )
|
template<typename Type> inline
|
||||||
{
|
void remove_entry(HashTable<Type> table, ssize idx) {
|
||||||
Entries.remove_at( idx );
|
remove_at(table.Entries, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set( u64 key, Type value )
|
template<typename Type> inline
|
||||||
|
void set(HashTable<Type>* table, u64 key, Type value)
|
||||||
{
|
{
|
||||||
ssize idx;
|
ssize idx;
|
||||||
FindResult find_result;
|
HashTableFindResult find_result;
|
||||||
|
|
||||||
if ( full() )
|
if (full(* table))
|
||||||
grow();
|
grow(table);
|
||||||
|
|
||||||
find_result = find( key );
|
find_result = find(* table, key);
|
||||||
if ( find_result.EntryIndex >= 0 )
|
if (find_result.EntryIndex >= 0) {
|
||||||
{
|
|
||||||
idx = find_result.EntryIndex;
|
idx = find_result.EntryIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
idx = add_entry( key );
|
idx = add_entry(table, key);
|
||||||
|
|
||||||
if ( find_result.PrevIndex >= 0 )
|
if (find_result.PrevIndex >= 0) {
|
||||||
{
|
table->Entries[find_result.PrevIndex].Next = idx;
|
||||||
Entries[ find_result.PrevIndex ].Next = idx;
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
table->Hashes[find_result.HashIndex] = idx;
|
||||||
Hashes[ find_result.HashIndex ] = idx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entries[ idx ].Value = value;
|
table->Entries[idx].Value = value;
|
||||||
|
|
||||||
if ( full() )
|
if (full(* table))
|
||||||
grow();
|
grow(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize slot( u64 key )
|
template<typename Type> inline
|
||||||
{
|
ssize slot(HashTable<Type> table, u64 key) {
|
||||||
for ( ssize idx = 0; idx < ssize(Hashes.num()); ++idx )
|
for (ssize idx = 0; idx < ssize(num(table.Hashes)); ++idx)
|
||||||
if ( Hashes[ idx ] == key )
|
if (table.Hashes[idx] == key)
|
||||||
return idx;
|
return idx;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array< ssize> Hashes;
|
template<typename Type> inline
|
||||||
Array< Entry> Entries;
|
ssize add_entry(HashTable<Type>* table, u64 key) {
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
ssize add_entry( u64 key )
|
|
||||||
{
|
|
||||||
ssize idx;
|
ssize idx;
|
||||||
Entry entry = { key, -1 };
|
HashTableEntry<Type> entry = { key, -1 };
|
||||||
|
|
||||||
idx = Entries.num();
|
idx = num(table->Entries);
|
||||||
Entries.append( entry );
|
append( & table->Entries, entry);
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
FindResult find( u64 key )
|
template<typename Type> inline
|
||||||
|
HashTableFindResult find(HashTable<Type> table, u64 key)
|
||||||
{
|
{
|
||||||
FindResult result = { -1, -1, -1 };
|
HashTableFindResult result = { -1, -1, -1 };
|
||||||
|
|
||||||
if ( Hashes.num() > 0 )
|
if (num(table.Hashes) > 0)
|
||||||
{
|
{
|
||||||
result.HashIndex = key % Hashes.num();
|
result.HashIndex = key % num(table.Hashes);
|
||||||
result.EntryIndex = Hashes[ result.HashIndex ];
|
result.EntryIndex = table.Hashes[result.HashIndex];
|
||||||
|
|
||||||
while (result.EntryIndex >= 0)
|
while (result.EntryIndex >= 0)
|
||||||
{
|
{
|
||||||
if ( Entries[ result.EntryIndex ].Key == key )
|
if (table.Entries[result.EntryIndex].Key == key)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
result.PrevIndex = result.EntryIndex;
|
result.PrevIndex = result.EntryIndex;
|
||||||
result.EntryIndex = Entries[ result.EntryIndex ].Next;
|
result.EntryIndex = table.Entries[result.EntryIndex].Next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 full()
|
template<typename Type> inline
|
||||||
{
|
bool full(HashTable<Type> table) {
|
||||||
usize critical_load = usize( CriticalLoadScale * f32(Hashes.num()) );
|
usize critical_load = usize(HashTable_CriticalLoadScale * f32(num(table.Hashes)));
|
||||||
b32 result = Entries.num() > critical_load;
|
b32 result = num(table.Entries) > critical_load;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
#define hashtable_init(Type, allocator) hashtable_init<Type>(allocator)
|
||||||
|
#define hashtable_init_reserve(Type, allocator, num) hashtable_init_reserve<Type>(allocator, num)
|
||||||
|
#define hashtable_clear(Type, table) clear<Type>(table)
|
||||||
|
#define hashtable_destroy(Type, table) destroy<Type>(table)
|
||||||
|
#define hashtable_get(Type, table, key) get<Type>(table, key)
|
||||||
|
#define hashtable_grow(Type, table) grow<Type>(table)
|
||||||
|
#define hashtable_rehash(Type, table, new_num) rehash<Type>(table, new_num)
|
||||||
|
#define hashtable_rehash_fast(Type, table) rehash_fast<Type>(table)
|
||||||
|
#define hashtable_remove(Type, table, key) remove<Type>(table, key)
|
||||||
|
#define hashtable_remove_entry(Type, table, idx) remove_entry<Type>(table, idx)
|
||||||
|
#define hashtable_set(Type, table, key, value) set<Type>(table, key, value)
|
||||||
|
#define hashtable_slot(Type, table, key) slot<Type>(table, key)
|
||||||
|
#define hashtable_add_entry(Type, table, key) add_entry<Type>(table, key)
|
||||||
|
#define hashtable_find(Type, table, key) find<Type>(table, key)
|
||||||
|
#define hashtable_full(Type, table) full<Type>(table)
|
||||||
|
#define hashtable_map(Type, table, map_proc) map<Type>(table, map_proc)
|
||||||
|
#define hashtable_map_mut(Type, table, map_proc) map_mut<Type>(table, map_proc)
|
||||||
|
|
||||||
|
#pragma endregion HashTable
|
||||||
|
|
||||||
#pragma endregion Containers
|
#pragma endregion Containers
|
||||||
|
@ -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 );
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
#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
|
||||||
|
|
||||||
|
|
||||||
|
#if ! GEN_C_COMPILER
|
||||||
|
# ifndef cast
|
||||||
|
# define cast( type, value ) (tmpl_cast<type>( value ))
|
||||||
|
# endif
|
||||||
# ifndef ccast
|
# ifndef ccast
|
||||||
# define ccast( type, value ) ( const_cast< type >( (value) ) )
|
# define ccast( type, value ) ( const_cast< type >( (value) ) )
|
||||||
# endif
|
# endif
|
||||||
@ -35,6 +40,23 @@
|
|||||||
# ifndef scast
|
# ifndef scast
|
||||||
# define scast( type, value ) static_cast< type >( value )
|
# define scast( type, value ) static_cast< type >( value )
|
||||||
# endif
|
# 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
|
||||||
|
|
||||||
#ifndef stringize
|
#ifndef stringize
|
||||||
#define stringize_va( ... ) #__VA_ARGS__
|
#define stringize_va( ... ) #__VA_ARGS__
|
||||||
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,29 +169,96 @@ 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 );
|
||||||
|
|
||||||
|
#pragma region Arena
|
||||||
|
struct Arena;
|
||||||
|
|
||||||
|
AllocatorInfo allocator_info( Arena* arena );
|
||||||
|
|
||||||
|
// Remove static keyword and rename allocator_proc
|
||||||
|
void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags);
|
||||||
|
|
||||||
|
// Add these declarations after the Arena struct
|
||||||
|
Arena arena_init_from_allocator(AllocatorInfo backing, ssize size);
|
||||||
|
Arena arena_init_from_memory ( void* start, ssize size );
|
||||||
|
|
||||||
|
Arena init_sub (Arena* parent, ssize size);
|
||||||
|
ssize alignment_of (Arena* arena, ssize alignment);
|
||||||
|
void free (Arena* arena);
|
||||||
|
ssize size_remaining(Arena* arena, ssize alignment);
|
||||||
|
|
||||||
|
// This id is defined by Unreal for asserts
|
||||||
|
#pragma push_macro("check")
|
||||||
|
#undef check
|
||||||
|
void check(Arena* arena);
|
||||||
|
#pragma pop_macro("check")
|
||||||
|
|
||||||
struct Arena
|
struct Arena
|
||||||
{
|
{
|
||||||
static
|
AllocatorInfo Backing;
|
||||||
void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
|
void* PhysicalStart;
|
||||||
|
ssize TotalSize;
|
||||||
|
ssize TotalUsed;
|
||||||
|
ssize TempCount;
|
||||||
|
|
||||||
static
|
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||||
Arena init_from_memory( void* start, ssize size )
|
#pragma region Member Mapping
|
||||||
{
|
forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); }
|
||||||
return
|
|
||||||
|
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 },
|
{ nullptr, nullptr },
|
||||||
start,
|
start,
|
||||||
size,
|
size,
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
Arena init_from_allocator( AllocatorInfo backing, ssize size )
|
Arena arena_init_from_allocator(AllocatorInfo backing, ssize size) {
|
||||||
{
|
Arena result = {
|
||||||
Arena result =
|
|
||||||
{
|
|
||||||
backing,
|
backing,
|
||||||
alloc(backing, size),
|
alloc(backing, size),
|
||||||
size,
|
size,
|
||||||
@ -202,19 +268,21 @@ struct Arena
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
Arena init_sub( Arena& parent, ssize size )
|
Arena init_sub(Arena* parent, ssize size) {
|
||||||
{
|
GEN_ASSERT(parent != nullptr);
|
||||||
return init_from_allocator( parent.Backing, size );
|
return arena_init_from_allocator(parent->Backing, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize alignment_of( ssize alignment )
|
inline
|
||||||
|
ssize alignment_of(Arena* arena, ssize alignment)
|
||||||
{
|
{
|
||||||
|
GEN_ASSERT(arena != nullptr);
|
||||||
ssize alignment_offset, result_pointer, mask;
|
ssize alignment_offset, result_pointer, mask;
|
||||||
GEN_ASSERT(is_power_of_two(alignment));
|
GEN_ASSERT(is_power_of_two(alignment));
|
||||||
|
|
||||||
alignment_offset = 0;
|
alignment_offset = 0;
|
||||||
result_pointer = (ssize) PhysicalStart + TotalUsed;
|
result_pointer = (ssize)arena->PhysicalStart + arena->TotalUsed;
|
||||||
mask = alignment - 1;
|
mask = alignment - 1;
|
||||||
|
|
||||||
if (result_pointer & mask)
|
if (result_pointer & mask)
|
||||||
@ -223,68 +291,84 @@ struct Arena
|
|||||||
return alignment_offset;
|
return alignment_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This id is defined by Unreal for asserts
|
|
||||||
#pragma push_macro("check")
|
#pragma push_macro("check")
|
||||||
#undef check
|
#undef check
|
||||||
void check()
|
inline
|
||||||
|
void check(Arena* arena)
|
||||||
{
|
{
|
||||||
GEN_ASSERT( TempCount == 0 );
|
GEN_ASSERT(arena != nullptr );
|
||||||
|
GEN_ASSERT(arena->TempCount == 0);
|
||||||
}
|
}
|
||||||
#pragma pop_macro("check")
|
#pragma pop_macro("check")
|
||||||
|
|
||||||
void free()
|
inline
|
||||||
|
void free(Arena* arena)
|
||||||
{
|
{
|
||||||
if ( Backing.Proc )
|
GEN_ASSERT(arena != nullptr);
|
||||||
|
if (arena->Backing.Proc)
|
||||||
{
|
{
|
||||||
gen::free( Backing, PhysicalStart );
|
GEN_NS free(arena->Backing, arena->PhysicalStart);
|
||||||
PhysicalStart = nullptr;
|
arena->PhysicalStart = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize size_remaining( ssize alignment )
|
inline
|
||||||
|
ssize size_remaining(Arena* arena, ssize alignment)
|
||||||
{
|
{
|
||||||
ssize result = TotalSize - ( TotalUsed + alignment_of( alignment ) );
|
GEN_ASSERT(arena != nullptr);
|
||||||
|
ssize result = arena->TotalSize - (arena->TotalUsed + alignment_of(arena, alignment));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#pragma endregion Arena
|
||||||
|
|
||||||
AllocatorInfo Backing;
|
#pragma region FixedArena
|
||||||
void* PhysicalStart;
|
template<s32 Size>
|
||||||
ssize TotalSize;
|
struct FixedArena;
|
||||||
ssize TotalUsed;
|
|
||||||
ssize TempCount;
|
|
||||||
|
|
||||||
operator AllocatorInfo()
|
template<s32 Size> FixedArena<Size> fixed_arena_init();
|
||||||
{
|
template<s32 Size> AllocatorInfo allocator_info(FixedArena<Size>* fixed_arena );
|
||||||
return { allocator_proc, this };
|
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
|
|
||||||
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;
|
|
||||||
char memory[Size];
|
char memory[Size];
|
||||||
|
Arena arena;
|
||||||
|
|
||||||
|
#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 ) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -76,13 +76,18 @@
|
|||||||
/* Platform compiler */
|
/* Platform compiler */
|
||||||
|
|
||||||
#if defined( _MSC_VER )
|
#if defined( _MSC_VER )
|
||||||
|
# define GEN_COMPILER_CLANG 0
|
||||||
# define GEN_COMPILER_MSVC 1
|
# define GEN_COMPILER_MSVC 1
|
||||||
|
# define GEN_COMPILER_GCC 0
|
||||||
#elif defined( __GNUC__ )
|
#elif defined( __GNUC__ )
|
||||||
|
# define GEN_COMPILER_CLANG 0
|
||||||
|
# define GEN_COMPILER_MSVC 0
|
||||||
# define GEN_COMPILER_GCC 1
|
# 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
|
||||||
|
# if GEN_COMPILER_C
|
||||||
|
# define GEN_NS_ENUM_BEGIN
|
||||||
|
# define GEN_NS_ENUM_END
|
||||||
# define GEN_NS
|
# define GEN_NS
|
||||||
# define GEN_NS_BEGIN
|
# define GEN_NS_BEGIN
|
||||||
# define GEN_NS_END
|
# define GEN_NS_END
|
||||||
# else
|
# 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
|
||||||
|
# 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 }
|
||||||
|
@ -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;
|
||||||
|
@ -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 );
|
||||||
|
@ -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
|
||||||
|
@ -11,16 +11,17 @@ 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,232 +29,481 @@ 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.
|
||||||
struct String
|
#pragma region String
|
||||||
{
|
struct StringHeader;
|
||||||
struct Header
|
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;
|
AllocatorInfo Allocator;
|
||||||
ssize Capacity;
|
ssize Capacity;
|
||||||
ssize Length;
|
ssize Length;
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
#if ! GEN_COMPILER_C
|
||||||
usize grow_formula( usize value )
|
struct String
|
||||||
{
|
{
|
||||||
|
char* Data;
|
||||||
|
|
||||||
|
forceinline operator bool() { return Data != nullptr; }
|
||||||
|
forceinline operator char*() { return Data; }
|
||||||
|
forceinline operator char const*() const { return Data; }
|
||||||
|
forceinline operator StrC() const { return { GEN_NS length(* this), Data }; }
|
||||||
|
|
||||||
|
String const& operator=(String const& other) const {
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
String* this_ = ccast(String*, this);
|
||||||
|
this_->Data = other.Data;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
forceinline char& operator[](ssize index) { return Data[index]; }
|
||||||
|
forceinline char const& operator[](ssize index) const { 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
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 GEN_NS string_make(allocator, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#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.
|
// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library.
|
||||||
return 4 * value + 8;
|
return 4 * value + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
String make( AllocatorInfo allocator, char const* str )
|
String string_make(AllocatorInfo allocator, char const* str) {
|
||||||
{
|
|
||||||
ssize length = str ? str_len(str) : 0;
|
ssize length = str ? str_len(str) : 0;
|
||||||
return make_length( allocator, str, length );
|
return string_make_length(allocator, str, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
String make( AllocatorInfo allocator, StrC str )
|
String string_make(AllocatorInfo allocator, StrC str) {
|
||||||
{
|
return string_make_length(allocator, str.Ptr, str.Len);
|
||||||
return make_length( allocator, str.Ptr, str.Len );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
String make_reserve( AllocatorInfo allocator, ssize capacity );
|
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);
|
||||||
|
|
||||||
static
|
return string_make(allocator, buf);
|
||||||
String make_length( AllocatorInfo allocator, char const* str, ssize length );
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
String fmt( AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ... );
|
String string_fmt_buf(AllocatorInfo allocator, 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, "" );
|
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)
|
for (ssize idx = 0; idx < num_parts; ++idx)
|
||||||
{
|
{
|
||||||
result.append( parts[ idx ] );
|
append(& result, parts[idx]);
|
||||||
|
|
||||||
if (idx < num_parts - 1)
|
if (idx < num_parts - 1)
|
||||||
result.append( glue );
|
append(& result, glue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
bool are_equal( String lhs, String rhs )
|
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)
|
||||||
{
|
{
|
||||||
if ( lhs.length() != rhs.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;
|
return false;
|
||||||
|
|
||||||
for ( ssize idx = 0; idx < lhs.length(); ++idx )
|
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])
|
if (lhs[idx] != rhs[idx])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
inline
|
||||||
bool are_equal( String lhs, StrC rhs )
|
bool are_equal(String const lhs, StrC rhs)
|
||||||
{
|
{
|
||||||
if ( lhs.length() != (rhs.Len) )
|
if (length(lhs) != (rhs.Len))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for ( ssize idx = 0; idx < lhs.length(); ++idx )
|
for (ssize idx = 0; idx < length(lhs); ++idx)
|
||||||
if ( lhs[idx] != rhs[idx] )
|
if (lhs[idx] != rhs.Ptr[idx])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool make_space_for( char const* str, ssize add_len );
|
inline
|
||||||
|
ssize avail_space(String const str) {
|
||||||
bool append( char c )
|
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||||
{
|
return header->Capacity - header->Length;
|
||||||
return append( & c, 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append( char const* str )
|
inline
|
||||||
{
|
char* back(String* str) {
|
||||||
return append( str, str_len( str ) );
|
return & (*str)[length(* str) - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append( char const* str, ssize length )
|
inline
|
||||||
|
bool contains(String const str, StrC substring)
|
||||||
{
|
{
|
||||||
if ( sptr(str) > 0 )
|
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||||
{
|
|
||||||
ssize curr_len = this->length();
|
|
||||||
|
|
||||||
if ( ! make_space_for( str, length ) )
|
if (substring.Len > header->Length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Header& header = get_header();
|
ssize main_len = header->Length;
|
||||||
|
ssize sub_len = substring.Len;
|
||||||
|
|
||||||
mem_copy( Data + curr_len, str, length );
|
for (ssize idx = 0; idx <= main_len - sub_len; ++idx)
|
||||||
|
|
||||||
Data[ curr_len + length ] = '\0';
|
|
||||||
|
|
||||||
header.Length = curr_len + length;
|
|
||||||
}
|
|
||||||
return str != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool append( StrC str)
|
|
||||||
{
|
{
|
||||||
return append( str.Ptr, str.Len );
|
if (str_compare(str + idx, substring.Ptr, sub_len) == 0)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append( const String other )
|
return false;
|
||||||
{
|
|
||||||
return append( other.Data, other.length() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append_fmt( char const* fmt, ... );
|
inline
|
||||||
|
bool contains(String const str, String const substring)
|
||||||
ssize avail_space() const
|
|
||||||
{
|
{
|
||||||
Header const&
|
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||||
header = * rcast( Header const*, Data - sizeof( Header ));
|
|
||||||
|
|
||||||
return header.Capacity - header.Length;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
char& back()
|
return false;
|
||||||
{
|
|
||||||
return Data[ length() - 1 ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize capacity() const
|
inline
|
||||||
{
|
ssize capacity(String const str) {
|
||||||
Header const&
|
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||||
header = * rcast( Header const*, Data - sizeof( Header ));
|
return header->Capacity;
|
||||||
|
|
||||||
return header.Capacity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
inline
|
||||||
{
|
void clear(String str) {
|
||||||
get_header().Length = 0;
|
get_header(str)->Length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String duplicate( AllocatorInfo allocator ) const
|
inline
|
||||||
{
|
String duplicate(String const str, AllocatorInfo allocator) {
|
||||||
return make_length( allocator, Data, length() );
|
return string_make_length(allocator, str, length(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
void free()
|
inline
|
||||||
{
|
void free(String* str) {
|
||||||
if ( ! Data )
|
GEN_ASSERT(str != nullptr);
|
||||||
|
if (! (* str))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Header& header = get_header();
|
StringHeader* header = get_header(* str);
|
||||||
|
GEN_NS free(header->Allocator, header);
|
||||||
gen::free( header.Allocator, & header );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Header& get_header()
|
inline
|
||||||
{
|
StringHeader* get_header(String str) {
|
||||||
return *(Header*)(Data - sizeof(Header));
|
return (StringHeader*)(scast(char*, str) - sizeof(StringHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize length() const
|
inline
|
||||||
|
ssize length(String const str)
|
||||||
{
|
{
|
||||||
Header const&
|
StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||||
header = * rcast( Header const*, Data - sizeof( Header ));
|
|
||||||
|
|
||||||
return header.Length;
|
return header.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 starts_with( StrC substring ) const
|
inline
|
||||||
|
bool make_space_for(String* str, char const* to_append, ssize add_len)
|
||||||
{
|
{
|
||||||
if (substring.Len > length())
|
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;
|
return false;
|
||||||
|
|
||||||
b32 result = str_compare(Data, substring.Ptr, substring.Len ) == 0;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 starts_with( String substring ) const
|
inline
|
||||||
{
|
b32 starts_with(String const str, String substring) {
|
||||||
if (substring.length() > length())
|
if (length(substring) > length(str))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
b32 result = str_compare(Data, substring, substring.length() - 1 ) == 0;
|
b32 result = str_compare(str.Data, substring.Data, length(substring) - 1) == 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skip_line()
|
inline
|
||||||
|
void skip_line(String str)
|
||||||
{
|
{
|
||||||
#define current (*scanner)
|
#define current (*scanner)
|
||||||
char* scanner = Data;
|
char* scanner = str.Data;
|
||||||
while ( current != '\r' && current != '\n' )
|
while (current != '\r' && current != '\n') {
|
||||||
{
|
|
||||||
++scanner;
|
++scanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 new_length = scanner - Data;
|
s32 new_length = scanner - str.Data;
|
||||||
|
|
||||||
if ( current == '\r' )
|
if (current == '\r') {
|
||||||
{
|
|
||||||
new_length += 1;
|
new_length += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_move( Data, scanner, new_length );
|
mem_move(str.Data, scanner, new_length);
|
||||||
|
|
||||||
Header* header = & get_header();
|
StringHeader* header = get_header(str);
|
||||||
header->Length = new_length;
|
header->Length = new_length;
|
||||||
#undef current
|
#undef current
|
||||||
}
|
}
|
||||||
|
|
||||||
void strip_space()
|
inline
|
||||||
|
void strip_space(String str)
|
||||||
{
|
{
|
||||||
char* write_pos = Data;
|
char* write_pos = str;
|
||||||
char* read_pos = Data;
|
char* read_pos = str;
|
||||||
|
|
||||||
while (* read_pos)
|
while (* read_pos)
|
||||||
{
|
{
|
||||||
@ -268,15 +518,16 @@ struct String
|
|||||||
write_pos[0] = '\0'; // Null-terminate the modified string
|
write_pos[0] = '\0'; // Null-terminate the modified string
|
||||||
|
|
||||||
// Update the length if needed
|
// Update the length if needed
|
||||||
get_header().Length = write_pos - Data;
|
get_header(str)->Length = write_pos - str.Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trim( char const* cut_set )
|
inline
|
||||||
|
void trim(String str, char const* cut_set)
|
||||||
{
|
{
|
||||||
ssize len = 0;
|
ssize len = 0;
|
||||||
|
|
||||||
char* start_pos = Data;
|
char* start_pos = str.Data;
|
||||||
char* end_pos = Data + length() - 1;
|
char* end_pos = str.Data + length(str) - 1;
|
||||||
|
|
||||||
while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos))
|
while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos))
|
||||||
start_pos++;
|
start_pos++;
|
||||||
@ -286,130 +537,64 @@ struct String
|
|||||||
|
|
||||||
len = scast(ssize, (start_pos > end_pos) ? 0 : ((end_pos - start_pos) + 1));
|
len = scast(ssize, (start_pos > end_pos) ? 0 : ((end_pos - start_pos) + 1));
|
||||||
|
|
||||||
if ( Data != start_pos )
|
if (str.Data != start_pos)
|
||||||
mem_move( Data, start_pos, len );
|
mem_move(str.Data, start_pos, len);
|
||||||
|
|
||||||
Data[ len ] = '\0';
|
str.Data[len] = '\0';
|
||||||
|
|
||||||
get_header().Length = len;
|
get_header(str)->Length = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trim_space()
|
inline
|
||||||
{
|
void trim_space(String str) {
|
||||||
return trim( " \t\r\n\v\f" );
|
trim(str, " \t\r\n\v\f");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug function that provides a copy of the string with whitespace characters visualized.
|
inline
|
||||||
String visualize_whitespace() const
|
String visualize_whitespace(String const str)
|
||||||
{
|
{
|
||||||
Header* header = (Header*)(Data - sizeof(Header));
|
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.
|
||||||
|
|
||||||
String result = make_reserve(header->Allocator, length() * 2); // Assume worst case for space requirements.
|
for (auto c : str) switch (c)
|
||||||
|
|
||||||
for ( char c : *this )
|
|
||||||
{
|
|
||||||
switch ( c )
|
|
||||||
{
|
{
|
||||||
case ' ':
|
case ' ':
|
||||||
result.append( txt("·") );
|
append(& result, txt("·"));
|
||||||
break;
|
break;
|
||||||
case '\t':
|
case '\t':
|
||||||
result.append( txt("→") );
|
append(& result, txt("→"));
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
result.append( txt("↵") );
|
append(& result, txt("↵"));
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
result.append( txt("⏎") );
|
append(& result, txt("⏎"));
|
||||||
break;
|
break;
|
||||||
case '\v':
|
case '\v':
|
||||||
result.append( txt("⇕") );
|
append(& result, txt("⇕"));
|
||||||
break;
|
break;
|
||||||
case '\f':
|
case '\f':
|
||||||
result.append( txt("⌂") );
|
append(& result, txt("⌂"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result.append(c);
|
append(& result, c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#pragma endregion String
|
||||||
|
|
||||||
// For-range support
|
struct String_POD {
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
String*
|
|
||||||
this_ = ccast(String*, this);
|
|
||||||
this_->Data = other.Data;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
char& operator [] ( ssize index )
|
|
||||||
{
|
|
||||||
return Data[ index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
char const& operator [] ( ssize index ) const
|
|
||||||
{
|
|
||||||
return Data[ index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
char* Data;
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -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>()
|
||||||
|
10
project/helpers/member_proc_support.hpp
Normal file
10
project/helpers/member_proc_support.hpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gen.hpp"
|
||||||
|
|
||||||
|
GEN_NS_BEGIN
|
||||||
|
#include "dependencies/parsing.hpp"
|
||||||
|
GEN_NS_END
|
||||||
|
|
||||||
|
using namespace gen;
|
||||||
|
|
@ -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
|
||||||
|
24
scripts/c_library.refactor
Normal file
24
scripts/c_library.refactor
Normal 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.
|
0
scripts/refactor_c_library.ps1
Normal file
0
scripts/refactor_c_library.ps1
Normal file
Reference in New Issue
Block a user