diff --git a/project/gen.cpp b/project/gen.cpp index 743f524..e4fce32 100644 --- a/project/gen.cpp +++ b/project/gen.cpp @@ -71,10 +71,11 @@ namespace gen static StringTable StringMap; static TypeTable TypeMap; - static sw InitSize_CodePool = megabytes(64); - static sw InitSize_StringArena = megabytes(32); - static sw InitSize_StringTable = megabytes(4); - static sw InitSize_TypeTable = megabytes(4); + static sw InitSize_CodePool = megabytes(64); + static sw InitSize_StringTable = megabytes(4); + static sw InitSize_TypeTable = megabytes(4); + + static sw SizePer_StringArena = megabytes(32); static allocator Allocator_CodePool = heap(); static allocator Allocator_StringArena = heap(); @@ -111,33 +112,6 @@ namespace gen Code spec_inline; #pragma endregion CONSTANTS - /* - Used internally to retireve a Code object form the CodePool. - */ - static Code make_code() - { - using namespace StaticData; - -# ifndef GEN_CODE_USE_SOA - ct CodePOD Invalid = { ECode::Invalid, false, nullptr, nullptr, nullptr, { nullptr } }; - - array_append( CodePool, Invalid ); - - return pcast( Code, array_back( CodePool )); -# else - - array_append( CodePool::Type, ECode::Invalid ); - array_append( CodePool::Readonly, false ); - array_append( CodePool::Name, nullptr ); - array_append( CodePool::Comment, nullptr ); - array_append( CodePool::Data, { nullptr } ); - - Code code { array_count( CodePool::Type) - 1 }; - - return code; -# endif - } - # pragma region AST bool AST::add( AST* other ) { @@ -356,7 +330,7 @@ namespace gen array_init( StaticData::StringArenas, heap() ); arena string_arena; - arena_init_from_allocator( & string_arena, StaticData::Allocator_StringArena, StaticData::InitSize_StringArena ); + arena_init_from_allocator( & string_arena, StaticData::Allocator_StringArena, StaticData::SizePer_StringArena ); str_tbl_init( & StaticData::StringMap, StaticData::Allocator_StringTable ); type_tbl_init( & StaticData::TypeMap, StaticData::Allocator_TypeTable ); @@ -427,7 +401,7 @@ namespace gen if ( StringArenas->total_allocated + str_length > StringArenas->total_size ) { arena new_arena; - arena_init_from_allocator( & new_arena, Allocator_StringArena, InitSize_StringArena ); + arena_init_from_allocator( & new_arena, Allocator_StringArena, SizePer_StringArena ); array_append( StringArenas, new_arena ); @@ -438,7 +412,7 @@ namespace gen } // Will either make or retrive a code string. - string code_string( char const* cstr, s32 length ) + ro_string cached_string( char const* cstr, s32 length ) { s32 hash_length = length > kilobytes(1) ? kilobytes(1) : length; @@ -451,11 +425,40 @@ namespace gen return * result; } + * result = string_make( get_string_allocator( length ), cstr ); + str_tbl_set( & StaticData::StringMap, key, * result ); return * result; } + /* + Used internally to retireve a Code object form the CodePool. + */ + Code make_code() + { + using namespace StaticData; + +# ifndef GEN_CODE_USE_SOA + ct CodePOD Invalid = { nullptr, nullptr, nullptr, nullptr, ECode::Invalid, EOperator::Invalid, false, {0} }; + + array_append( CodePool, Invalid ); + + return pcast( Code, array_back( CodePool )); +# else + + array_append( CodePool::Type, ECode::Invalid ); + array_append( CodePool::Readonly, false ); + array_append( CodePool::Name, nullptr ); + array_append( CodePool::Comment, nullptr ); + array_append( CodePool::Data, { nullptr } ); + + Code code { array_count( CodePool::Type) - 1 }; + + return code; +# endif + } + void set_init_reserve_code_pool( sw size ) { StaticData::InitSize_CodePool = size; @@ -501,6 +504,12 @@ namespace gen { using namespace ECode; + if ( length <= 0 ) + { + log_failure( "gen::def_class: Invalid name length provided - %d", length ); + return Code::Invalid; + } + if ( name == nullptr ) { log_failure( "gen::def_class: name is null"); @@ -509,35 +518,35 @@ namespace gen if ( parent && parent->Type != Class || parent->Type != Struct ) { - log_failure( "gen::def_class: parent provided is not type 'Class' or 'Struct' - Type: %s", parent->type_str() ); + log_failure( "gen::def_class: parent provided is not type 'Class' or 'Struct' - Type: %s", parent->debug_str() ); return Code::Invalid; } if ( specifiers && specifiers->Type != Specifiers ) { - log_failure( "gen::def_class: specifiers was not a 'Specifiers' type - Type: %s", specifiers->type_str() ); + log_failure( "gen::def_class: specifiers was not a 'Specifiers' type - Type: %s", specifiers->debug_str() ); return Code::Invalid; } - switch ( body->Type ) - { - case Class_Body: - case Untyped: - break; - - default: - log_failure("gen_def_class: body must be either of Function_Body or Untyped type."); - return Code::Invalid; - } - Code result = make_code(); - result->Name = code_string( name, length ); + result->Name = cached_string( name, length ); array_init( result->Entries, StaticData::Allocator_CodePool ); if ( body ) { + switch ( body->Type ) + { + case Class_Body: + case Untyped: + break; + + default: + log_failure("gen::def_class: body must be either of Class_Body or Untyped type - %s", body->debug_str()); + return Code::Invalid; + } + result->Type = Class; result->add_entry( body ); } @@ -558,21 +567,61 @@ namespace gen Code def_enum( s32 length, char const* name, Code type, Code body ) { + using namespace ECode; + if ( length <= 0 ) { - log_failure( "gen_def_enum: Invalid name length provided - %d", length ); + log_failure( "gen::def_enum: Invalid name length provided - %d", length ); + return Code::Invalid; } if ( name == nullptr ) { - log_failure( "gen::def_class: name is null"); + log_failure( "gen::def_class: name is null" ); return Code::Invalid; } + if ( type && type->Type != Typename ) + { + log_failure( "gen::def_enum: enum underlying type provided was not of type Typename: %s", type->debug_str() ); + return Code::Invalid; + } + Code + result = make_code(); + result->Name = cached_string( name, length ); + + if ( body ) + { + switch ( body->Type ) + { + case Enum_Body: + case Untyped: + break; + + default: + log_failure( "gen::def_enum: body must be of Enum_Body or Untyped type %s", body->debug_str()); + return Code::Invalid; + } + + result->Type = Enum; + result->add_entry( body ); + } + else + { + result->Type = Enum_FwdDecl; + } + + if ( type ) + { + result->add_entry( type ); + } + + result.lock(); + return result; } - Code def_function( char const* name + Code def_function( s32 length, char const* name , Code specifiers , Code params , Code ret_type @@ -581,52 +630,76 @@ namespace gen { using namespace ECode; + if ( length <= 0 ) + { + log_failure( "gen::def_function: Invalid name length provided - %d", length ); + return Code::Invalid; + } + + if ( name == nullptr ) + { + log_failure( "gen::def_function: name is null" ); + return Code::Invalid; + } + if ( specifiers && specifiers->Type != Specifiers ) { - log_failure( "gen::def_function: specifiers was not a `Specifiers` type" ); + log_failure( "gen::def_function: specifiers was not a `Specifiers` type %s", specifiers->debug_str() ); return Code::Invalid; } if ( params && params->Type != Parameters ) { - log_failure( "gen::def_function: params was not a `Parameters` type" ); + log_failure( "gen::def_function: params was not a `Parameters` type %s", params->debug_str() ); return Code::Invalid; } if ( ret_type == nullptr || ret_type->Type != Typename ) { - log_failure( "gen::def_function: ret_type was not a Typename" ); + log_failure( "gen::def_function: ret_type was not a Typename %s", ret_type->debug_str() ); return Code::Invalid; } - switch ( body->Type ) - { - case Function_Body: - case Untyped: - break; - - default: - { - log_failure("gen::def_function: body must be either of Function_Body or Untyped type."); - return Code::Invalid; - } - } - - s32 name_length = zpl_strnlen( name, MaxNameLength ); - Code result = make_code(); - result->Name = code_string( name, name_length ); - result->Type = Function; + result->Name = cached_string( name, length ); array_init( result->Entries, StaticData::Allocator_CodePool ); - result->add_entry( body ); + if ( body ) + { + switch ( body->Type ) + { + case Function_Body: + case Untyped: + break; + + default: + { + log_failure("gen::def_function: body must be either of Function_Body or Untyped type. %s", body->debug_str()); + return Code::Invalid; + } + } + + result->Type = Function; + result->add_entry( body ); + } + else + { + result->Type = Function_FwdDecl; + } if ( specifiers ) result->add_entry( specifiers ); - result->add_entry( ret_type ); + if ( ret_type ) + { + result->add_entry( ret_type ); + } + else + { + result->add_entry( type_ns(void) ); + } if ( params ) result->add_entry( params ); @@ -635,6 +708,45 @@ namespace gen return result; } + Code def_namespace( s32 length, char const* name, Code body ) + { + using namespace ECode; + + if ( length <= 0 ) + { + log_failure( "gen::def_namespace: Invalid name length provided - %d", length ); + return Code::Invalid; + } + + if ( name == nullptr ) + { + log_failure( "gen::def_namespace: name is null" ); + return Code::Invalid; + } + + Code + result = make_code(); + result->Type = Namespace; + result->Name = cached_string( name, length ); + + array_init( result->Entries, g_allocator ); + + if ( body->Type != Namespace_Body || body->Type != Untyped ) + { + log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body->debug_str()); + return Code::Invalid; + } + + result->add_entry( body ); + + return result; + } + + Code def_operator( OperatorT Op, Code params, Code ret_type, Code specifiers, Code body ) + { + + } + Code def_function_body( s32 num, ... ) { using namespace ECode; @@ -763,7 +875,7 @@ namespace gen char const* name = va_arg(va, char const*); s32 name_length = zpl_strnlen(name, MaxNameLength); - result->Name = code_string( name, name_length ); + result->Name = cached_string( name, name_length ); array_init( result->Entries, g_allocator ); @@ -785,7 +897,7 @@ namespace gen Code param = make_code(); param->Type = Parameters; - param->Name = code_string(name, name_length); + param->Name = cached_string(name, name_length); array_init( param->Entries, StaticData::Allocator_CodePool ); @@ -806,27 +918,6 @@ namespace gen return result; } - Code def_namespace( char const* name, Code body ) - { - using namespace ECode; - - Code - result = make_code(); - result->Type = Namespace; - - array_init( result->Entries, g_allocator ); - - if ( body->Type != Namespace_Body || body->Type != Untyped ) - { - log_failure("gen::def_namespace: body is not of namespace or untyped type"); - return Code::Invalid; - } - - result->add_entry( body ); - - return result; - } - Code def_namespace_body( s32 num, ... ) { using namespace ECode; @@ -874,10 +965,19 @@ namespace gen if ( num <= 0 ) fatal("gen::make_specifier: num cannot be zero or less"); + // This should be more than enough... + static u8 FixedSizedBuffer[kilobytes(1024)]; + + static arena str_arena; + do_once_start + arena_init_from_memory( & str_arena, FixedSizedBuffer, kilobytes(1024) ); + do_once_end + Code result = make_code(); result->Type = ECode::Specifiers; - result->Content = string_make( g_allocator, "" ); + + string crafted = string_make( arena_allocator( & str_arena ), "" ); va_list va; va_start(va, num); @@ -888,26 +988,42 @@ namespace gen switch ( type ) { case ESpecifier::Alignas: - result->Content = string_append_fmt( result->Content, "%s(%d)", ESpecifier::to_str(type), va_arg(va, u32) ); + crafted = string_append_fmt( result->Content, "%s(%d)", ESpecifier::to_str(type), va_arg(va, u32) ); break; default: const char* str = ESpecifier::to_str(type); - result->Content = string_append_fmt( result->Content, "%s", str ); + crafted = string_append_fmt( result->Content, "%s", str ); break; } } while ( --num, num ); va_end(va); + result->Content = cached_string( crafted, string_length( crafted ) ); + + arena_free( & str_arena ); + return result; } - Code def_struct( char const* name, Code body, Code parent, Code specifiers ) + Code def_struct( u32 length, char const* name, Code body, Code parent, Code specifiers ) { using namespace ECode; + if ( length <= 0 ) + { + log_failure( "gen::def_function: Invalid name length provided - %d", length ); + return Code::Invalid; + } + + if ( name == nullptr ) + { + log_failure( "gen::def_function: name is null" ); + return Code::Invalid; + } + if ( specifiers && specifiers->Type != Specifiers ) { log_failure( "gen::def_struct: specifiers was not a `Specifiers` type" ); @@ -929,7 +1045,7 @@ namespace gen Code result = make_code(); result->Type = Struct; - result->Name = string_make( g_allocator, name ); + result->Name = cached_string( name, length ); array_init( result->Entries, g_allocator ); @@ -987,8 +1103,20 @@ namespace gen return result; } - Code def_variable( Code type, char const* name, Code value, Code specifiers ) + Code def_variable( Code type, u32 length, char const* name, Code value, Code specifiers ) { + if ( length <= 0 ) + { + log_failure( "gen::def_function: Invalid name length provided - %d", length ); + return Code::Invalid; + } + + if ( name == nullptr ) + { + log_failure( "gen::def_function: name is null" ); + return Code::Invalid; + } + if ( specifiers && specifiers->Type != ECode::Specifiers ) { log_failure( "gen::def_variable: specifiers was not a `Specifiers` type" ); @@ -1009,7 +1137,7 @@ namespace gen Code result = make_code(); - result->Name = string_make( g_allocator, name ); + result->Name = cached_string( name, length ); result->Type = ECode::Variable; array_init( result->Entries, g_allocator ); @@ -1025,21 +1153,45 @@ namespace gen return result; } - Code def_type( char const* name, Code specifiers ) + Code def_type( u32 length, char const* name, Code specifiers ) { + if ( length <= 0 ) + { + log_failure( "gen::def_function: Invalid name length provided - %d", length ); + return Code::Invalid; + } + + if ( name == nullptr ) + { + log_failure( "gen::def_function: name is null" ); + return Code::Invalid; + } + Code result = make_code(); - result->Name = string_make( g_allocator, name ); + result->Name = cached_string( name, length ); result->Type = ECode::Typename; return result; } - Code def_using( char const* name, Code type ) + Code def_using( u32 length, char const* name, Code type ) { + if ( length <= 0 ) + { + log_failure( "gen::def_function: Invalid name length provided - %d", length ); + return Code::Invalid; + } + + if ( name == nullptr ) + { + log_failure( "gen::def_function: name is null" ); + return Code::Invalid; + } + Code result = make_code(); - result->Name = string_make( g_allocator, name ); + result->Name = cached_string( name, length ); result->Type = ECode::Using; array_init( result->Entries, g_allocator ); @@ -1295,7 +1447,7 @@ namespace gen Code result = make_code(); - result->Name = string_make( g_allocator, name ); + result->Name = cached_string( name, name_length ); result->Type = ECode::Function; array_init( result->Entries, g_allocator ); diff --git a/project/gen.hpp b/project/gen.hpp index 46d42cf..4ccef06 100644 --- a/project/gen.hpp +++ b/project/gen.hpp @@ -18,6 +18,22 @@ * Modern C++ (STL library) features * Modern C++ RTTI : This is kinda covered with the last point, but just wanted to emphasize. + Exceptions brought in from "Modern C++": + Specifiers: + * consteval + * constinit + * explicit + * export + * noexcept + * import + * final + * module + * override + * && + * virtual + + These features are in as they are just specifiers and aren't hard to implement seralization or validation. + The AST is managed by the library and provided the user via its interface prodedures. Notes: @@ -60,6 +76,7 @@ * def_class * def_enum * def_enum_class + * def_friend * def_function * def_namespace * def_operator @@ -113,6 +130,7 @@ * parse_class * parse_enum + * parse_friend * parse_function * parse_global_body * parse_namespace @@ -173,6 +191,8 @@ #define GEN_DEFINE_DSL #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS #define GEN_USE_FATAL +#define GEN_FEATURE_EDITOR +#define GEN_FEATURE_SCANNER #ifdef gen_time @@ -192,37 +212,42 @@ namespace gen namespace ECode { - enum Type : u8 - { - Invalid, - Untyped, - Access_Public, - Access_Private, - Access_Protected, - Class, - Class_FwdDecl, - Class_Body, - Enum, - Enum_FwdDecl, - Enum_Body, - Friend, - Global_Body, - Namespace, - Namespace_Body, - Parameters, - Function, - Function_FwdDecl, - Function_Body, - Specifiers, - Struct, - Struct_FwdDecl, - Struct_Body, - Variable, - Typedef, - Typename, - Using, +# define Define_Types \ + Entry( Untyped ) \ + Entry( Access_Public ) \ + Entry( Access_Private ) \ + Entry( Access_Protected ) \ + Entry( Class ) \ + Entry( Class_FwdDecl ) \ + Entry( Class_Body ) \ + Entry( Enum ) \ + Entry( Enum_FwdDecl ) \ + Entry( Enum_Body ) \ + Entry( Friend ) \ + Entry( Global_Body ) \ + Entry( Namespace ) \ + Entry( Namespace_Body ) \ + Entry( Parameters ) \ + Entry( Function ) \ + Entry( Function_FwdDecl ) \ + Entry( Function_Body ) \ + Entry( Specifiers ) \ + Entry( Struct ) \ + Entry( Struct_FwdDecl ) \ + Entry( Struct_Body ) \ + Entry( Variable ) \ + Entry( Typedef ) \ + Entry( Typename ) \ + Entry( Using ) - Num_Types + enum Type : u32 + { +# define Entry( Type ) Type, + Define_Types +# undef Entry + + Num_Types, + Invalid }; inline @@ -230,49 +255,72 @@ namespace gen { static char const* lookup[Num_Types] = { - "Invalid", - "Untyped", - "Access_Public", - "Access_Private", - "Access_Protected", - "Class", - "Class_FwdDecl", - "Class_Body", - "Enum", - "Enum_FwdDecl", - "Enum_Body", - "Function", - "Function_FwdDecl", - "Function_Body", - "Global_Body", - "Namespace", - "Namespace_Body", - "Parameters", - "Specifiers", - "Struct", - "Struct_Body", - "Variable", - "Typedef", - "Typename", - "Using", +# define Entry( Type ) txt( Type ), + Define_Types +# undef Entry }; return lookup[ type ]; } + +# undef Define_Types } using CodeT = ECode::Type; namespace EOperator { - enum Type : u8 - { - Add, - Subtract, - Multiply, - Divide, - Modulo, +# define Define_Operators \ + Entry( Assign, = ) \ + Entry( Assign_Add, += ) \ + Entry( Assign_Subtract, -= ) \ + Entry( Assgin_Multiply, *= ) \ + Entry( Assgin_Divide, /= ) \ + Entry( Assgin_Modulo, %= ) \ + Entry( Assgin_BAnd, &= ) \ + Entry( Assgin_BOr, &= ) \ + Entry( Assign_BXOr, ^= ) \ + Entry( Assign_LShift, <<= ) \ + Entry( Assign_RShift, >>= ) \ + Entry( Increment, ++ ) \ + Entry( Decrement, -- ) \ + Entry( Unary_Plus, + ) \ + Entry( Unary_Minus, - ) \ + Entry( Add, + ) \ + Entry( Subtract, - ) \ + Entry( Multiply, * ) \ + Entry( Divide, / ) \ + Entry( Modulo, % ) \ + Entry( BNot, ~ ) \ + Entry( BAnd, & ) \ + Entry( BOr, | ) \ + Entry( BXOr, ^ ) \ + Entry( LShift, << ) \ + Entry( RShift, >> ) \ + Entry( LNot, ! ) \ + Entry( LAnd, && ) \ + Entry( LOr, || ) \ + Entry( Equals, == ) \ + Entry( NotEquals, != ) \ + Entry( Lesser, < ) \ + Entry( Greater, > ) \ + Entry( LesserEqual, <= ) \ + Entry( GreaterEqual, >= ) \ + Entry( Subscript, [] ) \ + Entry( Indirection, * ) \ + Entry( AddressOf, & ) \ + Entry( MemberOfPointer, -> ) \ + Entry( PtrToMemOfPtr, ->* ) \ + Entry( FunctionCall, () ) - Num_Ops + enum Type : u32 + { +# define Entry( Type, Token ) Type, + Define_Operators +# undef Entry + Comma, + + Num_Ops, + Invalid }; inline @@ -280,41 +328,74 @@ namespace gen { local_persist char const* lookup[ Num_Ops ] = { - "+", - "-", - "*", - "/", +# define Entry( Type, Token ) txt(Token), + Define_Operators +# undef Entry + "," }; return lookup[ op ]; } +# undef Define_Operators } using OperatorT = EOperator::Type; namespace ESpecifier { - enum Type : u8 +# if defined(ZPL_SYSTEM_WINDOWS) +# define API_Export_Code __declspec(dllexport) +# define API_Import_Code __declspec(dllimport) +# elif defined(ZPL_SYSTEM_MACOS) +# define API_Export_Code __attribute__ ((visibility ("default"))) +# define API_Import_Code __attribute__ ((visibility ("default"))) +# endif + +# if defined(ZPL_MODULE_THREADING) +# define Thread_Local_Code thread_local +# else +# define Thread_Local_Code "NOT DEFINED" +# endif + + // Entry( Explicit, explicit ) \ + + #define Define_Specifiers \ + Entry( API_Import, API_Export_Code ) \ + Entry( API_Export, API_Import_Code ) \ + Entry( Attribute, "You cannot stringize an attribute this way" ) \ + Entry( Alignas, alignas ) \ + Entry( Const, const ) \ + Entry( C_Linkage, extern "C" ) \ + Entry( Consteval, consteval ) \ + Entry( Constexpr, constexpr ) \ + Entry( Constinit, constinit ) \ + Entry( Export, export ) \ + Entry( External_Linkage, extern ) \ + Entry( Import, import ) \ + Entry( Inline, inline ) \ + Entry( Internal_Linkage, static ) \ + Entry( Final, final ) \ + Entry( Local_Persist, static ) \ + Entry( Module, module ) \ + Entry( Mutable, mutable ) \ + Entry( NoExcept, noexcept ) \ + Entry( Override, override ) \ + Entry( Pointer, * ) \ + Entry( Reference, & ) \ + Entry( Register, register ) \ + Entry( RValue, && ) \ + Entry( Static_Member, static ) \ + Entry( Thread_Local, Thread_Local_Code ) \ + Entry( Virtual, virtual ) \ + Entry( Volatile, volatile ) + + enum Type : u32 { - Attribute, - Alignas, - Constexpr, - Const, - Inline, - Pointer, - Reference, - RValue, +# define Entry( Specifier, Code ) Specifier, + Define_Specifiers +# undef Entry - C_Linkage, - API_Import, - API_Export, - External_Linkage, - Internal_Linkage, - Static_Member, - Local_Persist, - Thread_Local, - - Invalid, Num_Specifiers, + Invalid, }; // Specifier to string @@ -323,29 +404,9 @@ namespace gen { local_persist char const* lookup[ Num_Specifiers ] = { - "alignas", - "constexpr", - "const", - "inline", - "*", - "&", - "&&", - - "extern \"C\"", - -# if defined(ZPL_SYSTEM_WINDOWS) - "__declspec(dllexport)", - "__declspec(dllimport)", -# elif defined(ZPL_SYSTEM_MACOS) - "__attribute__ ((visibility (\"default\")))", - "__attribute__ ((visibility (\"default\")))", -# endif - - "extern", - "static", - "static", - "static", - "thread_local" +# define Entry( Spec_, Code_ ) txt(Code_), + Define_Specifiers +# undef Entry }; return lookup[ specifier ]; @@ -394,11 +455,13 @@ namespace gen forceinline void add_entry( AST* other ) { - array_append( Entries, other ); + Code to_add = other->Parent ? + other->duplicate() : other; - other->Parent = this; + array_append( Entries, to_add ); + + to_add->Parent = this; } - forceinline AST* body() { @@ -408,6 +471,8 @@ namespace gen forceinline bool check(); + Code duplicate(); + forceinline bool has_entries() const { @@ -440,6 +505,27 @@ namespace gen return Type != ECode::Invalid; } + forceinline + char const* debug_str() const + { + char const* fmt = txt( + \nCode Debug: + \nType : %s + \nReadonly: %s + \nParent : %s + \nName : %s + \nComment : %s + ); + + bprintf( fmt + , type_str() + , Readonly ? "true" : "false" + , Parent ? Parent->Name : "" + , Name ? Name : "" + , Comment ? Comment : "" + ); + } + forceinline char const* type_str() const { @@ -449,16 +535,18 @@ namespace gen string to_string() const; #pragma endregion Member Procedures - #define Using_Code_POD \ - CodeT Type; \ - bool Readonly; \ - AST* Parent; \ - string Name; \ - string Comment; \ - union { \ - array(AST*) Entries; \ - string Content; \ - }; + #define Using_Code_POD \ + AST* Parent; \ + ro_string Name; \ + ro_string Comment; \ + union { \ + array(AST*) Entries; \ + ro_string Content; \ + }; \ + CodeT Type; \ + OperatorT Op; \ + bool Readonly; \ + u8 _64_Align[23]; Using_Code_POD; }; @@ -468,6 +556,9 @@ namespace gen Using_Code_POD; }; + ct u32 sizeof_AST = sizeof(AST); + ct u32 sizeof_CODE = sizeof(CodePOD); + // Its intended for the AST to have equivalent size to its POD. // All extra functionality within the AST namespace should just be syntatic sugar. static_assert( sizeof(AST) == sizeof(CodePOD), "ERROR: AST IS NOT POD" ); @@ -594,6 +685,8 @@ namespace gen */ ZPL_TABLE_DECLARE( ZPL_EXTERN, StringTable, str_tbl_, string ); + using ro_string = char const*; + /* Type registy: Used to store Typename ASTs. Types are registered by their string literal value. @@ -615,6 +708,19 @@ namespace gen // And rather get rid of current code asts instead of growing the pool memory. void clear_code_pool(); + /* + Used internally to retrive or make string allocations. + Strings are stored in a series of string arenas of fixed size (SizePer_StringArena) + */ + ro_string cached_string( char const* cstr, s32 length ); + + /* + This provides a fresh Code AST struct. + The gen interface use this as their method from getting a new AST object from the CodePool. + Use this if you want to make your own API for formatting the supported Code Types. + */ + Code make_code(); + // Set these before calling gen's init() procedure. void set_init_reserve_code_pool ( sw size ); @@ -632,6 +738,7 @@ namespace gen Code def_class ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode, Code body = NoCode ); Code def_enum ( char const* name, Code type = NoCode, Code body = NoCode); Code def_enum ( s32 length, char const* name, Code type = NoCode, Code body = NoCode ); + Code def_friend ( Code symbol ); Code def_function ( char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); Code def_function ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode ); Code def_namespace ( char const* name, Code body ); @@ -695,6 +802,7 @@ namespace gen # pragma region Parsing Code parse_class ( s32 length, char const* class_def ); Code parse_enum ( s32 length, char const* enum_def ); + Code parse_friend ( s32 length, char const* friend_def ); Code parse_function ( s32 length, char const* fn_def ); Code parse_global_body( s32 length, char const* body_def ); Code parse_namespace ( s32 length, char const* namespace_def ); @@ -705,8 +813,9 @@ namespace gen Code parse_typedef ( s32 length, char const* typedef_def ); Code parse_using ( s32 length, char const* using_def ); - s32 parse_classes ( s32 length, char const* class_defs, Code* out_classes ); - s32 parse_enums ( s32 length, char const* enum_defs, Code* out_enums ); + s32 parse_classes ( s32 length, char const* class_defs, Code* out_class_codes ); + s32 parse_enums ( s32 length, char const* enum_defs, Code* out_enum_codes ); + s32 parse_friends ( s32 length, char const* friend_defs, Code* out_friend_codes ); s32 parse_functions ( s32 length, char const* fn_defs, Code* out_fn_codes ); s32 parse_namespaces( s32 length, char const* namespace_defs, Code* out_namespaces_codes ); s32 parse_operators ( s32 length, char const* operator_defs, Code* out_operator_codes ); @@ -740,25 +849,10 @@ namespace gen }; - struct AddPolicy - { - // Not sure yet - }; - - struct ReplacePolicy - { - - }; - - struct RemovePolicy - { - - }; - struct SymbolInfo { - char const* File; - Code Signature; + ro_string File; + Code Signature; }; struct Editor @@ -770,27 +864,75 @@ namespace gen Remove }; - struct RequestEntry + struct SymbolData { - RequestType Type; - SymbolInfo Info; Policy Policy; + SymbolInfo Info; }; + struct RequestEntry + { + union { + SymbolData Symbol; + string Specification; + }; + RequestType Type; + }; - zpl_file File; + struct Receipt + { + ro_string File; + Code Found; + Code Written; + bool Result; + }; + + static allocator Allocator; + + static void set_allocator( allocator mem_allocator ); + + array(zpl_file) Files; string Buffer; - array(RequestEntry) Requestss ; + array(RequestEntry) Requests; - void add( SymbolInfo definition, AddPolicy policy, Code to_inject ); - - void replace( SymbolInfo definiton, ReplacePolicy policy, Code to_replace); - - void remove( SymbolInfo definition, RemovePolicy policy, Code to_remove ); + void add ( SymbolInfo definition, Policy policy, Code to_inject ); + void replace( SymbolInfo definition, Policy policy, Code to_replace); + void remove ( SymbolInfo definition, Policy policy, Code to_remove ); # ifdef GEN_USE_REFACTOR_LIBRARY void refactor( char const* specification ); # endif + + bool process_requests( array(Receipt) out_receipts ); + }; +#endif + +#ifdef GEN_FEATURE_SCANNER + struct Scanner + { + struct RequestEntry + { + SymbolInfo Info; + }; + + struct Receipt + { + ro_string File; + Code Defintion; + bool Result; + }; + + allocator Allocator; + + static void set_allocator( allocator mem_allocator ); + + array(zpl_file) Files; + string Buffer; + array(RequestEntry) Requests; + + void add( SymbolInfo signature, Policy policy ); + + bool process_requests( array(Receipt) out_receipts ); }; #endif #pragma endregion Gen Interface