mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 07:44:45 -08:00
Design: Added additional keywords to specifiers, added def_friend. Fleshed out scanner.
This commit is contained in:
parent
fcf037d50f
commit
f5fe30e7cb
336
project/gen.cpp
336
project/gen.cpp
@ -72,10 +72,11 @@ namespace gen
|
||||
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 SizePer_StringArena = megabytes(32);
|
||||
|
||||
static allocator Allocator_CodePool = heap();
|
||||
static allocator Allocator_StringArena = heap();
|
||||
static allocator Allocator_StringTable = 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,16 +518,24 @@ 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;
|
||||
}
|
||||
|
||||
Code
|
||||
result = make_code();
|
||||
result->Name = cached_string( name, length );
|
||||
|
||||
array_init( result->Entries, StaticData::Allocator_CodePool );
|
||||
|
||||
if ( body )
|
||||
{
|
||||
switch ( body->Type )
|
||||
{
|
||||
case Class_Body:
|
||||
@ -526,18 +543,10 @@ namespace gen
|
||||
break;
|
||||
|
||||
default:
|
||||
log_failure("gen_def_class: body must be either of Function_Body or Untyped type.");
|
||||
log_failure("gen::def_class: body must be either of Class_Body or Untyped type - %s", body->debug_str());
|
||||
return Code::Invalid;
|
||||
}
|
||||
|
||||
Code
|
||||
result = make_code();
|
||||
result->Name = code_string( name, length );
|
||||
|
||||
array_init( result->Entries, StaticData::Allocator_CodePool );
|
||||
|
||||
if ( body )
|
||||
{
|
||||
result->Type = Class;
|
||||
result->add_entry( body );
|
||||
}
|
||||
@ -558,9 +567,12 @@ 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 )
|
||||
@ -569,10 +581,47 @@ namespace gen
|
||||
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 def_function( char const* name
|
||||
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( s32 length, char const* name
|
||||
, Code specifiers
|
||||
, Code params
|
||||
, Code ret_type
|
||||
@ -581,24 +630,44 @@ 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;
|
||||
}
|
||||
|
||||
Code
|
||||
result = make_code();
|
||||
result->Name = cached_string( name, length );
|
||||
|
||||
array_init( result->Entries, StaticData::Allocator_CodePool );
|
||||
|
||||
if ( body )
|
||||
{
|
||||
switch ( body->Type )
|
||||
{
|
||||
case Function_Body:
|
||||
@ -607,26 +676,30 @@ namespace gen
|
||||
|
||||
default:
|
||||
{
|
||||
log_failure("gen::def_function: body must be either of Function_Body or Untyped type.");
|
||||
log_failure("gen::def_function: body must be either of Function_Body or Untyped type. %s", body->debug_str());
|
||||
return Code::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
s32 name_length = zpl_strnlen( name, MaxNameLength );
|
||||
|
||||
Code
|
||||
result = make_code();
|
||||
result->Name = code_string( name, name_length );
|
||||
result->Type = Function;
|
||||
|
||||
array_init( result->Entries, StaticData::Allocator_CodePool );
|
||||
|
||||
result->add_entry( body );
|
||||
}
|
||||
else
|
||||
{
|
||||
result->Type = Function_FwdDecl;
|
||||
}
|
||||
|
||||
if ( specifiers )
|
||||
result->add_entry( specifiers );
|
||||
|
||||
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 );
|
||||
|
434
project/gen.hpp
434
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
|
||||
{
|
||||
@ -450,15 +536,17 @@ namespace gen
|
||||
#pragma endregion Member Procedures
|
||||
|
||||
#define Using_Code_POD \
|
||||
CodeT Type; \
|
||||
bool Readonly; \
|
||||
AST* Parent; \
|
||||
string Name; \
|
||||
string Comment; \
|
||||
ro_string Name; \
|
||||
ro_string Comment; \
|
||||
union { \
|
||||
array(AST*) Entries; \
|
||||
string Content; \
|
||||
};
|
||||
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,24 +849,9 @@ namespace gen
|
||||
|
||||
};
|
||||
|
||||
struct AddPolicy
|
||||
{
|
||||
// Not sure yet
|
||||
};
|
||||
|
||||
struct ReplacePolicy
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct RemovePolicy
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct SymbolInfo
|
||||
{
|
||||
char const* File;
|
||||
ro_string File;
|
||||
Code Signature;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user