diff --git a/project/gen.cpp b/project/gen.cpp index f43795b..6bcb6e7 100644 --- a/project/gen.cpp +++ b/project/gen.cpp @@ -6,7 +6,7 @@ namespace gen { ZPL_TABLE_DEFINE( StringTable, str_tbl_, String ); - ZPL_TABLE_DEFINE( TypeTable, type_tbl_ , Code ); + // ZPL_TABLE_DEFINE( TypeTable, type_tbl_ , Code ); namespace StaticData { @@ -15,7 +15,7 @@ namespace gen static Array(Arena) StringArenas = nullptr; static StringTable StringMap; - static TypeTable TypeMap; + // static TypeTable TypeMap; static AllocatorInfo Allocator_DataArrays = heap(); static AllocatorInfo Allocator_CodePool = heap(); @@ -54,11 +54,26 @@ namespace gen Code access_protected; Code access_private; - Code spec_constexpr; Code spec_const; + Code spec_consteval; + Code spec_constexpr; + Code spec_constinit; + Code spec_extern_linkage; Code spec_inline; - Code sepc_ptr; + Code spec_internal_linkage; + Code spec_local_persist; + Code spec_mutable; + Code spec_ptr; Code spec_ref; + Code spec_register; + Code spec_rvalue; + Code spec_static_member; + Code spec_thread_local; + Code spec_volatile; + Code spec_type_signed; + Code spec_type_unsigned; + Code spec_type_short; + Code spec_type_long; #pragma endregion Constants #pragma region AST Body Case Macros @@ -1201,15 +1216,14 @@ namespace gen if ( StringMap.entries == nullptr ) fatal( "gen::init: Failed to initialize the StringMap"); - type_tbl_init( & TypeMap, Allocator_TypeTable ); - if ( TypeMap.entries == nullptr ) - fatal( "gen::init: Failed to initialize the TypeMap" ); + //type_tbl_init( & TypeMap, Allocator_TypeTable ); + //if ( TypeMap.entries == nullptr ) + // fatal( "gen::init: Failed to initialize the TypeMap" ); } Code::Invalid = make_code(); Code::Invalid.lock(); - #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS Code& t_void_write = ccast( Code, t_void ); t_void_write = def_type( name(void) ); @@ -1224,6 +1238,7 @@ namespace gen def_constant_code_type( char ); def_constant_code_type( wchar_t ); + #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS def_constant_code_type( s8 ); def_constant_code_type( s16 ); def_constant_code_type( s32 ); @@ -1239,20 +1254,58 @@ namespace gen def_constant_code_type( f32 ); def_constant_code_type( f64 ); - # undef def_constant_code_type #endif + # undef def_constant_code_type Code& - spec_constexpr_write = ccast( Code, spec_constexpr ); - spec_constexpr_write = def_specifiers( 1, ESpecifier::Constexpr ); + access_private_write = ccast( Code, access_private ); + access_private_write = make_code(); + access_private_write->Type = ECode::Access_Private; + access_private_write->Name = get_cached_string( { sizeof("private"), "private" } ); + access_private_write.lock(); + + Code& + access_protected_write = ccast( Code, access_protected ); + access_protected_write = make_code(); + access_protected_write->Type = ECode::Access_Protected; + access_protected_write->Name = get_cached_string( { sizeof("protected"), "protected" } ); + access_protected_write.lock(); + + Code& + access_public_write = ccast( Code, access_public ); + access_public_write = make_code(); + access_public_write->Type = ECode::Access_Public; + access_public_write->Name = get_cached_string( { sizeof("public"), "public" } ); + access_public_write.lock(); + + Code& + spec_local_persist_write = ccast( Code, spec_local_persist ); + spec_local_persist_write = def_specifiers( 1, ESpecifier::Local_Persist ); # define def_constant_spec( Type_, ... ) \ Code& \ spec_##Type_##_write = ccast( Code, spec_##Type_); \ spec_##Type_##_write = def_specifiers( macro_num_args(__VA_ARGS__), __VA_ARGS__); \ - def_constant_spec( const, ESpecifier::Const ); - def_constant_spec( inline, ESpecifier::Inline ); + def_constant_spec( consteval, ESpecifier::Consteval ); + def_constant_spec( constexpr, ESpecifier::Constexpr ); + def_constant_spec( constinit, ESpecifier::Constinit ); + def_constant_spec( extern_linkage, ESpecifier::External_Linkage ); + def_constant_spec( const, ESpecifier::Const ); + def_constant_spec( inline, ESpecifier::Inline ); + def_constant_spec( internal_linkage, ESpecifier::Internal_Linkage ); + def_constant_spec( mutable, ESpecifier::Mutable ); + def_constant_spec( ptr, ESpecifier::Ptr ); + def_constant_spec( ref, ESpecifier::Ref ); + def_constant_spec( register, ESpecifier::Register ); + def_constant_spec( rvalue, ESpecifier::RValue ); + def_constant_spec( static_member, ESpecifier::Static_Member ); + def_constant_spec( thread_local, ESpecifier::Thread_Local ); + def_constant_spec( volatile, ESpecifier::Volatile) + def_constant_spec( type_signed, ESpecifier::Type_Signed ); + def_constant_spec( type_unsigned, ESpecifier::Type_Unsigned ); + def_constant_spec( type_short, ESpecifier::Type_Short ); + def_constant_spec( type_long, ESpecifier::Type_Long ); # undef def_constant_spec } @@ -1260,35 +1313,42 @@ namespace gen { using namespace StaticData; - s32 left = array_count( CodePools ); + s32 index = 0; + s32 left = array_count( CodePools ); do { - Pool* code_pool = & CodePools[left]; + Pool* code_pool = & CodePools[index]; pool_free( code_pool ); + index++; } while ( left--, left ); - left = array_count( CodeEntriesArenas ); + index = 0; + left = array_count( CodeEntriesArenas ); do { - Arena* code_entries_arena = & CodeEntriesArenas[left]; + Arena* code_entries_arena = & CodeEntriesArenas[index]; arena_free( code_entries_arena ); + index++; } while ( left--, left ); - left = array_count( StringArenas ); + index = 0; + left = array_count( StringArenas ); do { - Arena* string_arena = & StringArenas[left]; + Arena* string_arena = & StringArenas[index]; arena_free( string_arena ); + index++; } while ( left--, left ); str_tbl_destroy( & StringMap ); - type_tbl_destroy( & TypeMap ); + // type_tbl_destroy( & TypeMap ); array_free( CodePools ); array_free( CodeEntriesArenas ); + array_free( StringArenas ); } void clear_code_memory() @@ -1323,7 +1383,7 @@ namespace gen array_clear( CodeEntriesArenas ); } - type_tbl_clear( & StaticData::TypeMap ); + // type_tbl_clear( & StaticData::TypeMap ); } inline @@ -1364,6 +1424,20 @@ namespace gen return result; } + // Code get_cached_type( StrC name ) + // { + // s32 hash_length = name.Len > kilobytes(1) ? kilobytes(1) : name.Len; + // s32 key = crc32( name.Ptr, hash_length ); + // { + // Code* result = type_tbl_get( & StaticData::TypeMap, key ); + + // if ( result ) + // return * result; + // } + + // return Code::Invalid; + // } + /* Used internally to retireve a Code object form the CodePool. */ @@ -1373,11 +1447,16 @@ namespace gen AllocatorInfo allocator = { nullptr, nullptr }; - s32 left = array_count( CodePools ); + s32 index = 0; + s32 left = array_count( CodePools ); do { - if ( CodePools[left].free_list != nullptr ) - allocator = zpl::pool_allocator( & CodePools[left] ); + if ( CodePools[index].free_list != nullptr ) + { + allocator = zpl::pool_allocator( & CodePools[index] ); + break; + } + index++; } while ( left--, left ); @@ -1417,11 +1496,13 @@ namespace gen AllocatorInfo allocator = { nullptr, nullptr }; - s32 left = array_count( CodeEntriesArenas ); + s32 index = 0; + s32 left = array_count( CodeEntriesArenas ); do { - if ( arena_size_remaining(CodeEntriesArenas, ZPL_DEFAULT_MEMORY_ALIGNMENT) >= InitSize_CodeEntiresArray ) - allocator = arena_allocator( & CodeEntriesArenas[left] ); + if ( arena_size_remaining( & CodeEntriesArenas[index], ZPL_DEFAULT_MEMORY_ALIGNMENT) >= InitSize_CodeEntiresArray ) + allocator = arena_allocator( & CodeEntriesArenas[index] ); + index++; } while( left--, left ); @@ -1433,7 +1514,8 @@ namespace gen if ( arena.physical_start == nullptr ) fatal( "gen::make_code: Failed to allocate a new code entries arena - CodeEntriesArena allcoator returned nullptr." ); - allocator = arena_allocator( CodeEntriesArenas ); + allocator = arena_allocator( & arena ); + array_append( CodeEntriesArenas, arena ); } Array(AST*) entry_array; @@ -2399,6 +2481,10 @@ namespace gen return Code::Invalid; } + // Code cached = get_cached_type( name ); + // if ( cached ) + // return cached; + Code result = make_code(); result->Name = get_cached_string( name ); @@ -2411,6 +2497,12 @@ namespace gen result->add_entry( ArrayExpr ); result.lock(); + + // s32 hash_length = name.Len > kilobytes(1) ? kilobytes(1) : name.Len; + // s32 key = crc32( name.Ptr, hash_length ); + + // type_tbl_set( & StaticData::TypeMap, key, result ); + return result; } diff --git a/project/gen.hpp b/project/gen.hpp index 9e56de0..be46ec2 100644 --- a/project/gen.hpp +++ b/project/gen.hpp @@ -723,8 +723,13 @@ namespace gen Provides interning specific to Typename ASTs. Interning for other types should be possible (specifiers) with this, so long as they don't have an set of child AST entries (Use the content field). + + TODO: I'm not sure if this is viable. + ASTs are duplicated when added (parent is unique), + Parent is currently used for debug and serialization. + If these features are considered unnecessary, then caching would be fine. */ - ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeTable, type_tbl_, Code ); + // ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeTable, type_tbl_, Code ); #pragma endregion Data Structures #pragma region Gen Interface @@ -1058,131 +1063,13 @@ namespace gen // Used by the DSL but can also be used without it. # define type_ns( Name_ ) t_##Name_ -// Convienence for defining any name used with the gen interface. +// Convienence for defining any name used with the gen api. // Lets you provide the length and string literal to the functions without the need for the DSL. # define name( Id_ ) { txt_n_len( Id_ ) } // Same as name just used to indicate intention of literal for code instead of names. # define code( Code_ ) { txt_n_len( Code_ ) } -/* - gen's Domain Specific Langauge. - - Completely optional, makes the code gen syntax less verbose and cumbersome... - Since its C macros ends up looking like a lisp dialect... - - Longforms auto-define the variable. - Shorthands are just the function call. - - Anything below the make() macro is intended to be syntactically used in the follwing format: - make( , ) - { - ... - } - - Where ... are whatever is deemed necessary to produce the definition for the def( ). - - The code macros are used to embed c/c++ to insert into the desired lcoation. -*/ -#ifdef GEN_DEFINE_DSL - -// Boilerplate - -/* - In order to provide some convient syntax sugar this polymoprhic macro boilerplate is needed for: - * function( ... ) - * operator( ... ) - * params( ... ) - - macrofn based off of: https://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros - specifically: https://stackoverflow.com/a/56038661 -*/ - -# define macrofn_chooser(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, ...) _f16 -# define macrofn_recomposer(ArgsWithParentheses_) macrofn_chooser ArgsWithParentheses_ -# define macrofn_chose_from_arg_num(F, ...) macrofn_recomposer((__VA_ARGS__, F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8, F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, )) -# define marcofn_no_arg_expander(Func_) ,,,,,,,,,,,,,,,,Func_ ## _0 -# define macrofn_finder(Func_, ...) macrofn_chose_from_arg_num(Func_, marcofn_no_arg_expander __VA_ARGS__ (Func_)) -# define macrofn_polymorphic(Func_, ...) macrofn_finder(Func_, __VA_ARGS__)(__VA_ARGS__) - -# define function_5( Name_, Params_, RetType_, Specifiers_, Body_ ) gen::def_function( txt_n_len( Name_ ), macro_expand( Params_ ), type_ns(RetType_), Specifiers_, Body_ ) -# define function_4( Name_, Params_, RetType_, Specifiers_ ) gen::def_function( txt_n_len( Name_ ), macro_expand( Params_ ), type_ns(RetType_), Specifiers_ ) -# define function_3( Name_, Params_, RetType_ ) gen::def_function( txt_n_len( Name_ ), macro_expand( Params_ ), type_ns(RetType_) ) -# define function_2( Name_, Params_ ) gen::def_function( txt_n_len( Name_ ), macro_expand( Params_ ) ) -# define function_1( Name_ ) gen::def_function( txt_n_len( Name_ ) ) - -# define params_12( T_1, V_1, T_2, V_2, T_3, V_3, T_4, V_4, T_5, V_5, T_6, V_6 ) gen::def_params( 12, type_ns(T_1), txt_n_len( V_1), type_ns(T_2), txt_n_len( V_2), type_ns(T_3), txt_n_len( V_3), type_ns(T_4), txt_n_len( V_4), type_ns(T_5), txt_n_len( V_5), type_ns(T_6), txt_n_len(V_6)) -# define params_10( T_1, V_1, T_2, V_2, T_3, V_3, T_4, V_4, T_5, V_5 ) gen::def_params( 10, type_ns(T_1), txt_n_len( V_1), type_ns(T_2), txt_n_len( V_2), type_ns(T_3), txt_n_len( V_3), type_ns(T_4), txt_n_len( V_4), type_ns(T_5), txt_n_len( V_5)) -# define params_8( T_1, V_1, T_2, V_2, T_3, V_3, T_4, V_4 ) gen::def_params( 8, type_ns(T_1), txt_n_len( V_1), type_ns(T_2), txt_n_len( V_2), type_ns(T_3), txt_n_len( V_3), type_ns(T_4), txt_n_len( V_4) ) -# define params_6( T_1, V_1, T_2, V_2, T_3, V_3 ) gen::def_params( 6, type_ns(T_1), txt_n_len( V_1), type_ns(T_2), txt_n_len( V_2), type_ns(T_3), txt_n_len( V_3)) -# define params_4( T_1, V_1, T_2, V_2 ) gen::def_params( 4, type_ns(T_1), txt_n_len( V_1), type_ns(T_2), txt_n_len( V_2)) -# define params_2( T_1, V_1 ) gen::def_param ( type_ns(T_1), txt_n_len( V_1)) -# define params_bad static_assert("params(...): Invalid number of parameters provided.") -# define params_11 params_bad -# define params_9 params_bad -# define params_7 params_bad -# define params_5 params_bad -# define params_3 params_bad -# define params_1 params_bad - -// Upfront - -# define comment( Value_ ) gen::def_comment( sizeof(Value), Value_ ) -# define attribute( Value_ ) gen::def_attribute( txt_n_len(Value_) ) -# define class( Name_, ... ) gen::def_class( txt_n_len(Name_), __VA_ARGS__ ) -# define enum( Name_, Type_, Body_ ) gen::def_enum ( txt_n_len(Name_), type_ns(Type_), Body_ ) -# define extern_linkage( Name_, Body_ ) gen::def_extern_linkage( txt_n_len(Name_), Body_ ) -# define function( ... ) macrofn_polymorphic( function, __VA_ARGS__ ) -# define namespace( Name_, Body_ ) gen::def_namespace ( txt_n_len(Name_), Body_ ) -# define operator( Op_, ... ) macrofn_polymorphic( operator, __VA_ARGS__ ) -# define params( ... ) macrofn_polymorphic( params, __VA_ARGS__ ) -# define specifiers( ... ) gen::def_specifiers ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define struct( Name_, ... ) gen::def_struct ( txt_n_len(Name_), __VA_ARGS__ ) -# define variable( Type_, Name_, ... ) gen::def_variable ( type_ns(Type_), txt_n_len(Name_), __VA_ARGS__ ) -# define type( Value_, ... ) gen::def_type ( txt_n_len(Value_), __VA_ARGS__ ) -# define type_fmt( Fmt_, ... ) gen::def_type ( bprintf( Fmt_, __VA_ARGS__ ) ) -# define union( Name_, ... ) gen::def_union ( txt_n_len(Name_), __VA_ARGS__ ) -# define using( Name_, ... ) gen::def_using ( txt_n_len(Name_), __VA_ARGS__ ) - -# define class_body( ... ) gen::def_class_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define enum_body( ... ) gen::def_enum_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define extern_linkage_body( ... ) gen::def_extern_linkage_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define global_body( ... ) gen::def_global_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define function_body( ... ) gen::def_function_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define namespace_body( ... ) gen::def_namespace_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define operator_body( ... ) gen::def_operator_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define struct_body( ... ) gen::def_struct_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) -# define union_body( ... ) gen::def_union_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ ) - -# ifdef GEN_FEATURE_INCREMENTAL -// Incremental - -# define make( ConstructType_, Name_, ... ) Code Name_ = make_##ConstructType_( txt_n_len(Name_), __VA_ARGS__ ); -# endif - -# ifdef GEN_FEATURE_PARSING -// Parsing - -# define class_code( ... ) gen::parse_class ( txt_n_len( __VA_ARGS__ )) -# define enum_code( ... ) gen::parse_enum ( txt_n_len( __VA_ARGS__ )) -# define function_code( ... ) gen::parse_function ( txt_n_len( __VA_ARGS__ )) -# define global_body_code( ... ) gen::parse_global_body( txt_n_len( __VA_ARGS__ )) -# define operator_code( ... ) gen::parse_operator ( txt_n_len( __VA_ARGS__ )) -# define namespace_code( ... ) gen::parse_namespace ( txt_n_len( __VA_ARGS__ )) -# define struct_code( ... ) gen::parse_struct ( txt_n_len( __VA_ARGS__ )) -# define variable_code( ... ) gen::parse_variable ( txt_n_len( __VA_ARGS__ )) -# define type_code( ... ) gen::parse_type ( txt_n_len( __VA_ARGS__ )) -# define typedef_code( ... ) gen::parse_typedef ( txt_n_len( __VA_ARGS__ )) -# define union_code( ... ) gen::parse_union ( txt_n_len( __VA_ARGS__ )) -# define using_code( ... ) gen::parse_code ( txt_n_len( __VA_ARGS__ )) -# endif - -// Untyped - -# define code_str( ... ) gen::untyped_str ( txt_n_len(__VA_ARGS__) ) -# define code_fmt( Fmt_, ... ) gen::untyped_fmt ( Fmt_, __VA_ARGS__ ) -# define code_token( Fmt_, ... ) gen::untyped_token_fmt( Fmt_, macro_num_args( __VA_ARGS__) / 2, __VA_ARGS__ ) -#endif #pragma endregion Macros #pragma region Constants @@ -1241,11 +1128,26 @@ namespace gen extern Code access_protected; extern Code access_private; - extern Code spec_constexpr; extern Code spec_const; + extern Code spec_consteval; + extern Code spec_constexpr; + extern Code spec_constinit; + extern Code spec_extern_linkage; extern Code spec_inline; + extern Code spec_internal_linkage; + extern Code spec_local_persist; + extern Code spec_mutable; extern Code spec_ptr; extern Code spec_ref; + extern Code spec_register; + extern Code spec_rvalue; + extern Code spec_static_member; + extern Code spec_thread_local; + extern Code spec_volatile; + extern Code spec_type_signed; + extern Code spec_type_unsigned; + extern Code spec_type_short; + extern Code spec_type_long; } #pragma endregion Constants