Added constructor and destructor supported (UNTESTED)

Just compiles and generates...

Also fixed a bug where parsing didn't have a token for virtual specifiers...
This commit is contained in:
Edward R. Gonzalez 2023-08-07 03:10:45 -04:00
parent c2319b9651
commit c2f8c8aeb1
17 changed files with 511 additions and 72 deletions

View File

@ -145,6 +145,70 @@ String AST::to_string()
}
break;
case Constructor:
{
result.append( Parent->Name );
if ( Params )
result.append_fmt( "( %s )", Params->to_string() );
else
result.append( "(void)" );
if ( InitializerList )
result.append_fmt( " : %s", InitializerList->to_string() );
result.append_fmt( "\n{\n%s\n}", Body->to_string() );
}
break;
case Constructor_Fwd:
{
result.append( Parent->Name );
if ( Params )
result.append_fmt( "( %s )", Params->to_string() );
else
result.append( "(void);" );
}
break;
case Destructor:
{
if ( Specs )
{
CodeSpecifiers specs = Specs->cast<CodeSpecifiers>();
if ( specs.has( ESpecifier::Virtual ) )
result.append_fmt( "virtual ~%s()", Parent->Name );
else
result.append_fmt( "~%s()", Parent->Name );
}
else
result.append_fmt( "~%s()", Parent->Name );
result.append_fmt( "\n{\n%s\n}", Body->to_string() );
}
break;
case Destructor_Fwd:
{
if ( Specs )
{
CodeSpecifiers specs = Specs->cast<CodeSpecifiers>();
if ( specs.has( ESpecifier::Virtual ) )
result.append_fmt( "virtual ~%s();", Parent->Name );
else
result.append_fmt( "~%s()", Parent->Name );
if ( specs.has( ESpecifier::Pure ) )
result.append( " = 0;" );
}
else
result.append_fmt( "~%s();", Parent->Name );
}
break;
case Enum:
{
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export ))

View File

@ -2,8 +2,10 @@ struct AST;
struct AST_Body;
struct AST_Attributes;
struct AST_Comment;
struct AST_Constructor;
struct AST_Class;
struct AST_Define;
struct AST_Destructor;
struct AST_Enum;
struct AST_Exec;
struct AST_Extern;
@ -31,6 +33,8 @@ struct CodeBody;
// These are to offer ease of use and optionally strong type safety for the AST.
struct CodeAttributes;
struct CodeComment;
struct CodeConstructor;
struct CodeDestructor;
struct CodeClass;
struct CodeDefine;
struct CodeEnum;
@ -108,6 +112,8 @@ struct Code
#endif
operator CodeAttributes() const;
operator CodeComment() const;
operator CodeConstructor() const;
operator CodeDestructor() const;
operator CodeClass() const;
operator CodeDefine() const;
operator CodeExec() const;
@ -171,6 +177,8 @@ struct AST
operator CodeBody();
operator CodeAttributes();
operator CodeComment();
operator CodeConstructor();
operator CodeDestructor();
operator CodeClass();
operator CodeDefine();
operator CodeEnum();
@ -214,18 +222,19 @@ struct AST
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
AST* Specs; // Function, Operator, Type symbol, Variable
union {
AST* InitializerList; // Constructor, Destructor
AST* ParentType; // Class, Struct
AST* ReturnType; // Function, Operator
AST* UnderlyingType; // Enum, Typedef
AST* ValueType; // Parameter, Variable
};
union {
AST* Params; // Function, Operator, Template
AST* BitfieldSize; // Varaiable (Class/Struct Data Member)
AST* Params; // Function, Operator, Template
};
union {
AST* ArrExpr; // Type Symbol
AST* Body; // Class, Enum, Function, Namespace, Struct, Union
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
@ -261,18 +270,19 @@ struct AST_POD
AST* Attributes; // Class, Enum, Function, Struct, Typename, Union, Using, Variable
AST* Specs; // Function, Operator, Type symbol, Variable
union {
AST* InitializerList; // Constructor, Destructor
AST* ParentType; // Class, Struct
AST* ReturnType; // Function, Operator
AST* UnderlyingType; // Enum, Typedef
AST* ValueType; // Parameter, Variable
};
union {
AST* Params; // Function, Operator, Template
AST* BitfieldSize; // Varaiable (Class/Struct Data Member)
AST* Params; // Function, Operator, Template
};
union {
AST* ArrExpr; // Type Symbol
AST* Body; // Class, Enum, Function, Namespace, Struct, Union
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
@ -536,7 +546,9 @@ struct CodeStruct
Define_CodeType( Attributes );
Define_CodeType( Comment );
Define_CodeType( Constructor );
Define_CodeType( Define );
Define_CodeType( Destructor );
Define_CodeType( Enum );
Define_CodeType( Exec );
Define_CodeType( Extern );

View File

@ -71,6 +71,27 @@ struct AST_Class
};
static_assert( sizeof(AST_Class) == sizeof(AST), "ERROR: AST_Class is not the same size as AST");
struct AST_Constructor
{
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_ [ sizeof(AST*) * 3 ];
Code InitializerList;
CodeParam Params;
Code Body;
};
};
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
};
static_assert( sizeof(AST_Constructor) == sizeof(AST), "ERROR: AST_Constructor is not the same size as AST");
struct AST_Define
{
union {
@ -86,6 +107,27 @@ struct AST_Define
};
static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the same size as AST");
struct AST_Destructor
{
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
CodeSpecifiers Specs;
char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ];
Code Body;
};
};
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
};
static_assert( sizeof(AST_Destructor) == sizeof(AST), "ERROR: AST_Destructor is not the same size as AST");
struct AST_Enum
{
union {

View File

@ -81,6 +81,7 @@ extern CodeSpecifiers spec_mutable;
extern CodeSpecifiers spec_neverinline;
extern CodeSpecifiers spec_override;
extern CodeSpecifiers spec_ptr;
extern CodeSpecifiers spec_pure;
extern CodeSpecifiers spec_ref;
extern CodeSpecifiers spec_register;
extern CodeSpecifiers spec_rvalue;

View File

@ -197,6 +197,7 @@ void define_constants()
def_constant_spec( neverinline, ESpecifier::NeverInline );
def_constant_spec( override, ESpecifier::Override );
def_constant_spec( ptr, ESpecifier::Ptr );
def_constant_spec( pure, ESpecifier::Pure )
def_constant_spec( ref, ESpecifier::Ref );
def_constant_spec( register, ESpecifier::Register );
def_constant_spec( rvalue, ESpecifier::RValue );

View File

@ -45,8 +45,12 @@ CodeClass def_class( StrC name
, ModuleFlag mflags = ModuleFlag::None
, CodeType* interfaces = nullptr, s32 num_interfaces = 0 );
CodeConstructor def_constructor( CodeParam params = NoCode, Code initializer_list = NoCode, Code body = NoCode );
CodeDefine def_define( StrC name, StrC content );
CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = NoCode );
CodeEnum def_enum( StrC name
, Code body = NoCode, CodeType type = NoCode
, EnumT specifier = EnumRegular, CodeAttributes attributes = NoCode
@ -137,6 +141,8 @@ CodeBody def_union_body ( s32 num, Code* codes );
#pragma region Parsing
CodeClass parse_class ( StrC class_def );
CodeConstructor parse_constructor ( StrC constructor_def );
CodeDestructor parse_destructor ( StrC destructor_def );
CodeEnum parse_enum ( StrC enum_def );
CodeBody parse_export_body ( StrC export_def );
CodeExtern parse_extern_link ( StrC exten_link_def );

View File

@ -89,6 +89,21 @@ namespace Parser
return Arr[idx - 1];
}
Token& next( bool skip_new_lines = false )
{
s32 idx = this->Idx;
if ( skip_new_lines )
{
while ( Arr[idx].Type == TokType::NewLine )
idx++;
return Arr[idx];
}
return Arr[idx + 1];
}
Token& operator []( s32 idx )
{
return Arr[idx];
@ -1098,6 +1113,7 @@ if ( def.Ptr == nullptr ) \
# define currtok_noskip Context.Tokens.current( dont_skip_new_lines )
# define currtok Context.Tokens.current()
# define prevtok Context.Tokens.previous()
# define nexttok Context.Tokens.next()
# define eat( Type_ ) Context.Tokens.__eat( Type_ )
# define left ( Context.Tokens.Arr.num() - Context.Tokens.Idx )
@ -1114,6 +1130,8 @@ internal Code parse_function_body();
internal Code parse_global_nspace();
internal CodeClass parse_class ( bool inplace_def = false );
internal CodeConstructor parse_constructor ();
internal CodeDestructor parse_destructor ( CodeSpecifiers specifiers = NoCode );
internal CodeEnum parse_enum ( bool inplace_def = false );
internal CodeBody parse_export_body ();
internal CodeBody parse_extern_link_body();
@ -2471,7 +2489,7 @@ Code parse_complicated_definition( Parser::TokType which )
}
internal
CodeBody parse_class_struct_body( Parser::TokType which )
CodeBody parse_class_struct_body( Parser::TokType which, Parser::Token name = Parser::NullToken )
{
using namespace Parser;
using namespace ECode;
@ -2566,6 +2584,16 @@ CodeBody parse_class_struct_body( Parser::TokType which )
member = parse_using();
break;
case TokType::Operator:
if ( currtok.Text[0] != '~' )
{
log_failure( "Operator token found in global body but not destructor unary negation\n%s", Context.to_string() );
return CodeInvalid;
}
member = parse_destructor();
break;
case TokType::Preprocess_Define:
member = parse_define();
break;
@ -2661,6 +2689,12 @@ CodeBody parse_class_struct_body( Parser::TokType which )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
}
if ( currtok.Type == TokType::Operator && currtok.Text[0] == '~' )
{
member = parse_destructor( specifiers );
break;
}
}
//! Fallthrough intentional
case TokType::Identifier:
@ -2673,6 +2707,15 @@ CodeBody parse_class_struct_body( Parser::TokType which )
case TokType::Type_int:
case TokType::Type_double:
{
if ( nexttok.Type == TokType::Capture_Start && name.Length && currtok.Type == TokType::Identifier )
{
if ( str_compare( name.Text, currtok.Text, name.Length ) == 0 )
{
member = parse_constructor();
break;
}
}
member = parse_operator_function_or_variable( expects_function, attributes, specifiers );
}
break;
@ -2775,7 +2818,7 @@ Code parse_class_struct( Parser::TokType which, bool inplace_def = false )
if ( check( TokType::BraceCurly_Open ) )
{
body = parse_class_struct_body( which );
body = parse_class_struct_body( which, name );
}
if ( ! inplace_def )
@ -3122,6 +3165,158 @@ CodeClass parse_class( StrC def )
return result;
}
internal
CodeConstructor parse_constructor()
{
using namespace Parser;
push_scope();
Token identifier = parse_identifier();
CodeParam params = parse_params();
Code initializer_list = { nullptr };
CodeBody body = { nullptr };
if ( check( TokType::Assign_Classifer ) )
{
eat( TokType::Assign_Classifer );
Token initializer_list_tok;
s32 level = 0;
while ( left && ( currtok.Type != TokType::BraceCurly_Open || level > 0 ) )
{
if ( currtok.Type == TokType::BraceCurly_Open )
level++;
else if ( currtok.Type == TokType::BraceCurly_Close )
level--;
eat( currtok.Type );
}
initializer_list_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)initializer_list_tok.Text;
initializer_list = untyped_str( initializer_list_tok );
body = parse_function_body();
}
else if ( check( TokType::BraceCurly_Open ) )
{
body = parse_function_body();
}
CodeConstructor result = (CodeConstructor) make_code();
if ( params )
result->Params = params;
if ( initializer_list )
result->InitializerList = initializer_list;
if ( body )
{
result->Body = body;
result->Type = ECode::Constructor;
}
else
result->Type = ECode::Constructor_Fwd;
Context.pop();
return result;
}
CodeConstructor parse_constructor( StrC def )
{
check_parse_args( def );
using namespace Parser;
TokArray toks = lex( def );
if ( toks.Arr == nullptr )
return CodeInvalid;
Context.Tokens = toks;
CodeConstructor result = parse_constructor();
return result;
}
internal
CodeDestructor parse_destructor( CodeSpecifiers specifiers )
{
using namespace Parser;
push_scope();
if ( check( TokType::Spec_Virtual ) )
{
if ( specifiers )
specifiers.append( ESpecifier::Virtual );
else
specifiers = def_specifier( ESpecifier::Virtual );
eat( TokType::Spec_Virtual );
}
if ( left && currtok.Text[0] == '~' )
eat( TokType::Operator );
else
{
log_failure( "Expected destructor '~' token\n%s", Context.to_string() );
return CodeInvalid;
}
Token identifier = parse_identifier();
CodeBody body = { nullptr };
eat( TokType::Capture_Start );
eat( TokType::Capture_End );
if ( check( TokType::Operator ) && currtok.Text[0] == '=' )
{
eat( TokType::Operator );
if ( left && currtok.Text[0] == '0' )
{
eat( TokType::Number );
specifiers.append( ESpecifier::Pure );
}
else
{
log_failure( "Pure specifier expected due to '=' token\n%s", Context.to_string() );
return CodeInvalid;
}
}
if ( check( TokType::BraceCurly_Open ) )
body = parse_function_body();
CodeDestructor result = (CodeDestructor) make_code();
if ( specifiers )
result->Specs = specifiers;
if ( body )
{
result->Body = body;
result->Type = ECode::Destructor;
}
else
result->Type = ECode::Destructor_Fwd;
Context.pop();
return result;
}
CodeDestructor parse_destructor( StrC def )
{
check_parse_args( def );
using namespace Parser;
TokArray toks = lex( def );
if ( toks.Arr == nullptr )
return CodeInvalid;
Context.Tokens = toks;
CodeDestructor result = parse_destructor();
return result;
}
internal
CodeEnum parse_enum( bool inplace_def )
{
@ -4550,6 +4745,7 @@ CodeVar parse_variable( StrC def )
# undef check_parse_args
# undef currtok
# undef prevtok
# undef nexttok
# undef eat
# undef left
# undef check

View File

@ -422,6 +422,53 @@ CodeComment def_comment( StrC content )
return (CodeComment) result;
}
CodeConstructor def_constructor( CodeParam params, Code initializer_list, Code body )
{
using namespace ECode;
if ( params && params->Type != Parameters )
{
log_failure("gen::def_constructor: params must be of Parameters type - %s", params.debug_str());
return CodeInvalid;
}
CodeConstructor
result = (CodeConstructor) make_code();
if ( params )
{
result->Params = params;
}
if ( initializer_list )
{
result->InitializerList = initializer_list;
}
if ( body )
{
switch ( body->Type )
{
case Function_Body:
case Untyped:
break;
default:
log_failure("gen::def_constructor: body must be either of Function_Body or Untyped type - %s", body.debug_str());
return CodeInvalid;
}
result->Type = Constructor;
result->Body = body;
}
else
{
result->Type = Constructor_Fwd;
}
return result;
}
CodeClass def_class( StrC name
, Code body
, CodeType parent, AccessSpec parent_access
@ -512,6 +559,45 @@ CodeDefine def_define( StrC name, StrC content )
return result;
}
CodeDestructor def_destructor( Code body, CodeSpecifiers specifiers )
{
using namespace ECode;
if ( specifiers && specifiers->Type != Specifiers )
{
log_failure( "gen::def_destructor: specifiers was not a 'Specifiers' type: %s", specifiers.debug_str() );
return CodeInvalid;
}
CodeDestructor result = (CodeDestructor) make_code();
if ( specifiers )
result->Specs = specifiers;
if ( body )
{
switch ( body->Type )
{
case Function_Body:
case Untyped:
break;
default:
log_failure("gen::def_destructor: body must be either of Function_Body or Untyped type - %s", body.debug_str());
return CodeInvalid;
}
result->Type = Destructor;
result->Body = body;
}
else
{
result->Type = Destructor_Fwd;
}
return result;
}
CodeEnum def_enum( StrC name
, Code body, CodeType type
, EnumT specifier, CodeAttributes attributes

View File

@ -55,6 +55,7 @@ global CodeSpecifiers spec_mutable;
global CodeSpecifiers spec_neverinline;
global CodeSpecifiers spec_override;
global CodeSpecifiers spec_ptr;
global CodeSpecifiers spec_pure;
global CodeSpecifiers spec_ref;
global CodeSpecifiers spec_register;
global CodeSpecifiers spec_rvalue;

View File

@ -102,7 +102,9 @@ Define_CodeImpl( CodeBody );
Define_CodeImpl( CodeAttributes );
Define_CodeImpl( CodeComment );
Define_CodeImpl( CodeClass );
Define_CodeImpl( CodeConstructor );
Define_CodeImpl( CodeDefine );
Define_CodeImpl( CodeDestructor );
Define_CodeImpl( CodeEnum );
Define_CodeImpl( CodeExec );
Define_CodeImpl( CodeExtern );
@ -127,7 +129,9 @@ Define_CodeImpl( CodeVar );
Define_CodeType_Impl( Attributes );
Define_CodeType_Impl( Comment );
Define_CodeType_Impl( Constructor );
Define_CodeType_Impl( Define );
Define_CodeType_Impl( Destructor );
Define_CodeType_Impl( Enum );
Define_CodeType_Impl( Exec );
Define_CodeType_Impl( Extern );
@ -159,8 +163,10 @@ AST::operator Code ## typename() \
Define_AST_Cast( Body );
Define_AST_Cast( Attributes );
Define_AST_Cast( Comment );
Define_AST_Cast( Constructor );
Define_AST_Cast( Class );
Define_AST_Cast( Define );
Define_AST_Cast( Destructor );
Define_AST_Cast( Enum );
Define_AST_Cast( Exec );
Define_AST_Cast( Extern );
@ -192,8 +198,10 @@ Code::operator Code ## type() const \
Define_CodeCast( Attributes );
Define_CodeCast( Comment );
Define_CodeCast( Constructor );
Define_CodeCast( Class );
Define_CodeCast( Define );
Define_CodeCast( Destructor );
Define_CodeCast( Exec );
Define_CodeCast( Enum );
Define_CodeCast( Extern );

View File

@ -14,6 +14,10 @@ namespace ECode
Entry( Class ) \
Entry( Class_Fwd ) \
Entry( Class_Body ) \
Entry( Constructor ) \
Entry( Constructor_Fwd ) \
Entry( Destructor ) \
Entry( Destructor_Fwd ) \
Entry( Enum ) \
Entry( Enum_Fwd ) \
Entry( Enum_Body ) \

View File

@ -31,7 +31,8 @@ namespace ESpecifier
Entry( Virtual, virtual ) \
Entry( Const, const ) \
Entry( Final, final ) \
Entry( Override, override )
Entry( Override, override ) \
Entry( Pure, = 0 )
enum Type : u32
{

View File

@ -88,6 +88,7 @@ namespace Parser
Entry( Spec_Override, "override" ) \
Entry( Spec_Static, "static" ) \
Entry( Spec_ThreadLocal, "thread_local" ) \
Entry( Spec_Virtual, "virtual" ) \
Entry( Spec_Volatile, "volatile") \
Entry( Star, "*" ) \
Entry( Statement_End, ";" ) \

View File

@ -9,6 +9,10 @@ PlatformAttributes
Class
Class_Fwd
Class_Body
Constructor
Constructor_Fwd
Destructor
Destructor_Fwd
Enum
Enum_Fwd
Enum_Body

1 Invalid
9 Class
10 Class_Fwd
11 Class_Body
12 Constructor
13 Constructor_Fwd
14 Destructor
15 Destructor_Fwd
16 Enum
17 Enum_Fwd
18 Enum_Body

View File

@ -21,3 +21,4 @@ Virtual, virtual
Const, const
Final, final
Override, override
Pure, = 0

1 Invalid INVALID
21 Const const
22 Final final
23 Override override
24 Pure = 0

View File

@ -71,6 +71,7 @@ Spec_Override, "override"
Spec_Static, "static"
Spec_ThreadLocal, "thread_local"
Spec_Volatile, "volatile"
Spec_Virtual, "virtual"
Star, "*"
Statement_End, ";"
StaticAssert, "static_assert"

1 Invalid __invalid__
71 Spec_Static static
72 Spec_ThreadLocal thread_local
73 Spec_Volatile volatile
74 Spec_Virtual virtual
75 Star *
76 Statement_End ;
77 StaticAssert static_assert

View File

@ -437,8 +437,10 @@ CodeBody gen_ast_inlines()
CodeBody impl_code_body = parse_global_body( token_fmt( "typename", StrC name(CodeBody), code_impl_tmpl ));
CodeBody impl_code_attr = parse_global_body( token_fmt( "typename", StrC name(CodeAttributes), code_impl_tmpl ));
CodeBody impl_code_cmt = parse_global_body( token_fmt( "typename", StrC name(CodeComment), code_impl_tmpl ));
CodeBody impl_code_constr = parse_global_body( token_fmt( "typename", StrC name(CodeConstructor), code_impl_tmpl ));
CodeBody impl_code_class = parse_global_body( token_fmt( "typename", StrC name(CodeClass), code_impl_tmpl ));
CodeBody impl_code_define = parse_global_body( token_fmt( "typename", StrC name(CodeDefine), code_impl_tmpl ));
CodeBody impl_code_destruct = parse_global_body( token_fmt( "typename", StrC name(CodeDestructor), code_impl_tmpl ));
CodeBody impl_code_enum = parse_global_body( token_fmt( "typename", StrC name(CodeEnum), code_impl_tmpl ));
CodeBody impl_code_exec = parse_global_body( token_fmt( "typename", StrC name(CodeExec), code_impl_tmpl ));
CodeBody impl_code_extern = parse_global_body( token_fmt( "typename", StrC name(CodeExtern), code_impl_tmpl ));
@ -463,7 +465,9 @@ CodeBody gen_ast_inlines()
impl_code_attr. append( parse_global_body( token_fmt( "typename", StrC name(Attributes), codetype_impl_tmpl )));
impl_code_cmt. append( parse_global_body( token_fmt( "typename", StrC name(Comment), codetype_impl_tmpl )));
impl_code_constr. append( parse_global_body( token_fmt( "typename", StrC name(Constructor), codetype_impl_tmpl )));
impl_code_define. append( parse_global_body( token_fmt( "typename", StrC name(Define), codetype_impl_tmpl )));
impl_code_destruct.append( parse_global_body( token_fmt( "typename", StrC name(Destructor), codetype_impl_tmpl )));
impl_code_enum. append( parse_global_body( token_fmt( "typename", StrC name(Enum), codetype_impl_tmpl )));
impl_code_exec. append( parse_global_body( token_fmt( "typename", StrC name(Exec), codetype_impl_tmpl )));
impl_code_extern. append( parse_global_body( token_fmt( "typename", StrC name(Extern), codetype_impl_tmpl )));
@ -498,8 +502,10 @@ CodeBody gen_ast_inlines()
CodeBody impl_cast_body = parse_global_body( token_fmt( "typename", StrC name(Body), cast_tmpl ));
CodeBody impl_cast_attribute = parse_global_body( token_fmt( "typename", StrC name(Attributes), cast_tmpl ));
CodeBody impl_cast_cmt = parse_global_body( token_fmt( "typename", StrC name(Comment), cast_tmpl ));
CodeBody impl_cast_constr = parse_global_body( token_fmt( "typename", StrC name(Constructor), cast_tmpl ));
CodeBody impl_cast_class = parse_global_body( token_fmt( "typename", StrC name(Class), cast_tmpl ));
CodeBody impl_cast_define = parse_global_body( token_fmt( "typename", StrC name(Define), cast_tmpl ));
CodeBody impl_cast_destruct = parse_global_body( token_fmt( "typename", StrC name(Destructor), cast_tmpl ));
CodeBody impl_cast_enum = parse_global_body( token_fmt( "typename", StrC name(Enum), cast_tmpl ));
CodeBody impl_cast_exec = parse_global_body( token_fmt( "typename", StrC name(Exec), cast_tmpl ));
CodeBody impl_cast_extern = parse_global_body( token_fmt( "typename", StrC name(Extern), cast_tmpl ));
@ -529,8 +535,10 @@ CodeBody gen_ast_inlines()
impl_code_body,
impl_code_attr,
impl_code_cmt,
impl_code_constr,
impl_code_class,
impl_code_define,
impl_code_destruct,
impl_code_enum,
impl_code_exec,
impl_code_extern,
@ -560,8 +568,10 @@ CodeBody gen_ast_inlines()
impl_cast_body,
impl_cast_attribute,
impl_cast_cmt,
impl_cast_constr,
impl_cast_class,
impl_cast_define,
impl_cast_destruct,
impl_cast_enum,
impl_cast_exec,
impl_cast_extern,