Removed readonly ast option. Removed indentation from serialization. Updates to readme.

- Readonly overcompilcates things for the scope of this project. I'm avoding const correctness to avoid mental overhead.
- Indentation was removed as it still required a formatting pass after, and the only significant thing needed was the newlines.
- Removed some opinionated takes from readme, trying to keep it straight to the point.
- Used def_execution more in array and ring defs (was using untyped_str when could have been using execution...)
This commit is contained in:
Edward R. Gonzalez 2023-07-08 12:21:26 -04:00
parent 4db9aadea7
commit a0250d1109
9 changed files with 147 additions and 385 deletions

View File

@ -157,7 +157,7 @@ If in your use case, you decide to have exclusive separation or partial separati
### *WHAT IS NOT PROVIDED*
* Macro or template generation : This library is to avoid those, adding support for them adds unnecessary complexity.
* Vendor provided dynamic dispatch (virtuals) : Roll your own, this library might roll its own vtable/interface generation helpers in the future.
* Vendor provided dynamic dispatch (virtuals) : `override` and `final` specifiers complicate the specifier serialization. (I'll problably end up adding in later)
* RTTI
* Exceptions
* Execution statement validation : Execution expressions are defined using the untyped string API.
@ -177,20 +177,9 @@ When it comes to expressions:
There is no support for validating expressions.
The reason: thats where the can of worms open for parsing validation. This library would most likey more than double in size with that addition alone.
For most metaprogramming (espcially for C/C++), expression validation is not necessary for metaprogramming, it can be done by the compiler for the runtime program.
Most of the time, the critical complex metaprogramming conundrums are producing the frame of abstractions around the expressions.
Thus its not very much a priority to add such a level of complexity to the library when there isn't a high reward or need for it.
To further this point, lets say you do have an error with an expressions composition.
It will either be caught by the c++ compiler when compiling the target program, or at runtime for the program.
* If its not caught by the compiler, the only downside is the error appers on the generated function.
Those with knowledge of how that definition was generated know where to find the code that inlined that expression in that file for that definition.
* If its caught at runtime. The expression will be shown in a stack trace if debug symbols are enabled in the generated function body.
Yet again those with knowledge of how that definition was generated know where to find the code that inlined that expression.
In both these cases the user will get objectively better debug information than you would normally get on most c++ compilers/editors using complex macros or templates.
### The Data & Interface
As mentioned in [Usage](#usage), the user is provided Code objects by calling the constructor's functions to generate them or find existing matches.
@ -214,9 +203,8 @@ OperatorT Op;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
u32 StaticIndex;
bool Readonly;
bool DynamicEntries;
u8 _Align_Pad[2];
u8 _Align_Pad[3];
```
*`CodeT` is a typedef for `ECode::Type` which has an underlying type of `u32`*
@ -237,7 +225,7 @@ uw ArrS_Cap =
- sizeof(ModuleFlag) // ModuleFlags
- sizeof(AccessSpec) // ParentAccess
- sizeof(u32) // StaticIndex
- sizeof(bool) * 2 // Readonly, DynamicEntries
- sizeof(bool) * 1 // DynamicEntries
- sizeof(u8) * 2 ) // _Align_Pad
/ sizeof(AST*);
```

View File

@ -85,12 +85,6 @@ using zpl::str_fmt_va;
using zpl::str_fmt_out_va;
using zpl::str_fmt_out_err_va;
using zpl::str_compare;
// using zpl::string_appendc;
// using zpl::string_append_fmt;
// using zpl::string_append_length;
// using zpl::string_make_length;
// using zpl::string_length;
// using zpl::string_make;
using zpl::str_len;
#if __clang__

View File

@ -33,7 +33,6 @@ While getting fleshed out, all feature macros are defined on the top of the head
These macros are:
* `GEN_DEFINE_LIBRARY_CORE_CONSTANTS` : Optional typename codes as they are non-standard to C/C++ and not necessary to library usage
* `GEN_ENCORCE_READONLY_AST` : Defines checks in Code when accessing the AST to make sure readonly marked ASTs are not mutated
* `GEN_FEATURE_INCREMENTAL` : Defines the incremental constructors
* `GEN_FEATURE_PARSING` : Defines the parse constructors
* `GEN_FEATURE_EDITOR` : Defines the file editing features for changing definitions based on ASTs

View File

@ -151,6 +151,7 @@ namespace gen
#pragma endregion AST Body Case Macros
#pragma region AST
Code Code::Global;
Code Code::Invalid;
AST* AST::duplicate()
@ -163,7 +164,6 @@ namespace gen
result->Name = Name;
result->Type = Type;
result->Op = Op;
result->Readonly = Readonly;
switch ( Type )
{
@ -171,14 +171,15 @@ namespace gen
log_failure( "AST::duplicate: Cannot duplicate an invalid AST." );
return nullptr;
case Untyped:
case Comment:
case Preprocessor_Include:
case Access_Public:
case Access_Protected:
case Access_Private:
case Attributes:
case Comment:
case Execution:
case Module:
case Preprocessor_Include:
case Untyped:
// Can just be the same, as its a cached string.
result->Content = Content;
return result;
@ -200,7 +201,6 @@ namespace gen
case Enum_Class:
case Enum_Class_Fwd:
case Export_Body:
case Execution:
case Extern_Linkage:
case Extern_Linkage_Body:
case Friend:
@ -253,42 +253,6 @@ namespace gen
String result = String::make( g_allocator, "" );
// Scope indentation.
char indent_str[128] = {0}; // Should be more than enough...
s32 tab_count = 0;
{
AST* curr_parent = Parent;
while ( curr_parent )
{
switch ( curr_parent->Type )
{
using namespace ECode;
case Class_Body:
case Enum_Body:
case Extern_Linkage_Body:
case Function_Body:
case Global_Body:
case Namespace_Body:
case Struct_Body:
case Union_Body:
break;
default:
{
curr_parent = curr_parent->Parent;
continue;
}
}
indent_str[tab_count] = '\t';
tab_count++;
curr_parent = curr_parent->Parent;
}
}
StrC indent = { tab_count, indent_str };
switch ( Type )
{
using namespace ECode;
@ -304,8 +268,6 @@ namespace gen
case Comment:
{
result.append( indent );
static char line[MaxCommentLineLength];
s32 left = Content.length();
@ -339,8 +301,6 @@ namespace gen
case Class:
{
result.append( indent );
ProcessModuleFlags();
if ( num_entries() > 1 )
@ -363,10 +323,9 @@ namespace gen
{
char const* access_level = to_str( ParentAccess );
result.append_fmt( ": %s %s\n%s{\n"
result.append_fmt( ": %s %s\n{\n"
, access_level
, parent
, indent_str
);
}
else
@ -374,19 +333,17 @@ namespace gen
result.append( "\n{\n" );
}
result.append_fmt( "%s\n%s};", body()->to_string(), indent_str );
result.append_fmt( "%s\n};", body()->to_string() );
}
else
{
result.append_fmt( "class %s\n{\n%s\n%s};", Name, body()->to_string(), indent_str );
result.append_fmt( "class %s\n{\n%s\n};", Name, body()->to_string() );
}
}
break;
case Class_Fwd:
{
result.append( indent );
ProcessModuleFlags();
result.append_fmt( "class %s;", Name );
@ -395,8 +352,6 @@ namespace gen
case Enum:
{
result.append( indent );
ProcessModuleFlags();
result.append( "enum " );
@ -442,8 +397,6 @@ namespace gen
case Enum_Fwd:
{
result.append( indent );
ProcessModuleFlags();
result.append_fmt( "enum %s : %s;", Name, entry( 0 )->to_string() );
@ -452,8 +405,6 @@ namespace gen
case Enum_Class:
{
result.append( indent );
ProcessModuleFlags();
result.append( "enum class " );
@ -470,10 +421,9 @@ namespace gen
if ( entry( idx )->Type == Typename )
{
result.append_fmt( "%s : %s\n%s{\n"
result.append_fmt( "%s : %s\n{\n"
, Name
, entry( idx )->to_string()
, indent_str
);
}
else
@ -492,8 +442,6 @@ namespace gen
case Enum_Class_Fwd:
{
result.append( indent );
ProcessModuleFlags();
result.append( "enum class " );
@ -512,41 +460,35 @@ namespace gen
case Export_Body:
{
result.append_fmt( "%sexport\n%s{\n", indent_str, indent_str );
result.append_fmt( "export\n{\n" );
s32 index = 0;
s32 left = num_entries();
while ( left -- )
{
result.append_fmt( "%s\t%s\n", indent_str, entry( index )->to_string() );
result.append_fmt( "%s\n", entry( index )->to_string() );
index++;
}
result.append_fmt( "%s};", indent_str );
result.append_fmt( "};" );
}
break;
case Extern_Linkage:
result.append( indent );
ProcessModuleFlags();
result.append_fmt( "extern \"%s\"\n%s{\n%s\n%s}"
result.append_fmt( "extern \"%s\"\n{\n%s\n}"
, Name
, indent_str
, body()->to_string()
, indent_str
);
break;
case Friend:
result.append_fmt( "%sfriend %s", indent_str, entry( 0 )->to_string() );
result.append_fmt( "friend %s", entry( 0 )->to_string() );
break;
case Function:
{
result.append( indent );
ProcessModuleFlags();
u32 idx = 1;
@ -592,18 +534,14 @@ namespace gen
result.append( "void" );
}
result.append_fmt( ")\n%s{\n%s\n%s}"
, indent_str
result.append_fmt( ")\n{\n%s\n}"
, body()->to_string()
, indent_str
);
}
break;
case Function_Fwd:
{
result.append( indent );
ProcessModuleFlags();
u32 idx = 0;
@ -654,8 +592,6 @@ namespace gen
break;
case Module:
result.append( indent );
if (((u32(ModuleFlag::Export) & u32(ModuleFlags)) == u32(ModuleFlag::Export)))
result.append("export ");
@ -666,23 +602,17 @@ namespace gen
break;
case Namespace:
result.append( indent );
ProcessModuleFlags();
result.append_fmt( "namespace %s\n%s{\n%s\n%s};"
result.append_fmt( "namespace %s\n{\n%s\n};"
, Name
, indent_str
, body()->to_string()
, indent_str
);
break;
case Operator:
case Operator_Member:
{
result.append( indent );
ProcessModuleFlags();
s32 idx = 1;
@ -712,8 +642,7 @@ namespace gen
result.append_fmt( "void" );
}
result.append_fmt( ")\n%s{\n%s\n}"
, indent_str
result.append_fmt( ")\n{\n%s\n}"
, body()->to_string()
);
}
@ -722,8 +651,6 @@ namespace gen
case Operator_Fwd:
case Operator_Member_Fwd:
{
result.append( indent );
ProcessModuleFlags();
s32 idx = 0;
@ -785,8 +712,6 @@ namespace gen
case Struct:
{
result.append( indent );
ProcessModuleFlags();
result.append( "struct ");
@ -833,8 +758,6 @@ namespace gen
case Struct_Fwd:
{
result.append( indent );
ProcessModuleFlags();
result.append( "struct ");
@ -853,8 +776,6 @@ namespace gen
case Variable:
{
result.append( indent );
ProcessModuleFlags();
s32 idx = 1;
@ -881,8 +802,6 @@ namespace gen
case Typedef:
{
result.append( indent );
ProcessModuleFlags();
AST* type = entry( 0 );
@ -918,8 +837,6 @@ namespace gen
case Union:
{
result.append( indent );
ProcessModuleFlags();
s32 idx = 0;
@ -932,19 +849,15 @@ namespace gen
idx++;
}
result.append_fmt( "%s\n%s{\n%s\n%s};"
result.append_fmt( "%s\n{\n%s\n};"
, Name
, indent_str
, body()->to_string()
, indent_str
);
}
break;
case Using:
{
result.append( indent );
ProcessModuleFlags();
AST* type = entry( 0 );
@ -969,7 +882,7 @@ namespace gen
break;
case Using_Namespace:
result.append_fmt( "%susing namespace %s;", indent_str, Name );
result.append_fmt( "using namespace %s;", Name );
break;
case Class_Body:
@ -985,7 +898,7 @@ namespace gen
s32 left = num_entries();
while ( left -- )
{
result.append_fmt( "%s%s\n", indent_str, entry( index )->to_string() );
result.append_fmt( "%s\n", entry( index )->to_string() );
index++;
}
}
@ -1085,20 +998,19 @@ namespace gen
// fatal( "gen::init: Failed to initialize the TypeMap" );
}
Code::Global = make_code();
Code::Global->Name = get_cached_string( name("Global Code") );
Code::Global->Content = Code::Global->Name;
Code::Invalid = make_code();
Code::Invalid.lock();
type_ns(auto) = def_type( name(auto) );
Code&
t_void_write = ccast( Code, t_void );
t_void_write = def_type( name(void) );
Code::Invalid.set_global();
# define def_constant_code_type( Type_ ) \
Code& \
t_##Type_##_write = ccast( Code, type_ns(Type_) ); \
t_##Type_##_write = def_type( name(Type_) ); \
type_ns(Type_) = def_type( name(Type_) ); \
type_ns(Type_).set_global();
def_constant_code_type( auto );
def_constant_code_type( void );
def_constant_code_type( int );
def_constant_code_type( bool );
def_constant_code_type( char );
@ -1125,53 +1037,42 @@ namespace gen
#endif
# undef def_constant_code_type
Code&
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( StrC::from("private:") );
access_private_write.lock();
access_private = make_code();
access_private->Type = ECode::Access_Private;
access_private->Name = get_cached_string( StrC::from("private:") );
access_private.set_global();
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( StrC::from("protected:") );
access_protected_write.lock();
access_protected = make_code();
access_protected->Type = ECode::Access_Protected;
access_protected->Name = get_cached_string( StrC::from("protected:") );
access_protected.set_global();
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( StrC::from("public:") );
access_public_write.lock();
access_public = make_code();
access_public->Type = ECode::Access_Public;
access_public->Name = get_cached_string( StrC::from("public:") );
access_public.set_global();
module_global_fragment = make_code();
module_global_fragment->Type = ECode::Untyped;
module_global_fragment->Name = get_cached_string( StrC::from("module;") );
module_global_fragment->Content = module_global_fragment->Name;
module_global_fragment.lock();
module_global_fragment.set_global();
module_private_fragment = make_code();
module_private_fragment->Type = ECode::Untyped;
module_private_fragment->Name = get_cached_string( StrC::from("module : private;") );
module_private_fragment->Content = module_private_fragment->Name;
module_private_fragment.lock();
module_private_fragment.set_global();
pragma_once = make_code();
pragma_once->Type = ECode::Untyped;
pragma_once->Name = get_cached_string( StrC::from("#pragma once") );
pragma_once->Content = pragma_once->Name;
pragma_once.lock();
Code&
spec_local_persist_write = ccast( Code, spec_local_persist );
spec_local_persist_write = def_specifiers( 1, ESpecifier::Local_Persist );
pragma_once.set_global();
# 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__); \
spec_##Type_ = def_specifiers( macro_num_args(__VA_ARGS__), __VA_ARGS__); \
spec_##Type_.set_global();
def_constant_spec( consteval, ESpecifier::Consteval );
def_constant_spec( constexpr, ESpecifier::Constexpr );
@ -1192,6 +1093,10 @@ namespace gen
def_constant_spec( type_unsigned, ESpecifier::Type_Unsigned );
def_constant_spec( type_short, ESpecifier::Type_Short );
def_constant_spec( type_long, ESpecifier::Type_Long );
spec_local_persist = def_specifiers( 1, ESpecifier::Local_Persist );
spec_local_persist.set_global();
# undef def_constant_spec
}
@ -1268,8 +1173,6 @@ namespace gen
array_clear( CodeEntriesArenas );
}
// type_tbl_clear( & StaticData::TypeMap );
}
inline
@ -1356,7 +1259,6 @@ namespace gen
result->ModuleFlags = ModuleFlag::Invalid;
result->ParentAccess = AccessSpec::Invalid;
result->StaticIndex = 0;
result->Readonly = false;
result->DynamicEntries = false;
return result;
@ -1822,7 +1724,6 @@ namespace gen
result->Name = get_cached_string( content );
result->Content = result->Name;
result.lock();
return result;
}
@ -1840,7 +1741,6 @@ namespace gen
result->Name = get_cached_string( content );
result->Content = result->Name;
result.lock();
return result;
}
@ -1901,7 +1801,6 @@ namespace gen
result->add_entry( parent );
}
result.lock();
return result;
}
@ -1968,7 +1867,6 @@ namespace gen
return Code::Invalid;
}
result.lock();
return result;
}
@ -1986,7 +1884,6 @@ namespace gen
result->Name = get_cached_string( content );
result->Content = result->Name;
result.lock();
return result;
}
@ -2011,7 +1908,6 @@ namespace gen
result->add_entry( body );
result.lock();
return result;
}
@ -2041,7 +1937,6 @@ namespace gen
result->add_entry( declaration );
result.lock();
return result;
}
@ -2125,7 +2020,6 @@ namespace gen
if ( params )
result->add_entry( params );
result.lock();
return result;
}
@ -2143,7 +2037,6 @@ namespace gen
result->Name = get_cached_string( path );
result->Content = result->Name;
result.lock();
return result;
}
@ -2158,7 +2051,6 @@ namespace gen
result->Content = result->Name;
result->ModuleFlags = mflags;
result.lock();
return result;
}
@ -2183,7 +2075,6 @@ namespace gen
result->add_entry( body );
result.lock();
return result;
}
@ -2258,7 +2149,6 @@ namespace gen
if (params_code)
result->add_entry( params_code );
result.lock();
return result;
}
@ -2291,7 +2181,6 @@ namespace gen
if ( value )
result->add_entry( value );
result.lock();
return result;
}
@ -2303,7 +2192,6 @@ namespace gen
result->add_specifier( spec );
result.lock();
return result;
}
@ -2359,7 +2247,6 @@ namespace gen
result->add_entry( parent );
}
result.lock();
return result;
}
@ -2384,8 +2271,6 @@ namespace gen
if ( ArrayExpr )
result->add_entry( ArrayExpr );
result.lock();
return result;
}
@ -2420,7 +2305,6 @@ namespace gen
if ( attributes )
result->add_entry( attributes );
result.lock();
return result;
}
@ -2446,7 +2330,6 @@ namespace gen
if ( attributes )
result->add_entry( attributes );
result.lock();
return result;
}
@ -2477,7 +2360,6 @@ namespace gen
if ( attributes )
result->add_entry( attributes );
result.lock();
return result;
}
@ -2491,7 +2373,6 @@ namespace gen
result->Content = result->Name;
result->Type = ECode::Using_Namespace;
result.lock();
return result;
}
@ -2543,7 +2424,6 @@ namespace gen
if ( value )
result->add_entry( value );
result.lock();
return result;
}
@ -2650,7 +2530,6 @@ namespace gen
def_body_code_validation_end( def_class_body );
va_end(va);
result.lock();
return result;
}
@ -2666,7 +2545,6 @@ namespace gen
AST_BODY_CLASS_UNALLOWED_TYPES
def_body_code_validation_end( def_class_body );
result.lock();
return result;
}
@ -2702,7 +2580,6 @@ namespace gen
while ( num--, num > 0 );
va_end(va);
result.lock();
return result;
}
@ -2734,7 +2611,6 @@ namespace gen
}
while ( codes++, num--, num > 0 );
result.lock();
return result;
}
@ -2753,7 +2629,6 @@ namespace gen
def_body_code_validation_end( def_export_body );
va_end(va);
result.lock();
return result;
}
@ -2769,7 +2644,6 @@ namespace gen
AST_BODY_EXPORT_UNALLOWED_TYPES
def_body_code_validation_end( def_export_body );
result.lock();
return result;
}
@ -2788,7 +2662,6 @@ namespace gen
def_body_code_validation_end( def_extern_linkage_body );
va_end(va);
result.lock();
return result;
}
@ -2804,7 +2677,6 @@ namespace gen
AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
def_body_code_validation_end( def_extern_linkage_body );
result.lock();
return result;
}
@ -2823,7 +2695,6 @@ namespace gen
def_body_code_validation_end( def_function_body );
va_end(va);
result.lock();
return result;
}
@ -2839,7 +2710,6 @@ namespace gen
AST_BODY_FUNCTION_UNALLOWED_TYPES
def_body_code_validation_end( def_function_body );
result.lock();
return result;
}
@ -2858,7 +2728,6 @@ namespace gen
def_body_code_validation_end( def_global_body );
va_end(va);
result.lock();
return result;
}
@ -2874,7 +2743,6 @@ namespace gen
AST_BODY_GLOBAL_UNALLOWED_TYPES
def_body_code_validation_end( def_global_body );
result.lock();
return result;
}
@ -2893,7 +2761,6 @@ namespace gen
def_body_code_validation_end( def_namespace_body );
va_end(va);
result.lock();
return result;
}
@ -2909,7 +2776,6 @@ namespace gen
AST_BODY_NAMESPACE_UNALLOWED_TYPES
def_body_code_validation_end( def_namespace_body );
result.lock();
return result;
}
@ -2948,7 +2814,6 @@ namespace gen
}
va_end(va);
result.lock();
return result;
}
@ -2986,7 +2851,6 @@ namespace gen
}
# undef check_current
result.lock();
return result;
}
@ -3019,7 +2883,6 @@ namespace gen
while ( --num, num );
va_end(va);
result.lock();
return result;
}
@ -3038,7 +2901,6 @@ namespace gen
def_body_code_validation_end( def_struct_body );
va_end(va);
result.lock();
return result;
}
@ -3054,7 +2916,6 @@ namespace gen
AST_BODY_STRUCT_UNALLOWED_TYPES
def_body_code_validation_end( def_struct_body );
result.lock();
return result;
}
@ -3090,7 +2951,6 @@ namespace gen
while ( num--, num > 0 );
va_end(va);
result.lock();
return result;
}
@ -3122,7 +2982,6 @@ namespace gen
}
while ( codes++, num--, num > 0 );
result.lock();
return result;
}
@ -5293,7 +5152,6 @@ namespace gen
result->Type = ECode::Untyped;
result->Content = result->Name;
result.lock();
return result;
}
@ -5313,7 +5171,6 @@ namespace gen
result->Type = ECode::Untyped;
result->Content = get_cached_string( { length, buf } );
result.lock();
return result;
}
@ -5333,7 +5190,6 @@ namespace gen
result->Type = ECode::Untyped;
result->Content = get_cached_string( { length, buf } );
result.lock();
return result;
}
#pragma endregion Untyped Constructors

View File

@ -13,9 +13,7 @@
// Temporarily here for debugging purposes.
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
// #define GEN_DONT_USE_FATAL
// #define GEN_ENFORCE_READONLY_AST
#define GEN_FEATURE_INCREMENTAL
// #define GEN_FEATURE_PARSING
// #define GEN_FEATURE_EDITOR
// #define GEN_FEATURE_SCANNER
@ -427,8 +425,6 @@ namespace gen
// Parameter
bool add_param( AST* type, StrC name );
inline
AST* get_param( s32 index )
{
@ -509,7 +505,6 @@ namespace gen
char const* fmt = txt(
\nCode Debug:
\nType : %s
\nReadonly: %s
\nParent : %s
\nName : %s
\nComment : %s
@ -521,7 +516,6 @@ namespace gen
// allocate this to proper string.
return str_fmt_buf( fmt
, type_str()
, Readonly ? "true" : "false"
, Parent ? Parent->Name : ""
, Name ? Name : ""
);
@ -546,7 +540,7 @@ namespace gen
- sizeof(ModuleFlag) // ModuleFlags
- sizeof(AccessSpec) // ParentAccess
- sizeof(u32) // StaticIndex
- sizeof(bool) * 2 // Readonly, DynamicEntries
- sizeof(bool) * 1 // DynamicEntries
- sizeof(u8) * 2 ) // _Align_Pad
/ sizeof(AST*);
@ -567,9 +561,8 @@ namespace gen
ModuleFlag ModuleFlags; \
AccessSpec ParentAccess; \
u32 StaticIndex; \
bool Readonly; \
bool DynamicEntries; \
u8 _Align_Pad[2];
u8 _Align_Pad[3];
Using_AST_POD
};
@ -599,6 +592,9 @@ namespace gen
struct Code
{
#pragma region Statics
// Used to identify ASTs that should always be duplicated. (Global constant ASTs)
static Code Global;
// Used to identify invalid generated code.
static Code Invalid;
#pragma endregion Statics
@ -630,18 +626,24 @@ namespace gen
return * (Code*)( ast->body() );
}
inline
void lock()
{
ast->Readonly = true;
}
inline
String to_string() const
{
return ast->to_string();
}
inline
void set_global()
{
if ( ast == nullptr )
{
log_failure("Code::set_global: Cannot set code as global, AST is null!");
return;
}
ast->Parent = Global.ast;
}
inline
operator bool() const
{
@ -669,13 +671,11 @@ namespace gen
inline
Code& operator=( Code other )
{
#ifdef GEN_ENFORCE_READONLY_AST
if ( ast && ast->Readonly )
if ( other.ast == nullptr )
{
log_failure("Attempted to set a readonly AST!");
log_failure("Attempted to assign a nullptr!");
return *this;
}
#endif
ast = other.ast;
@ -691,14 +691,6 @@ namespace gen
return nullptr;
}
#ifdef GEN_ENFORCE_READONLY_AST
if ( ast->Readonly )
{
log_failure("Attempted to access a member from a readonly AST!");
return nullptr;
}
#endif
return ast;
}
#pragma endregion Member Functions
@ -722,13 +714,14 @@ namespace gen
// This currently just initializes the CodePool.
void init();
// Currently manually free's the arenas, code for checking for leaks.
// However on Windows at least, it doesn't need to occur as the OS will clean up after the process.
void deinit();
/*
Use this only if you know you generated the code you needed to a file.
And rather get rid of current code asts instead of growing the pool memory.
This generally can be done everytime a file is generated
TODO: In order for this to work, the type map needs its own arenas so do specifiers.
TODO: Need to put permanent ASTs into a separate set of memory. (I might just remove this tbh as it might be useless)
*/
void clear_code_memory();
@ -1141,52 +1134,6 @@ namespace gen
to_add->Parent = this;
}
inline
bool AST::add_param( AST* type, StrC name )
{
if ( Type != ECode::Function )
{
log_failure( "gen::AST::add_param: this AST is not a function - %s", debug_str() );
return Code::Invalid;
}
if ( name.Len <= 0 )
{
log_failure( "gen::AST::add_param: Invalid name length provided - %d", name.Len );
return Code::Invalid;
}
if ( name == nullptr )
{
log_failure( "gen::AST::add_param: name is null");
return Code::Invalid;
}
s32
score = 0;
score += Name == nullptr;
score += entry( 0 ) == nullptr;
if ( score == 1 )
{
log_failure("gen::AST::add_param: this AST has bad data - %s", debug_str() );
return false;
}
else if ( score == 2)
{
Name = get_cached_string( name );
entry( 0 ) = type;
return true;
}
Code
result = make_code();
result->Type = ECode::Parameters;
result->add_entry( result );
return true;
}
}
#pragma endregion Inlines

View File

@ -16,7 +16,7 @@ Code gen__array_base()
));
Code grow_formula = def_function( name(array_grow_formula), def_param( t_uw, name(value)), t_uw
, untyped_str( code( return 2 * value * 8; ) )
, def_execution( code( return 2 * value * 8; ) )
, def_specifiers( 2, ESpecifier::Static_Member, ESpecifier::Inline )
);
@ -57,20 +57,17 @@ Code gen__array( StrC type, sw type_size )
Code t_header_ptr = def_type( name(Header), __, spec_ptr );
Code t_header_ref = def_type( name(Header), __, spec_ref );
Code array;
Code array = {0};
{
Code using_type = def_using( name(Type), t_type );
Code data = def_variable( t_alias_ptr, name(Data) );
Code init;
{
Code params = def_param( t_allocator_info, name(allocator) );
Code body = untyped_str( code(
Code init = def_function( name(init), def_param( t_allocator_info, name(allocator) ), t_array_type
, def_execution( code(
return init_reserve( allocator, grow_formula(0) );
));
init = def_function( name(init), params, t_array_type, body, spec_static );
}
))
, spec_static
);
Code init_reserve;
{
@ -79,7 +76,7 @@ Code gen__array( StrC type, sw type_size )
, def_param( t_sw, name(capacity) )
);
Code body = untyped_str( code(
Code body = def_execution( code(
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) ));
if ( header == nullptr )
@ -95,16 +92,8 @@ Code gen__array( StrC type, sw type_size )
init_reserve = def_function( name(init_reserve), params, t_array_type, body, spec_static );
}
Code append;
{
// Code param_type;
// if ( type_size <= 64 )
// param_type = t_type;
// else
// param_type = t_type_ref;
append = def_function( name(append), def_param(t_alias, name(value)), t_bool
, untyped_str( code(
Code append = def_function( name(append), def_param(t_alias, name(value)), t_bool
, def_execution( code(
Header& header = get_header();
if ( header.Num == header.Capacity )
@ -119,20 +108,17 @@ Code gen__array( StrC type, sw type_size )
return true;
))
);
}
Code back;
{
Code body = untyped_str( code(
Code back = def_function( name(back), __, t_alias_ref
, def_execution( code(
Header& header = get_header();
return Data[ header.Num - 1 ];
));
back = def_function( name(back), __, t_alias_ref, body, spec_inline );
}
))
, spec_inline
);
Code clear = def_function( name(clear), __, t_void
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
header.Num = 0;
))
@ -165,19 +151,22 @@ Code gen__array( StrC type, sw type_size )
}
Code free = def_function( name(free), __, t_void
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
zpl::free( header.Allocator, & header );
))
, spec_inline
);
Code get_header = def_function( name(get_header), __, t_header_ref, untyped_str( code(
Code get_header = def_function( name(get_header), __, t_header_ref
, def_execution( code(
return * ( rcast( Header*, Data ) - 1 );
)));
))
, spec_inline
);
Code grow = def_function( name(grow), def_param( t_uw, name(min_capacity)), t_bool
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
uw new_capacity = grow_formula( header.Capacity );
@ -190,23 +179,21 @@ Code gen__array( StrC type, sw type_size )
);
Code num = def_function( name(num), __, t_uw
, untyped_str( code(
, def_execution( code(
return get_header().Num;
))
, spec_inline
);
Code pop;
{
Code body = untyped_str( code(
Code pop = def_function( name(pop), __, t_bool
, def_execution( code(
Header& header = get_header();
ZPL_ASSERT( header.Num > 0 );
header.Num--;
));
pop = def_function( name(pop), __, t_bool, body, spec_inline );
}
))
, spec_inline
);
Code remove_at = def_function( name(remove_at), def_param( t_uw, name(idx)), t_void
, def_execution( code(
@ -220,7 +207,7 @@ Code gen__array( StrC type, sw type_size )
);
Code reserve = def_function( name(reserve), def_param( t_uw, name(new_capacity)), t_bool
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
if ( header.Capacity < new_capacity )
@ -231,7 +218,7 @@ Code gen__array( StrC type, sw type_size )
);
Code resize = def_function( name(resize), def_param( t_uw, name(num)), t_bool
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
if ( num > header.Capacity )
@ -247,7 +234,7 @@ Code gen__array( StrC type, sw type_size )
Code set_capacity;
{
Code body = untyped_str( code(
Code body = def_execution( code(
Header& header = get_header();
if ( new_capacity == header.Capacity )

View File

@ -42,7 +42,7 @@ Code gen__buffer( StrC type, sw type_size )
Code t_header_ptr = def_type( name(Header), __, spec_ptr );
Code t_header_ref = def_type( name(Header), __, spec_ref );
Code buffer;
Code buffer = {0};
{
Code using_type = def_using( name(Type), t_type );
Code data = def_variable( t_type_ptr, name(Data) );
@ -54,7 +54,7 @@ Code gen__buffer( StrC type, sw type_size )
, def_param( t_sw, name(capacity))
);
Code body = untyped_str( code(
Code body = def_execution( code(
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + capacity * sizeof(Type) ) );
if ( header == nullptr )
@ -78,7 +78,7 @@ Code gen__buffer( StrC type, sw type_size )
);
init_copy = def_function( name(init), params, t_buffer_type
, untyped_str( code(
, def_execution( code(
Header& other_header = other.get_header();
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + other_header.Capacity * sizeof(Type) ) );
@ -95,23 +95,14 @@ Code gen__buffer( StrC type, sw type_size )
);
}
Code append;
{
// Code param_type;
// if ( type_size <= 64 )
// param_type = t_type;
// else
// param_type = t_type_ref;
append = def_function( name(append), def_param( t_type, name(value)), t_void
, untyped_str( code(
Code append = def_function( name(append), def_param( t_type, name(value)), t_void
, def_execution( code(
Header& header = get_header();
Data[ header.Num ] = value;
header.Num++;
))
, spec_inline
);
}
Code appendv;
{
@ -121,7 +112,7 @@ Code gen__buffer( StrC type, sw type_size )
);
appendv = def_function( name(append), params, t_void
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
ZPL_ASSERT( header.Num + num <= header.Capacity);
@ -135,7 +126,7 @@ Code gen__buffer( StrC type, sw type_size )
}
Code clear = def_function( name(clear), __, t_void
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
header.Num = 0;
))
@ -143,7 +134,7 @@ Code gen__buffer( StrC type, sw type_size )
);
Code end = def_function( name(end), __, t_type_ref
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
return Data[ header.Num - 1 ];
))
@ -151,7 +142,7 @@ Code gen__buffer( StrC type, sw type_size )
);
Code free = def_function( name(free), __, t_void
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
zpl::free( header.Backing, & header );
))
@ -159,21 +150,21 @@ Code gen__buffer( StrC type, sw type_size )
);
Code get_header = def_function( name(get_header), __, t_header_ref
, untyped_str( code(
, def_execution( code(
return * ( rcast( Header*, Data ) - 1 );
))
, spec_inline
);
Code num = def_function( name(num), __, t_sw
, untyped_str( code(
, def_execution( code(
return get_header().Num;
))
, spec_inline
);
Code pop = def_function( name(pop), __, t_type
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
header.Num--;
return Data[ header.Num ];
@ -182,7 +173,7 @@ Code gen__buffer( StrC type, sw type_size )
);
Code wipe = def_function( name(wipe), __, t_void
, untyped_str( code(
, def_execution( code(
Header& header = get_header();
header.Num = 0;
mem_set( Data, 0, header.Capacity * sizeof( Type ) );

View File

@ -12,7 +12,7 @@ Code gen__hashtable_base()
Code entry_prev = def_variable( t_sw, name(PrevIndex) );
Code entry_index = def_variable( t_sw, name(EntryIndex) );
Code find_result = def_struct( name(HashTableFindResult), def_struct_body( 3
Code find_result = def_struct( name(HashTable_FindResult), def_struct_body( 3
, hashIndex
, entry_prev
, entry_index
@ -25,7 +25,7 @@ Code gen__hashtable( StrC type, sw type_size )
{
static Code t_allocator_info = def_type( name(AllocatorInfo) );
Code t_find_result = def_type( name(HashTableFindResult) );
Code t_find_result = def_type( name(HashTable_FindResult) );
StringCached name;
{
@ -61,7 +61,7 @@ Code gen__hashtable( StrC type, sw type_size )
t_array_ht_entry = def_type( array_ht_entry->Name );
}
Code hashtable;
Code hashtable = {0};
{
Code using_entry = def_using( name(Entry), t_ht_entry );
Code using_array_entry = def_using( name(Array_Entry), t_array_ht_entry );

View File

@ -33,7 +33,7 @@ Code gen__ring( StrC type, sw type_size )
t_buffer_type = def_type( { len, name_str } );
}
Code ring;
Code ring = {0};
{
Code using_type = def_using( name(Type), t_type );
@ -64,7 +64,7 @@ Code gen__ring( StrC type, sw type_size )
return result;
);
Code body = untyped_str( token_fmt( tmpl, 2
Code body = def_execution( token_fmt( tmpl, 2
, "type", (char const*)name
, "data_type", (char const*)type
));
@ -73,7 +73,7 @@ Code gen__ring( StrC type, sw type_size )
}
Code append = def_function( name(append), def_param( t_type, name(value)), t_void
, untyped_str( code(
, def_execution( code(
Buffer[ Head ] = value;
Head = ( Head + 1 ) % Capacity;
@ -90,7 +90,7 @@ Code gen__ring( StrC type, sw type_size )
, def_param( t_sw, name(num))
);
Code body = untyped_str( code(
Code body = def_execution( code(
for ( sw idx = 0; idx < num; idx++ )
append( values[ idx ] );
));