From fbdb870986cb1ab2242eb70dd29c8aaa4feaddc3 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 30 Nov 2024 23:38:27 -0500 Subject: [PATCH] Finished first pass reviewing memory.hpp for C lib generation --- .gitignore | 1 + .vscode/settings.json | 3 +- gen_c_library/c_library.cpp | 104 +++++++++++++++- gen_c_library/components/fixed_arena.hpp | 119 +++++++++++++++++++ gen_c_library/components/header_start.hpp | 14 +++ gen_c_library/components/misc.hpp | 61 ++++++++++ gen_singleheader/components/header_start.hpp | 9 -- project/components/code_types.hpp | 40 +++++++ project/components/header_end.hpp | 2 + project/components/parser.cpp | 4 +- project/dependencies/basic_types.hpp | 4 +- project/dependencies/containers.hpp | 8 +- project/dependencies/macros.hpp | 2 +- project/dependencies/memory.hpp | 5 +- scripts/build.ci.ps1 | 4 +- 15 files changed, 350 insertions(+), 30 deletions(-) create mode 100644 gen_c_library/components/fixed_arena.hpp create mode 100644 gen_c_library/components/header_start.hpp create mode 100644 gen_c_library/components/misc.hpp diff --git a/.gitignore b/.gitignore index 9ff6447..d638b75 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ project/auxillary/vis_ast/dependencies/temp test/gen/original singleheader/gen/scratch.hpp test/gen/scratch.cpp +gen_c_library/gen diff --git a/.vscode/settings.json b/.vscode/settings.json index 65611a9..87d304b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,7 +38,8 @@ "android_native_app_glue.h": "c", "raylib.h": "c", "*.m": "cpp", - "atomic": "cpp" + "atomic": "cpp", + "gen.h": "c" }, "C_Cpp.intelliSenseEngineFallback": "disabled", "mesonbuild.configureOnOpen": true, diff --git a/gen_c_library/c_library.cpp b/gen_c_library/c_library.cpp index 4d8ea1a..e29a620 100644 --- a/gen_c_library/c_library.cpp +++ b/gen_c_library/c_library.cpp @@ -1,7 +1,7 @@ #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS #define GEN_ENFORCE_STRONG_CODE_TYPES #define GEN_EXPOSE_BACKEND -#include "gen.cpp" +#include "../project/gen.cpp" #include "helpers/push_ignores.inline.hpp" #include "helpers/helper.hpp" @@ -16,6 +16,9 @@ GEN_NS_END #include // for system() +#include "components/fixed_arena.hpp" +#include "components/misc.hpp" + using namespace gen; constexpr char const* generation_notice = @@ -80,26 +83,117 @@ Code dump_to_scratch_and_retireve( Code code ) 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 } ); + 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 single_header_start = scan_file( "components/header_start.hpp" ); + 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.hpp" ); + 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" ); + + CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); + CodeBody memory = def_body(ECode::Struct_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 = entry.cast(); + CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); + + memory.append(typedef_ver); + } + break; + case ECode::Function: + { + CodeFn fn = entry.cast(); + s32 constexpr_found = fn->Specs.remove( ESpecifier::Constexpr ); + if (constexpr_found > -1) { + log_fmt("Found constexpr proc\n"); + fn->Specs.append(ESpecifier::Inline); + } + memory.append(entry); + } + 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: + { + ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), entry, memory ); + } + break; + case ECode::Preprocess_Pragma: + { + swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory); + } + break; + default: { + memory.append(entry); + } + break; + } + } + + 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 ); + header.print( memory ); } + header.print( pop_ignores ); + header.write(); + + format_file( "gen/gen.h" ); + gen::deinit(); return 0; #undef project_dir diff --git a/gen_c_library/components/fixed_arena.hpp b/gen_c_library/components/fixed_arena.hpp new file mode 100644 index 0000000..8f0ff21 --- /dev/null +++ b/gen_c_library/components/fixed_arena.hpp @@ -0,0 +1,119 @@ +// #pragma once +// #include "../project/gen.hpp" + +// using namespace gen; + +CodeBody gen_fixed_arenas() +{ + CodeBody result = def_body(ECode::Global_Body); + + char const* template_struct = stringize( + struct FixedArena_ + { + char memory[]; + Arena arena; + }; + ); + + char const* template_interface = stringize( + inline + void fixed_arena_init_(FixedArena_* result) { + zero_size(& result.memory[0], ); + result.arena = arena_init_from_memory(& result.memory[0], ); + } + + inline + ssize fixed_arena_size_remaining_(FixedArena_* 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) +)" + ))); + + return result; +} diff --git a/gen_c_library/components/header_start.hpp b/gen_c_library/components/header_start.hpp new file mode 100644 index 0000000..cbfa228 --- /dev/null +++ b/gen_c_library/components/header_start.hpp @@ -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 diff --git a/gen_c_library/components/misc.hpp b/gen_c_library/components/misc.hpp new file mode 100644 index 0000000..1fc20aa --- /dev/null +++ b/gen_c_library/components/misc.hpp @@ -0,0 +1,61 @@ +// #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 ) +{ + CodePreprocessCond cond = entry_iter.cast(); + if ( cond->Content.contains(cond_sig) ) + { + s32 depth = 1; + ++ entry_iter; for(b32 continue_for = true; continue_for && entry_iter != body.end(); ++ entry_iter) 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; + } + } + + return entry_iter != body.end(); +} + +void swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_content, Code& entry_iter, CodeBody& body ) +{ + CodePragma possible_region = entry_iter.cast(); + + 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)) + { + 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 = entry_iter.cast(); + if ( possible_end_region->Content.contains(endregion_sig) ) { + body.append(possible_end_region); + continue_for = false; + } + } + break; + } + } + body.append(entry_iter); +} diff --git a/gen_singleheader/components/header_start.hpp b/gen_singleheader/components/header_start.hpp index fdee90c..8d69720 100644 --- a/gen_singleheader/components/header_start.hpp +++ b/gen_singleheader/components/header_start.hpp @@ -12,12 +12,3 @@ #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) # error Gen.hpp : GEN_TIME not defined #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 - diff --git a/project/components/code_types.hpp b/project/components/code_types.hpp index 4b67d57..bc0f5f9 100644 --- a/project/components/code_types.hpp +++ b/project/components/code_types.hpp @@ -165,6 +165,46 @@ struct CodeSpecifiers 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; + } void to_string( String& result ); AST* raw() { diff --git a/project/components/header_end.hpp b/project/components/header_end.hpp index 39cc1f2..27d03d9 100644 --- a/project/components/header_end.hpp +++ b/project/components/header_end.hpp @@ -133,6 +133,7 @@ extern CodeType t_typename; #pragma region Macros +#ifndef token_fmt # define gen_main main # 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. # define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) +#endif #pragma endregion Macros diff --git a/project/components/parser.cpp b/project/components/parser.cpp index 2c19973..3c00ee7 100644 --- a/project/components/parser.cpp +++ b/project/components/parser.cpp @@ -714,8 +714,8 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) char interface_arr_mem[ kilobytes(4) ] {0}; Array interfaces; { Arena arena = arena_init_from_memory( interface_arr_mem, kilobytes(4) ); - array_init_reserve( allocator_info(arena), 4 ); - } + interfaces = array_init_reserve( allocator_info(arena), 4 ); + } // TODO(Ed) : Make an AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them. if ( check( TokType::Assign_Classifer ) ) diff --git a/project/dependencies/basic_types.hpp b/project/dependencies/basic_types.hpp index 5b4b0e3..37da1de 100644 --- a/project/dependencies/basic_types.hpp +++ b/project/dependencies/basic_types.hpp @@ -123,8 +123,8 @@ typedef s8 b8; typedef s16 b16; typedef s32 b32; -using mem_ptr = void*; -using mem_ptr_const = void const*; +typedef void* mem_ptr; +typedef void const* mem_ptr_const ; #if ! GEN_COMPILER_C template uptr to_uptr( Type* ptr ) { return (uptr)ptr; } diff --git a/project/dependencies/containers.hpp b/project/dependencies/containers.hpp index 9c12af2..e6ec2d8 100644 --- a/project/dependencies/containers.hpp +++ b/project/dependencies/containers.hpp @@ -52,9 +52,9 @@ template bool resize(Array& array, usize num); template bool set_capacity(Array& array, usize new_capacity); template ArrayHeader* get_header(Array& array); -template forceinline Type* begin(Array& array) { return array; } -template forceinline Type* end(Array& array) { return array + get_header(array)->Num; } -template forceinline Type* next(Type* entry) { return entry + 1; } +template forceinline Type* begin(Array& array) { return array; } +template forceinline Type* end(Array& array) { return array + get_header(array)->Num; } +template forceinline Type* next(Array& array, Type* entry) { return entry + 1; } struct ArrayHeader { AllocatorInfo Allocator; @@ -250,7 +250,7 @@ bool fill(Array& array, usize begin, usize end, Type value) template inline void free(Array& array) { ArrayHeader* header = get_header(array); - gen::free(header->Allocator, header); + GEN_NS free(header->Allocator, header); Type*& Data = rcast(Type*&, array); Data = nullptr; } diff --git a/project/dependencies/macros.hpp b/project/dependencies/macros.hpp index 790f1b4..cf0346d 100644 --- a/project/dependencies/macros.hpp +++ b/project/dependencies/macros.hpp @@ -200,7 +200,7 @@ // 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(entry_id) ) +# 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 diff --git a/project/dependencies/memory.hpp b/project/dependencies/memory.hpp index d8c4253..545e337 100644 --- a/project/dependencies/memory.hpp +++ b/project/dependencies/memory.hpp @@ -80,10 +80,7 @@ enum AllocType : u8 EAllocation_RESIZE, }; -using AllocatorProc = void* ( void* allocator_data, AllocType type - , ssize size, ssize alignment - , void* old_memory, ssize old_size - , u64 flags ); +typedef void*(AllocatorProc)( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); struct AllocatorInfo { diff --git a/scripts/build.ci.ps1 b/scripts/build.ci.ps1 index 73cd1b3..67b2697 100644 --- a/scripts/build.ci.ps1 +++ b/scripts/build.ci.ps1 @@ -90,7 +90,7 @@ else { $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" } @@ -215,7 +215,7 @@ if ( $c_library ) build-simple $path_build $includes $compiler_args $linker_args $unit $executable - Push-Location $path_singleheader + Push-Location $path_c_library if ( Test-Path( $executable ) ) { write-host "`nRunning c_library generator" $time_taken = Measure-Command { & $executable