From f9085d4b6f4da10b8dca455ba741716603454a5e Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 11 Jul 2023 03:10:20 -0400 Subject: [PATCH] Parser constructor passes all current tests... Pretty much have a working library now... Albiet with problably quite a few hidden bugs in parsing. Next steps are to start converting library to use its own Arena, Pool, Array, HashTable types. And either work on zpl dependency gutting or making a more robust set of tests. --- Readme.md | 6 +- project/gen.cpp | 42 +-- scripts/build.ci.ps1 | 2 +- test/NonParsed/Array.NonParsed.hpp | 11 +- test/NonParsed/HashTable.NonParsed.hpp | 9 +- test/NonParsed/Memory.NonParsed.hpp | 1 - test/NonParsed/Ring.NonParsed.hpp | 2 +- test/Parsed/Array.Parsed.hpp | 9 +- test/Parsed/Buffer.Parsed.hpp | 202 ++++++++++++++ test/Parsed/HashTable.Parsed.hpp | 359 +++++++++++++++++++++++++ test/Parsed/Ring.Parsed.hpp | 171 ++++++++++++ test/test.Parsed.cpp | 23 +- 12 files changed, 787 insertions(+), 50 deletions(-) delete mode 100644 test/NonParsed/Memory.NonParsed.hpp create mode 100644 test/Parsed/Buffer.Parsed.hpp create mode 100644 test/Parsed/HashTable.Parsed.hpp create mode 100644 test/Parsed/Ring.Parsed.hpp diff --git a/Readme.md b/Readme.md index 795ee10..2c15d50 100644 --- a/Readme.md +++ b/Readme.md @@ -588,8 +588,10 @@ Names or Content fields are interned strings and thus showed be cached using `ge # TODO -* May be in need of a better name, I found a few repos with this same one... -* Make a test suite made up of collections based of the ZPL library templated colllection macros and the memory module. +* Implement a context stack for the parsing, allows for accurate scope validation for the AST types. +* Make a test suite thats covers some base cases and zpl containers (+ anything else suitable) +* Finish support for module specifiers and standard/platform attributes. * Remove full ZPL dependency, move into Bloat header/source only what is used. * Generate a single-header library. * Actually get to version 1. +* May be in need of a better name, I found a few repos with this same one... diff --git a/project/gen.cpp b/project/gen.cpp index d92a6d7..bea40c9 100644 --- a/project/gen.cpp +++ b/project/gen.cpp @@ -4615,16 +4615,19 @@ namespace gen case TokType::Access_Public: member = access_public; eat( TokType::Access_Public ); + eat( TokType::Assign_Classifer ); break; case TokType::Access_Protected: member = access_protected; eat( TokType::Access_Protected ); + eat( TokType::Assign_Classifer ); break; case TokType::Access_Private: member = access_private; eat( TokType::Access_Private ); + eat( TokType::Assign_Classifer ); break; case TokType::Decl_Class: @@ -5721,10 +5724,13 @@ namespace gen { using namespace Parser; + Token context_tok = prevtok; + SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; s32 num_specifiers = 0; - Token name = { nullptr, 0, TokType::Invalid }; + Token name = { nullptr, 0, TokType::Invalid }; + Token func_sig = { currtok.Text, 0, TokType::Invalid }; while ( left && tok_is_specifier( currtok ) ) { @@ -5793,13 +5799,11 @@ namespace gen eat( currtok.Type ); } - Token func_sig = { nullptr, 0, TokType::Invalid }; - - if ( check( TokType::Capture_Start ) && prevtok.Type == TokType::Capture_End ) + // Not sure if its technically possible to cast ot a function pointer user defined operator cast... + // Supporting it is not worth the effort. + if ( check( TokType::Capture_Start ) && context_tok.Type != TokType::Decl_Operator ) { // Its a function type - - func_sig = currtok; eat( TokType::Capture_Start ); while ( check( TokType::Star ) || currtok.Type == TokType::Spec_Const ) @@ -5807,7 +5811,9 @@ namespace gen eat( currtok.Type ); } - eat(TokType::Identifier); + // if its a using statement there will not be an ID. + if ( check( TokType::Identifier ) ) + eat(TokType::Identifier); eat( TokType::Capture_End ); @@ -5817,8 +5823,15 @@ namespace gen // TODO : Change this to validate the parameters... // Bruteforce lex the parameters, no validation. - while ( ! check( TokType::Capture_End )) + s32 level = 0; + while ( ! check( TokType::Capture_End ) || level > 0 ) { + if ( check( TokType::Capture_Start ) ) + level++; + + if ( check( TokType::Capture_End ) ) + level--; + eat( currtok.Type ); } @@ -5833,17 +5846,10 @@ namespace gen result = make_code(); result->Type = Typename; - if ( func_sig ) + if ( func_sig.Length > 0 ) { - // Brute force name to the entire signature. - - String custom_name = String::make( Memory::GlobalAllocator, name ); - - if ( num_specifiers ) - custom_name.append( def_specifiers( num_specifiers, (SpecifierT*)specs_found ).to_string() ); - - custom_name.append( " " ); - custom_name.append(func_sig ); + // Bruteforce all tokens together. + name = func_sig; } else { diff --git a/scripts/build.ci.ps1 b/scripts/build.ci.ps1 index 556f26c..5d4b3db 100644 --- a/scripts/build.ci.ps1 +++ b/scripts/build.ci.ps1 @@ -50,7 +50,7 @@ $path_scripts = Join-Path $path_root scripts Pop-Location # Test NonParsed - if ($false) { + if ($true) { $gencpp = Join-Path $path_gen_build gencpp.exe Push-location $path_gen diff --git a/test/NonParsed/Array.NonParsed.hpp b/test/NonParsed/Array.NonParsed.hpp index ba5a08f..9411870 100644 --- a/test/NonParsed/Array.NonParsed.hpp +++ b/test/NonParsed/Array.NonParsed.hpp @@ -23,7 +23,7 @@ Code gen__array_base() return def_global_body( 2, header, grow_formula ); } -Code gen__array( StrC type, sw type_size ) +Code gen__array( StrC type ) { static Code t_allocator_info = def_type( name(AllocatorInfo) ); static Code v_nullptr = untyped_str( code(nullptr)); @@ -299,11 +299,10 @@ struct GenArrayRequest { StrC Dependency; StrC Type; - sw Size; }; Array(GenArrayRequest) GenArrayRequests; -void gen__array_request( StrC type, sw size, StrC dep = {} ) +void gen__array_request( StrC type, StrC dep = {} ) { do_once_start array_init( GenArrayRequests, Memory::GlobalAllocator ); @@ -321,10 +320,10 @@ void gen__array_request( StrC type, sw size, StrC dep = {} ) return; } - GenArrayRequest request = { dep, type, size }; + GenArrayRequest request = { dep, type }; array_append( GenArrayRequests, request ); } -#define gen_array( type ) gen__array_request( { txt_to_StrC(type) }, sizeof(type) ) +#define gen_array( type ) gen__array_request( { txt_to_StrC(type) } ) u32 gen_array_file() { @@ -344,7 +343,7 @@ u32 gen_array_file() { GenArrayRequest const& request = * current; - Code generated_array = gen__array( request.Type, request.Size ); + Code generated_array = gen__array( request.Type ); if ( request.Dependency ) { diff --git a/test/NonParsed/HashTable.NonParsed.hpp b/test/NonParsed/HashTable.NonParsed.hpp index a7f9ffa..8c1a317 100644 --- a/test/NonParsed/HashTable.NonParsed.hpp +++ b/test/NonParsed/HashTable.NonParsed.hpp @@ -48,7 +48,6 @@ Code gen__hashtable( StrC type, sw type_size ) s32 len = str_len( name_str ); StringCached ht_entry_name = get_cached_string({ len, name_str }); - sw const entry_size = sizeof( u64 ) + sizeof( sw ) + type_size; t_ht_entry = def_type( ht_entry_name ); ht_entry = def_struct( ht_entry_name, def_struct_body( 3 @@ -57,7 +56,7 @@ Code gen__hashtable( StrC type, sw type_size ) , def_variable( t_type, name(Value)) )); - array_ht_entry = gen__array( ht_entry_name, entry_size ); + array_ht_entry = gen__array( ht_entry_name ); t_array_ht_entry = def_type( array_ht_entry->Name ); } @@ -90,7 +89,7 @@ Code gen__hashtable( StrC type, sw type_size ) Code clear = def_function( name(clear), __, t_void , def_execution( code( - for ( s32 idx = 0; idx < Hashes.num(), idx++ ) + for ( s32 idx = 0; idx < Hashes.num(); idx++ ) Hashes[ idx ] = -1; Entries.clear(); @@ -222,7 +221,7 @@ Code gen__hashtable( StrC type, sw type_size ) ); Code body = def_execution( token_fmt( tmpl, 1, "type", name ) ); - rehash = def_function( name(rehash), def_param( t_sw, name(new_num)), t_void, body, spec_inline); + rehash = def_function( name(rehash), def_param( t_sw, name(new_num)), t_void, body ); } Code rehash_fast; @@ -435,7 +434,7 @@ u32 gen_hashtable_file() gen_buffer_file.print( def_include( StrC::from("Bloat.hpp")) ); gen_buffer_file.print( def_include( StrC::from("Array.NonParsed.hpp")) ); - gen_buffer_file.print( def_include( StrC::from("array.gen.hpp")) ); + gen_buffer_file.print( def_include( StrC::from("array.NonParsed.gen.hpp")) ); gen_buffer_file.print( gen__hashtable_base()); diff --git a/test/NonParsed/Memory.NonParsed.hpp b/test/NonParsed/Memory.NonParsed.hpp deleted file mode 100644 index 078426a..0000000 --- a/test/NonParsed/Memory.NonParsed.hpp +++ /dev/null @@ -1 +0,0 @@ -// \ No newline at end of file diff --git a/test/NonParsed/Ring.NonParsed.hpp b/test/NonParsed/Ring.NonParsed.hpp index 1f017ff..fabc141 100644 --- a/test/NonParsed/Ring.NonParsed.hpp +++ b/test/NonParsed/Ring.NonParsed.hpp @@ -197,7 +197,7 @@ u32 gen_ring_file() gen_ring_file.open( "ring.NonParsed.gen.hpp" ); gen_ring_file.print( def_include( StrC::from("Bloat.hpp")) ); - gen_ring_file.print( def_include( StrC::from("buffer.gen.hpp")) ); + gen_ring_file.print( def_include( StrC::from("buffer.NonParsed.gen.hpp")) ); // gen_ring_file.print( gen__ring_base() ); GenRingRequest* current = GenRingRequests; diff --git a/test/Parsed/Array.Parsed.hpp b/test/Parsed/Array.Parsed.hpp index fef561a..6356cc4 100644 --- a/test/Parsed/Array.Parsed.hpp +++ b/test/Parsed/Array.Parsed.hpp @@ -22,7 +22,7 @@ Code gen__array_base() )); } -Code gen__array( StrC type, sw type_size ) +Code gen__array( StrC type ) { StrC name; { @@ -184,7 +184,7 @@ Code gen__array( StrC type, sw type_size ) header.Num = new_capacity; sw size = sizeof( Header ) + sizeof( Type ) * new_capacity; - Header* new_header = reinterpret_cast< Header* >( alloc( header.Allocator, size ) ); + Header* new_header = rcast( Header*, alloc( header.Allocator, size ) ); if ( new_header == nullptr ) return false; @@ -223,7 +223,6 @@ struct GenArrayRequest { StrC Dependency; StrC Type; - sw Size; }; Array(GenArrayRequest) GenArrayRequests; @@ -245,7 +244,7 @@ void gen__array_request( StrC type, sw size, StrC dep = {} ) return; } - GenArrayRequest request = { dep, type, size }; + GenArrayRequest request = { dep, type }; array_append( GenArrayRequests, request ); } #define gen_array( type ) gen__array_request( { txt_to_StrC(type) }, sizeof(type) ) @@ -268,7 +267,7 @@ u32 gen_array_file() { GenArrayRequest const& request = * current; - Code generated_array = gen__array( request.Type, request.Size ); + Code generated_array = gen__array( request.Type ); if ( request.Dependency ) { diff --git a/test/Parsed/Buffer.Parsed.hpp b/test/Parsed/Buffer.Parsed.hpp new file mode 100644 index 0000000..82445e3 --- /dev/null +++ b/test/Parsed/Buffer.Parsed.hpp @@ -0,0 +1,202 @@ +#pragma once + +#if gen_time +#include "gen.hpp" + +using namespace gen; + +Code gen__buffer_base() +{ + return parse_global_body( code( + struct BufferHeader + { + AllocatorInfo Backing; + uw Capacity; + uw Num; + }; + )); +} + +Code gen__buffer( StrC type ) +{ + StrC name; + { + char const* name_str = str_fmt_buf( "Buffer_%s\0", type.Ptr ); + s32 name_len = str_len( name_str ); + + name = { name_len, name_str }; + }; + + Code buffer = parse_struct( token_fmt( + txt( + struct + { + using Header = BufferHeader; + using Type = ; + + static init( AllocatorInfo allocator, sw capacity ) + { + Header* header = rcast( Header*, alloc( allocator, sizeof( Header ) + capacity * sizeof( Type ) ) ); + + if ( header == nullptr ) + return { nullptr }; + + header->Backing = allocator; + header->Capacity = capacity; + header->Num = 0; + + return { rcast( Type*, header + 1 ) }; + } + + init( AllocatorInfo allocator, other ) + { + Header& other_header = other.get_header(); + Header* header = rcast( Header*, alloc( allocator, sizeof( Header ) + other_header.Capacity * sizeof( Type ) ) ); + + if ( header == nullptr ) + return { nullptr }; + + header->Backing = allocator; + header->Capacity = other_header.Capacity; + header->Num = other_header.Num; + + mem_copy( header + 1, other.Data, other_header.Num * sizeof( Type ) ); + + return { rcast( Type*, header + 1 ) }; + } + + void append( Type value ) + { + Header& header = get_header(); + Data[ header.Num ] = value; + header.Num++; + } + + void append( Type* values, sw num ) + { + Header& header = get_header(); + ZPL_ASSERT( header.Num + num <= header.Capacity); + + mem_copy( Data + header.Num, values, num * sizeof( Type ) ); + header.Num += num; + } + + void clear( void ) + { + Header& header = get_header(); + header.Num = 0; + } + + Type& end( void ) + { + Header& header = get_header(); + return Data[ header.Num - 1 ]; + } + + void free( void ) + { + Header& header = get_header(); + zpl::free( header.Backing, &header ); + } + + Header& get_header( void ) + { + return *( rcast( Header*, Data ) - 1 ); + } + + sw num( void ) + { + return get_header().Num; + } + + void wipe( void ) + { + Header& header = get_header(); + header.Num = 0; + mem_set( Data, 0, header.Capacity * sizeof( Type ) ); + } + + operator Type*() + { + return Data; + } + + Type* Data; + }; + ), + 2 + , "BufferName", (char const*) name + , "type", (char const*) type + )); + + return buffer; +} + +struct GenBufferRequest +{ + StrC Dependency; + StrC Type; +}; +Array(GenBufferRequest) GenBufferRequests; + +void gen__buffer_request( StrC type, StrC dep = {} ) +{ + do_once_start + array_init( GenBufferRequests, Memory::GlobalAllocator ); + do_once_end + + // Make sure we don't already have a request for the type. + for ( sw idx = 0; idx < array_count( GenBufferRequests ); ++idx ) + { + StrC const reqest_type = GenBufferRequests[ idx ].Type; + + if ( reqest_type.Len != type.Len ) + continue; + + if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 ) + return; + } + + GenBufferRequest request = { dep, type }; + array_append( GenBufferRequests, request ); +} +#define gen_buffer( type ) gen__buffer_request( { txt_to_StrC(type) } ) + +u32 gen_buffer_file() +{ + Builder + gen_buffer_file; + gen_buffer_file.open( "buffer.Parsed.gen.hpp" ); + + gen_buffer_file.print( def_include( StrC::from("Bloat.hpp")) ); + gen_buffer_file.print( gen__buffer_base() ); + + GenBufferRequest* current = GenBufferRequests; + s32 left = array_count( GenBufferRequests ); + while (left--) + { + GenBufferRequest const& request = * current; + + Code generated_buffer = gen__buffer( current->Type ); + + if ( request.Dependency ) + { + char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type ); + s32 cmt_len = str_len( cmt_str ); + + Code cmt = def_comment( { cmt_len, cmt_str } ); + Code include = def_include( request.Dependency ); + + gen_buffer_file.print( cmt ); + gen_buffer_file.print( include ); + } + + gen_buffer_file.print( generated_buffer ); + current++; + } + + gen_buffer_file.write(); + return 0; +} + +#endif // gen_time diff --git a/test/Parsed/HashTable.Parsed.hpp b/test/Parsed/HashTable.Parsed.hpp new file mode 100644 index 0000000..c7fda47 --- /dev/null +++ b/test/Parsed/HashTable.Parsed.hpp @@ -0,0 +1,359 @@ +#pragma once + +#if gen_time +#include "gen.hpp" +#include "Array.Parsed.hpp" + +using namespace gen; + +Code gen__hashtable_base() +{ + return parse_global_body( code( + struct HashTable_FindResult + { + sw HashIndex; + sw PrevIndex; + sw EntryIndex; + }; + )); +} + +Code gen__hashtable( StrC type, sw type_size ) +{ + StringCached name; + { + char const* name_str = str_fmt_buf( "HashTable_%s", type.Ptr ); + s32 len = str_len( name_str ); + + name = get_cached_string({ len, name_str }); + } + + Code ht_entry = parse_struct( token_fmt( + txt( + struct _Entry + { + u64 Key; + sw Next; + Value; + }; + ), + 2 + , "HashTableName", (char const*) name + , "type", (char const*) type + )); + + StringCached ht_entry_name = get_cached_string( token_fmt( "_Entry", 1, "HashTableName", name ) ); + + Code array_ht_entry = gen__array( ht_entry_name ); + + Code hashtable = parse_struct( token_fmt( + txt( + struct + { + using Type = ; + using Entry = _Entry; + using Array_Entry = Array__Entry; + using FindResult = HashTable_FindResult; + using MapProc = void ( * )( u64 key, Type value ); + using MapMutProc = void ( * )( u64 key, Type* value ); + + static + init( AllocatorInfo allocator ) + { + + result = { 0 }; + result.Hashes = Array_sw ::init( allocator ); + result.Entries = Array_Entry::init( allocator ); + return result; + } + + void clear( void ) + { + for ( s32 idx = 0; idx < Hashes.num(); idx++ ) + Hashes[ idx ] = -1; + + Entries.clear(); + } + + void destroy( void ) + { + if ( Hashes ) + Hashes.free(); + if ( Entries ) + Entries.free(); + } + + Type* get( u64 key ) + { + sw idx = find( key ).EntryIndex; + + if ( idx > 0 ) + return &Entries[ idx ].Value; + + return nullptr; + } + + void grow( void ) + { + sw new_num = array_grow_formula( Entries.num() ); + + rehash( new_num ); + } + + void map( MapProc map_proc ) + { + ZPL_ASSERT_NOT_NULL( map_proc ); + + for ( sw idx = 0; idx < Entries.num(); idx++ ) + { + map_proc( Entries[ idx ].Key, Entries[ idx ].Value ); + } + } + + void map_mut( MapMutProc map_proc ) + { + ZPL_ASSERT_NOT_NULL( map_proc ); + + for ( sw idx = 0; idx < Entries.num(); idx++ ) + { + map_proc( Entries[ idx ].Key, &Entries[ idx ].Value ); + } + } + + void rehash( sw new_num ) + { + sw idx; + sw last_added_index; + HashTable_u32 new_ht = HashTable_u32::init( Hashes.get_header().Allocator ); + + new_ht.Hashes.resize( new_num ); + new_ht.Entries.reserve( new_ht.Hashes.num() ); + + for ( idx = 0; idx < new_ht.Hashes.num(); ++idx ) + new_ht.Hashes[ idx ] = -1; + + for ( idx = 0; idx < Entries.num(); ++idx ) + { + Entry& entry = Entries[ idx ]; + FindResult find_result; + + if ( new_ht.Hashes.num() == 0 ) + new_ht.grow(); + + entry = Entries[ idx ]; + find_result = new_ht.find( entry.Key ); + last_added_index = new_ht.add_entry( entry.Key ); + + if ( find_result.PrevIndex < 0 ) + new_ht.Hashes[ find_result.HashIndex ] = last_added_index; + + else + new_ht.Entries[ find_result.PrevIndex ].Next = last_added_index; + + new_ht.Entries[ last_added_index ].Next = find_result.EntryIndex; + new_ht.Entries[ last_added_index ].Value = entry.Value; + } + + destroy(); + + Hashes = new_ht.Hashes; + Entries = new_ht.Entries; + } + + void rehash_fast( void ) + { + sw idx; + + for ( idx = 0; idx < Entries.num(); idx++ ) + Entries[ idx ].Next = -1; + + for ( idx = 0; idx < Hashes.num(); idx++ ) + Hashes[ idx ] = -1; + + for ( idx = 0; idx < Entries.num(); idx++ ) + { + Entry* entry; + FindResult find_result; + } + } + + void remove( u64 key ) + { + FindResult find_result = find( key ); + + if ( find_result.EntryIndex >= 0 ) + { + Entries.remove_at( find_result.EntryIndex ); + rehash_fast(); + } + } + + void remove_entry( sw idx ) + { + Entries.remove_at( idx ); + } + + void set( u64 key, Type value ) + { + sw idx; + FindResult find_result; + + if ( Hashes.num() == 0 ) + grow(); + + find_result = find( key ); + + if ( find_result.EntryIndex >= 0 ) + { + idx = find_result.EntryIndex; + } + else + { + idx = add_entry( key ); + + if ( find_result.PrevIndex >= 0 ) + { + Entries[ find_result.PrevIndex ].Next = idx; + } + else + { + Hashes[ find_result.HashIndex ] = idx; + } + } + + Entries[ idx ].Value = value; + + if ( full() ) + grow(); + } + + sw slot( u64 key ) + { + for ( sw idx = 0; idx < Hashes.num(); ++idx ) + if ( Hashes[ idx ] == key ) + return idx; + + return -1; + } + + Array_sw Hashes; + Array_Entry Entries; + + protected: + + sw add_entry( u64 key ) + { + sw idx; + Entry entry = { key, -1 }; + idx = Entries.num(); + Entries.append( entry ); + return idx; + } + + HashTable_FindResult find( u64 key ) + { + FindResult result = { -1, -1, -1 }; + if ( Hashes.num() > 0 ) + { + result.HashIndex = key % Hashes.num(); + result.EntryIndex = Hashes[ result.HashIndex ]; + + while ( result.EntryIndex >= 0 ) + { + if ( Entries[ result.EntryIndex ].Key == key ) + break; + + result.PrevIndex = result.EntryIndex; + result.EntryIndex = Entries[ result.EntryIndex ].Next; + } + } + return result; + } + + b32 full( void ) + { + return 0.75f * Hashes.num() < Entries.num(); + } + }; + ), + 2 + , "HashTableName", (char const*) name + , "type", (char const*) type + )); + + return def_global_body( 3, ht_entry, array_ht_entry, hashtable ); +} + +struct GenHashTableRequest +{ + StrC Dependency; + StrC Type; + sw TypeSize; +}; +Array(GenHashTableRequest) GenHashTableRequests; + +void gen__hashtable_request( StrC type, sw size, StrC dep = {} ) +{ + do_once_start + array_init( GenHashTableRequests, Memory::GlobalAllocator ); + + gen_array( sw ); + do_once_end + + // Make sure we don't already have a request for the type. + for ( sw idx = 0; idx < array_count( GenHashTableRequests ); ++idx ) + { + StrC const reqest_type = GenHashTableRequests[ idx ].Type; + + if ( reqest_type.Len != type.Len ) + continue; + + if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 ) + return; + } + + GenHashTableRequest request = { dep, type, size}; + array_append( GenHashTableRequests, request ); +} +#define gen_hashtable( type ) gen__hashtable_request( { txt_to_StrC(type) }, sizeof( type )) + +u32 gen_hashtable_file() +{ + Builder + gen_buffer_file; + gen_buffer_file.open( "hashtable.Parsed.gen.hpp" ); + + gen_buffer_file.print( def_include( StrC::from("Bloat.hpp")) ); + gen_buffer_file.print( def_include( StrC::from("Array.Parsed.hpp")) ); + gen_buffer_file.print( def_include( StrC::from("array.Parsed.gen.hpp")) ); + gen_buffer_file.print( gen__hashtable_base()); + + GenHashTableRequest* current = GenHashTableRequests; + s32 left = array_count( GenHashTableRequests ); + while (left--) + { + GenHashTableRequest const& request = * current; + + Code generated_buffer = gen__hashtable( current->Type, current->TypeSize ); + + if ( request.Dependency ) + { + char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type ); + s32 cmt_len = str_len( cmt_str ); + + Code cmt = def_comment( { cmt_len, cmt_str } ); + Code include = def_include( request.Dependency ); + + gen_buffer_file.print( cmt ); + gen_buffer_file.print( include ); + } + + gen_buffer_file.print( generated_buffer ); + current++; + } + + gen_buffer_file.write(); + return 0; +} + +#endif // gen_time diff --git a/test/Parsed/Ring.Parsed.hpp b/test/Parsed/Ring.Parsed.hpp new file mode 100644 index 0000000..9bdc01e --- /dev/null +++ b/test/Parsed/Ring.Parsed.hpp @@ -0,0 +1,171 @@ +#pragma once + +#if gen_time +#include "gen.hpp" +#include "Buffer.Parsed.hpp" + +using namespace gen; + +Code gen__ring( StrC type ) +{ + static Code t_allocator_info = def_type( name(AllocatorInfo) ); + + String name; + { + char const* name_str = str_fmt_buf( "Ring_%s\0", type.Ptr ); + s32 name_len = str_len( name_str ); + + name = get_cached_string({ name_len, name_str }); + }; + + Code ring = parse_struct( token_fmt( + txt( + struct + { + using Type = ; + + static init( AllocatorInfo allocator, uw max_size ) + { + result = { 0 }; + + result.Backing = allocator; + result.Buffer = ::init( allocator, max_size + 1 ); + + if ( result.Buffer == nullptr ) + return { nullptr }; + + result.Capacity = max_size + 1; + return result; + } + + void append( s16 value ) + { + Buffer[ Head ] = value; + Head = ( Head + 1 ) % Capacity; + if ( Head == Tail ) + Tail = ( Tail + 1 ) % Capacity; + } + + inline void append( Type* values, sw num ) + { + for ( sw idx = 0; idx < num; idx++ ) + append( values[ idx ] ); + } + + bool empty( void ) + { + return Head == Tail; + } + + void free( void ) + { + Buffer.free(); + } + + bool full( void ) + { + return ( Head + 1 ) % Capacity == Tail; + } + + Type& get( void ) + { + Type& data = Buffer[ Tail ]; + Tail = ( Tail + 1 ) % Capacity; + return data; + } + + void wipe( void ) + { + Head = 0; + Tail = 0; + Buffer.wipe(); + } + + AllocatorInfo Backing; + uw Capacity; + uw Head; + uw Tail; + Buffer; + }; + ), + 3 + , "RingName", (char const*) name + , "type", (char const*) type + , "BufferName", str_fmt_buf( "Buffer_%s", type.Ptr ) + )); + + return ring; +} + +struct GenRingRequest +{ + StrC Dependency; + StrC Type; +}; +Array(GenRingRequest) GenRingRequests; + +void gen__ring_request( StrC type, sw size, StrC dep = {} ) +{ + do_once_start + array_init( GenRingRequests, Memory::GlobalAllocator ); + do_once_end + + // Make sure we don't already have a request for the type. + for ( sw idx = 0; idx < array_count( GenRingRequests ); ++idx ) + { + StrC const reqest_type = GenRingRequests[ idx ].Type; + + if ( reqest_type.Len != type.Len ) + continue; + + if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 ) + return; + } + + // Ring definition depends on a array and buffer definition. + gen__buffer_request( type, dep ); + + GenRingRequest request = { dep, type }; + array_append( GenRingRequests, request ); +} +#define gen_ring( type ) gen__ring_request( { txt_to_StrC(type) }, sizeof( type )) + +u32 gen_ring_file() +{ + Builder + gen_ring_file; + gen_ring_file.open( "ring.Parsed.gen.hpp" ); + + gen_ring_file.print( def_include( StrC::from("Bloat.hpp")) ); + gen_ring_file.print( def_include( StrC::from("buffer.Parsed.gen.hpp")) ); + // gen_ring_file.print( gen__ring_base() ); + + GenRingRequest* current = GenRingRequests; + s32 left = array_count( GenRingRequests ); + while (left--) + { + GenRingRequest const& request = * current; + + Code generated_ring = gen__ring( current->Type ); + + if ( request.Dependency ) + { + char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type ); + s32 cmt_len = str_len( cmt_str ); + + Code cmt = def_comment( { cmt_len, cmt_str } ); + Code include = def_include( request.Dependency ); + + gen_ring_file.print( cmt ); + gen_ring_file.print( include ); + } + + gen_ring_file.print( generated_ring ); + current++; + } + + gen_ring_file.write(); + return 0; +} + +#endif // gen_time diff --git a/test/test.Parsed.cpp b/test/test.Parsed.cpp index 7004e54..be0894e 100644 --- a/test/test.Parsed.cpp +++ b/test/test.Parsed.cpp @@ -1,8 +1,8 @@ #include "Bloat.cpp" #include "Parsed\Array.Parsed.hpp" -// #include "Parsed\Buffer.Parsed.hpp" -// #include "Parsed\HashTable.Parsed.hpp" -// #include "Parsed\Ring.Parsed.hpp" +#include "Parsed\Buffer.Parsed.hpp" +#include "Parsed\HashTable.Parsed.hpp" +#include "Parsed\Ring.Parsed.hpp" #include "Parsed\Sanity.Parsed.hpp" @@ -17,21 +17,22 @@ int gen_main() Memory::setup(); gen::init(); - // gen_sanity(); + gen_sanity(); gen_array( u8 ); - // gen_array( sw ); + gen_array( sw ); - // gen_buffer( u8 ); + gen_buffer( u8 ); - // gen_hashtable( u32 ); + gen_hashtable( u32 ); - // gen_ring( s16 ); + gen_ring( s16 ); + gen_ring( uw ); gen_array_file(); - // gen_buffer_file(); - // gen_hashtable_file(); - // gen_ring_file(); + gen_buffer_file(); + gen_hashtable_file(); + gen_ring_file(); gen::deinit(); Memory::cleanup();