GASATHON/Project/Source/GasaGen/gen.hpp
Ed_ 74689f6c6a 24. Health and Mana
Decided to try using gencpp for the first time with UE (just codegen, not parsing).

I used it to generate the AttributeSet
2024-04-13 16:18:57 -04:00

6508 lines
137 KiB
C++

// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
#pragma once
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-const-variable"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wvarargs"
#pragma clang diagnostic ignored "-Wunused-function"
#endif
#if __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wcomment"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
#pragma once
/*
gencpp: An attempt at "simple" staged metaprogramming for c/c++.
See Readme.md for more information from the project repository.
Public Address:
https://github.com/Ed94/gencpp
*/
#if ! defined( GEN_DONT_ENFORCE_GEN_TIME_GUARD ) && ! defined( GEN_TIME )
#error Gen.hpp : GEN_TIME not defined
#endif
//! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file.
// Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl
#ifndef GEN_ROLL_OWN_DEPENDENCIES
#include "gen.dep.hpp"
#endif
#ifndef GEN_NS_BEGIN
#ifdef GEN_DONT_USE_NAMESPACE
#define GEN_NS
#define GEN_NS_BEGIN
#define GEN_NS_END
#else
#define GEN_NS gen::
#define GEN_NS_BEGIN \
namespace gen \
{
#define GEN_NS_END }
#endif
#endif
GEN_NS_BEGIN
#pragma region Types
using LogFailType = sw ( * )( char const*, ... );
// By default this library will either crash or exit if an error is detected while generating codes.
// Even if set to not use GEN_FATAL, GEN_FATAL will still be used for memory failures as the library is unusable when they occur.
#ifdef GEN_DONT_USE_FATAL
#define log_failure log_fmt
#else
#define log_failure GEN_FATAL
#endif
enum class AccessSpec : u32
{
Default,
Public,
Protected,
Private,
Num_AccessSpec,
Invalid,
};
inline char const* to_str( AccessSpec type )
{
local_persist char const* lookup[ ( u32 )AccessSpec::Num_AccessSpec ] = {
"",
"public",
"protected",
"private",
};
if ( type > AccessSpec::Public )
return "Invalid";
return lookup[ ( u32 )type ];
}
enum CodeFlag : u32
{
None = 0,
FunctionType = bit( 0 ),
ParamPack = bit( 1 ),
Module_Export = bit( 2 ),
Module_Import = bit( 3 ),
};
// Used to indicate if enum definitoin is an enum class or regular enum.
enum class EnumT : u8
{
Regular,
Class
};
constexpr EnumT EnumClass = EnumT::Class;
constexpr EnumT EnumRegular = EnumT::Regular;
enum class ModuleFlag : u32
{
None = 0,
Export = bit( 0 ),
Import = bit( 1 ),
Num_ModuleFlags,
Invalid,
};
StrC to_str( ModuleFlag flag )
{
local_persist StrC lookup[ ( u32 )ModuleFlag::Num_ModuleFlags ] = {
{ sizeof( "__none__" ), "__none__" },
{ sizeof( "export" ), "export" },
{ sizeof( "import" ), "import" },
};
if ( flag > ModuleFlag::Import )
return { sizeof( "invalid" ), "invalid" };
return lookup[ ( u32 )flag ];
}
ModuleFlag operator|( ModuleFlag A, ModuleFlag B )
{
return ( ModuleFlag )( ( u32 )A | ( u32 )B );
}
enum class EPreprocessCond : u32
{
If,
IfDef,
IfNotDef,
ElIf
};
constexpr EPreprocessCond PreprocessCond_If = EPreprocessCond::If;
constexpr EPreprocessCond PreprocessCond_IfDef = EPreprocessCond::IfDef;
constexpr EPreprocessCond PreprocessCond_IfNotDef = EPreprocessCond::IfNotDef;
constexpr EPreprocessCond PreprocessCond_ElIf = EPreprocessCond::ElIf;
namespace ECode
{
enum Type : u32
{
Invalid,
Untyped,
NewLine,
Comment,
Access_Private,
Access_Protected,
Access_Public,
PlatformAttributes,
Class,
Class_Fwd,
Class_Body,
Constructor,
Constructor_Fwd,
Destructor,
Destructor_Fwd,
Enum,
Enum_Fwd,
Enum_Body,
Enum_Class,
Enum_Class_Fwd,
Execution,
Export_Body,
Extern_Linkage,
Extern_Linkage_Body,
Friend,
Function,
Function_Fwd,
Function_Body,
Global_Body,
Module,
Namespace,
Namespace_Body,
Operator,
Operator_Fwd,
Operator_Member,
Operator_Member_Fwd,
Operator_Cast,
Operator_Cast_Fwd,
Parameters,
Preprocess_Define,
Preprocess_Include,
Preprocess_If,
Preprocess_IfDef,
Preprocess_IfNotDef,
Preprocess_ElIf,
Preprocess_Else,
Preprocess_EndIf,
Preprocess_Pragma,
Specifiers,
Struct,
Struct_Fwd,
Struct_Body,
Template,
Typedef,
Typename,
Union,
Union_Body,
Using,
Using_Namespace,
Variable,
NumTypes
};
StrC to_str( Type type )
{
local_persist StrC lookup[] {
{ sizeof( "Invalid" ), "Invalid" },
{ sizeof( "Untyped" ), "Untyped" },
{ sizeof( "NewLine" ), "NewLine" },
{ sizeof( "Comment" ), "Comment" },
{ sizeof( "Access_Private" ), "Access_Private" },
{ sizeof( "Access_Protected" ), "Access_Protected" },
{ sizeof( "Access_Public" ), "Access_Public" },
{ sizeof( "PlatformAttributes" ), "PlatformAttributes" },
{ sizeof( "Class" ), "Class" },
{ sizeof( "Class_Fwd" ), "Class_Fwd" },
{ sizeof( "Class_Body" ), "Class_Body" },
{ sizeof( "Constructor" ), "Constructor" },
{ sizeof( "Constructor_Fwd" ), "Constructor_Fwd" },
{ sizeof( "Destructor" ), "Destructor" },
{ sizeof( "Destructor_Fwd" ), "Destructor_Fwd" },
{ sizeof( "Enum" ), "Enum" },
{ sizeof( "Enum_Fwd" ), "Enum_Fwd" },
{ sizeof( "Enum_Body" ), "Enum_Body" },
{ sizeof( "Enum_Class" ), "Enum_Class" },
{ sizeof( "Enum_Class_Fwd" ), "Enum_Class_Fwd" },
{ sizeof( "Execution" ), "Execution" },
{ sizeof( "Export_Body" ), "Export_Body" },
{ sizeof( "Extern_Linkage" ), "Extern_Linkage" },
{ sizeof( "Extern_Linkage_Body" ), "Extern_Linkage_Body" },
{ sizeof( "Friend" ), "Friend" },
{ sizeof( "Function" ), "Function" },
{ sizeof( "Function_Fwd" ), "Function_Fwd" },
{ sizeof( "Function_Body" ), "Function_Body" },
{ sizeof( "Global_Body" ), "Global_Body" },
{ sizeof( "Module" ), "Module" },
{ sizeof( "Namespace" ), "Namespace" },
{ sizeof( "Namespace_Body" ), "Namespace_Body" },
{ sizeof( "Operator" ), "Operator" },
{ sizeof( "Operator_Fwd" ), "Operator_Fwd" },
{ sizeof( "Operator_Member" ), "Operator_Member" },
{ sizeof( "Operator_Member_Fwd" ), "Operator_Member_Fwd" },
{ sizeof( "Operator_Cast" ), "Operator_Cast" },
{ sizeof( "Operator_Cast_Fwd" ), "Operator_Cast_Fwd" },
{ sizeof( "Parameters" ), "Parameters" },
{ sizeof( "Preprocess_Define" ), "Preprocess_Define" },
{ sizeof( "Preprocess_Include" ), "Preprocess_Include" },
{ sizeof( "Preprocess_If" ), "Preprocess_If" },
{ sizeof( "Preprocess_IfDef" ), "Preprocess_IfDef" },
{ sizeof( "Preprocess_IfNotDef" ), "Preprocess_IfNotDef" },
{ sizeof( "Preprocess_ElIf" ), "Preprocess_ElIf" },
{ sizeof( "Preprocess_Else" ), "Preprocess_Else" },
{ sizeof( "Preprocess_EndIf" ), "Preprocess_EndIf" },
{ sizeof( "Preprocess_Pragma" ), "Preprocess_Pragma" },
{ sizeof( "Specifiers" ), "Specifiers" },
{ sizeof( "Struct" ), "Struct" },
{ sizeof( "Struct_Fwd" ), "Struct_Fwd" },
{ sizeof( "Struct_Body" ), "Struct_Body" },
{ sizeof( "Template" ), "Template" },
{ sizeof( "Typedef" ), "Typedef" },
{ sizeof( "Typename" ), "Typename" },
{ sizeof( "Union" ), "Union" },
{ sizeof( "Union_Body" ), "Union_Body" },
{ sizeof( "Using" ), "Using" },
{ sizeof( "Using_Namespace" ), "Using_Namespace" },
{ sizeof( "Variable" ), "Variable" },
};
return lookup[ type ];
}
} // namespace ECode
using CodeT = ECode::Type;
namespace EOperator
{
enum Type : u32
{
Invalid,
Assign,
Assign_Add,
Assign_Subtract,
Assign_Multiply,
Assign_Divide,
Assign_Modulo,
Assign_BAnd,
Assign_BOr,
Assign_BXOr,
Assign_LShift,
Assign_RShift,
Increment,
Decrement,
Unary_Plus,
Unary_Minus,
UnaryNot,
Add,
Subtract,
Multiply,
Divide,
Modulo,
BNot,
BAnd,
BOr,
BXOr,
LShift,
RShift,
LAnd,
LOr,
LEqual,
LNot,
Lesser,
Greater,
LesserEqual,
GreaterEqual,
Subscript,
Indirection,
AddressOf,
MemberOfPointer,
PtrToMemOfPtr,
FunctionCall,
Comma,
NumOps
};
StrC to_str( Type op )
{
local_persist StrC lookup[] {
{ sizeof( "INVALID" ), "INVALID" },
{ sizeof( "=" ), "=" },
{ sizeof( "+=" ), "+=" },
{ sizeof( "-=" ), "-=" },
{ sizeof( "*=" ), "*=" },
{ sizeof( "/=" ), "/=" },
{ sizeof( "%=" ), "%=" },
{ sizeof( "&=" ), "&=" },
{ sizeof( "|=" ), "|=" },
{ sizeof( "^=" ), "^=" },
{ sizeof( "<<=" ), "<<=" },
{ sizeof( ">>=" ), ">>=" },
{ sizeof( "++" ), "++" },
{ sizeof( "--" ), "--" },
{ sizeof( "+" ), "+" },
{ sizeof( "-" ), "-" },
{ sizeof( "!" ), "!" },
{ sizeof( "+" ), "+" },
{ sizeof( "-" ), "-" },
{ sizeof( "*" ), "*" },
{ sizeof( "/" ), "/" },
{ sizeof( "%" ), "%" },
{ sizeof( "~" ), "~" },
{ sizeof( "&" ), "&" },
{ sizeof( "|" ), "|" },
{ sizeof( "^" ), "^" },
{ sizeof( "<<" ), "<<" },
{ sizeof( ">>" ), ">>" },
{ sizeof( "&&" ), "&&" },
{ sizeof( "||" ), "||" },
{ sizeof( "==" ), "==" },
{ sizeof( "!=" ), "!=" },
{ sizeof( "<" ), "<" },
{ sizeof( ">" ), ">" },
{ sizeof( "<=" ), "<=" },
{ sizeof( ">=" ), ">=" },
{ sizeof( "[]" ), "[]" },
{ sizeof( "*" ), "*" },
{ sizeof( "&" ), "&" },
{ sizeof( "->" ), "->" },
{ sizeof( "->*" ), "->*" },
{ sizeof( "()" ), "()" },
{ sizeof( "," ), "," },
};
return lookup[ op ];
}
} // namespace EOperator
using OperatorT = EOperator::Type;
namespace ESpecifier
{
enum Type : u32
{
Invalid,
Consteval,
Constexpr,
Constinit,
Explicit,
External_Linkage,
ForceInline,
Global,
Inline,
Internal_Linkage,
Local_Persist,
Mutable,
NeverInline,
Ptr,
Ref,
Register,
RValue,
Static,
Thread_Local,
Virtual,
Const,
Final,
NoExceptions,
Override,
Pure,
Volatile,
NumSpecifiers
};
bool is_trailing( Type specifier )
{
return specifier > Virtual;
}
StrC to_str( Type type )
{
local_persist StrC lookup[] {
{ sizeof( "INVALID" ), "INVALID" },
{ sizeof( "consteval" ), "consteval" },
{ sizeof( "constexpr" ), "constexpr" },
{ sizeof( "constinit" ), "constinit" },
{ sizeof( "explicit" ), "explicit" },
{ sizeof( "extern" ), "extern" },
{ sizeof( "forceinline" ), "forceinline" },
{ sizeof( "global" ), "global" },
{ sizeof( "inline" ), "inline" },
{ sizeof( "internal" ), "internal" },
{ sizeof( "local_persist" ), "local_persist" },
{ sizeof( "mutable" ), "mutable" },
{ sizeof( "neverinline" ), "neverinline" },
{ sizeof( "*" ), "*" },
{ sizeof( "&" ), "&" },
{ sizeof( "register" ), "register" },
{ sizeof( "&&" ), "&&" },
{ sizeof( "static" ), "static" },
{ sizeof( "thread_local" ), "thread_local" },
{ sizeof( "virtual" ), "virtual" },
{ sizeof( "const" ), "const" },
{ sizeof( "final" ), "final" },
{ sizeof( "noexcept" ), "noexcept" },
{ sizeof( "override" ), "override" },
{ sizeof( "= 0" ), "= 0" },
{ sizeof( "volatile" ), "volatile" },
};
return lookup[ type ];
}
Type to_type( StrC str )
{
local_persist u32 keymap[ NumSpecifiers ];
do_once_start for ( u32 index = 0; index < NumSpecifiers; index++ )
{
StrC enum_str = to_str( ( Type )index );
keymap[ index ] = crc32( enum_str.Ptr, enum_str.Len - 1 );
}
do_once_end u32 hash = crc32( str.Ptr, str.Len );
for ( u32 index = 0; index < NumSpecifiers; index++ )
{
if ( keymap[ index ] == hash )
return ( Type )index;
}
return Invalid;
}
} // namespace ESpecifier
using SpecifierT = ESpecifier::Type;
#pragma endregion Types
#pragma region AST
struct AST;
struct AST_Body;
struct AST_Attributes;
struct AST_Comment;
struct AST_Constructor;
// struct AST_BaseClass;
struct AST_Class;
struct AST_Define;
struct AST_Destructor;
struct AST_Enum;
struct AST_Exec;
struct AST_Extern;
struct AST_Include;
struct AST_Friend;
struct AST_Fn;
struct AST_Module;
struct AST_NS;
struct AST_Operator;
struct AST_OpCast;
struct AST_Param;
struct AST_Pragma;
struct AST_PreprocessCond;
struct AST_Specifiers;
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct AST_Expr;
struct AST_Expr_Assign;
struct AST_Expr_Alignof;
struct AST_Expr_Binary;
struct AST_Expr_CStyleCast;
struct AST_Expr_FunctionalCast;
struct AST_Expr_CppCast;
struct AST_Expr_ProcCall;
struct AST_Expr_Decltype;
struct AST_Expr_Comma; // TODO(Ed) : This is a binary op not sure if it needs its own AST...
struct AST_Expr_AMS; // Access Member Symbol
struct AST_Expr_Sizeof;
struct AST_Expr_Subscript;
struct AST_Expr_Ternary;
struct AST_Expr_UnaryPrefix;
struct AST_Expr_UnaryPostfix;
struct AST_Expr_Element;
struct AST_Stmt;
struct AST_Stmt_Break;
struct AST_Stmt_Case;
struct AST_Stmt_Continue;
struct AST_Stmt_Decl;
struct AST_Stmt_Do;
struct AST_Stmt_Expr; // TODO(Ed) : Is this distinction needed? (Should it be a flag instead?)
struct AST_Stmt_Else;
struct AST_Stmt_If;
struct AST_Stmt_For;
struct AST_Stmt_Goto;
struct AST_Stmt_Label;
struct AST_Stmt_Switch;
struct AST_Stmt_While;
#endif
struct AST_Struct;
struct AST_Template;
struct AST_Type;
struct AST_Typedef;
struct AST_Union;
struct AST_Using;
struct AST_Var;
struct Code;
struct CodeBody;
// These are to offer ease of use and optionally strong type safety for the AST.
struct CodeAttributes;
// struct CodeBaseClass;
struct CodeComment;
struct CodeClass;
struct CodeConstructor;
struct CodeDefine;
struct CodeDestructor;
struct CodeEnum;
struct CodeExec;
struct CodeExtern;
struct CodeInclude;
struct CodeFriend;
struct CodeFn;
struct CodeModule;
struct CodeNS;
struct CodeOperator;
struct CodeOpCast;
struct CodeParam;
struct CodePreprocessCond;
struct CodePragma;
struct CodeSpecifiers;
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct CodeExpr;
struct CodeExpr_Assign;
struct CodeExpr_Alignof;
struct CodeExpr_Binary;
struct CodeExpr_CStyleCast;
struct CodeExpr_FunctionalCast;
struct CodeExpr_CppCast;
struct CodeExpr_Element;
struct CodeExpr_ProcCall;
struct CodeExpr_Decltype;
struct CodeExpr_Comma;
struct CodeExpr_AMS; // Access Member Symbol
struct CodeExpr_Sizeof;
struct CodeExpr_Subscript;
struct CodeExpr_Ternary;
struct CodeExpr_UnaryPrefix;
struct CodeExpr_UnaryPostfix;
struct CodeStmt;
struct CodeStmt_Break;
struct CodeStmt_Case;
struct CodeStmt_Continue;
struct CodeStmt_Decl;
struct CodeStmt_Do;
struct CodeStmt_Expr;
struct CodeStmt_Else;
struct CodeStmt_If;
struct CodeStmt_For;
struct CodeStmt_Goto;
struct CodeStmt_Label;
struct CodeStmt_Switch;
struct CodeStmt_While;
#endif
struct CodeStruct;
struct CodeTemplate;
struct CodeType;
struct CodeTypedef;
struct CodeUnion;
struct CodeUsing;
struct CodeVar;
namespace parser
{
struct Token;
}
/*
AST* wrapper
- Not constantly have to append the '*' as this is written often..
- Allows for implicit conversion to any of the ASTs (raw or filtered).
*/
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
#define Using_Code( Typename ) \
char const* debug_str(); \
Code duplicate(); \
bool is_equal( Code other ); \
bool is_valid(); \
void set_global(); \
String to_string(); \
Typename& operator=( AST* other ); \
Typename& operator=( Code other ); \
bool operator==( Code other ); \
bool operator!=( Code other ); \
operator bool();
Using_Code( Code );
template< class Type >
forceinline Type cast()
{
return *rcast( Type*, this );
}
AST* operator->()
{
return ast;
}
Code& operator++();
// TODO(Ed) : Remove this overload.
auto& operator*()
{
local_persist thread_local Code NullRef = { nullptr };
if ( ast == nullptr )
return NullRef;
return *this;
}
AST* ast;
#ifdef GEN_ENFORCE_STRONG_CODE_TYPES
#define operator explicit operator
#endif
operator CodeBody() const;
operator CodeAttributes() const;
// operator CodeBaseClass() const;
operator CodeComment() const;
operator CodeClass() const;
operator CodeConstructor() const;
operator CodeDefine() const;
operator CodeDestructor() const;
operator CodeExec() const;
operator CodeEnum() const;
operator CodeExtern() const;
operator CodeInclude() const;
operator CodeFriend() const;
operator CodeFn() const;
operator CodeModule() const;
operator CodeNS() const;
operator CodeOperator() const;
operator CodeOpCast() const;
operator CodeParam() const;
operator CodePragma() const;
operator CodePreprocessCond() const;
operator CodeSpecifiers() const;
operator CodeStruct() const;
operator CodeTemplate() const;
operator CodeType() const;
operator CodeTypedef() const;
operator CodeUnion() const;
operator CodeUsing() const;
operator CodeVar() const;
#undef operator
};
struct Code_POD
{
AST* ast;
};
static_assert( sizeof( Code ) == sizeof( Code_POD ), "ERROR: Code is not POD" );
// Desired width of the AST data structure.
constexpr int const AST_POD_Size = 128;
/*
Simple AST POD with functionality to seralize into C++ syntax.
*/
struct AST
{
#pragma region Member Functions
void append( AST* other );
char const* debug_str();
AST* duplicate();
Code& entry( u32 idx );
bool has_entries();
bool is_equal( AST* other );
char const* type_str();
bool validate_body();
String to_string();
neverinline void to_string( String& result );
template< class Type >
forceinline Type cast()
{
return *this;
}
operator Code();
operator CodeBody();
operator CodeAttributes();
// operator CodeBaseClass();
operator CodeComment();
operator CodeConstructor();
operator CodeDestructor();
operator CodeClass();
operator CodeDefine();
operator CodeEnum();
operator CodeExec();
operator CodeExtern();
operator CodeInclude();
operator CodeFriend();
operator CodeFn();
operator CodeModule();
operator CodeNS();
operator CodeOperator();
operator CodeOpCast();
operator CodeParam();
operator CodePragma();
operator CodePreprocessCond();
operator CodeSpecifiers();
operator CodeStruct();
operator CodeTemplate();
operator CodeType();
operator CodeTypedef();
operator CodeUnion();
operator CodeUsing();
operator CodeVar();
#pragma endregion Member Functions
constexpr static int ArrSpecs_Cap = ( AST_POD_Size - sizeof( AST* ) * 3 - sizeof( parser::Token* ) - sizeof( AST* ) - sizeof( StringCached )
- sizeof( CodeT ) - sizeof( ModuleFlag ) - sizeof( int ) )
/ sizeof( int )
- 1; // -1 for 4 extra bytes
union
{
struct
{
AST* InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
AST* Specs; // Destructor, Function, Operator, Typename, Variable
union
{
AST* InitializerList; // Constructor
AST* ParentType; // Class, Struct, ParentType->Next has a possible list of interfaces.
AST* ReturnType; // Function, Operator, Typename
AST* UnderlyingType; // Enum, Typedef
AST* ValueType; // Parameter, Variable
};
union
{
AST* BitfieldSize; // Variable (Class/Struct Data Member)
AST* Params; // Constructor, Function, Operator, Template, Typename
};
union
{
AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
union
{
AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr =
// NextVar->Value )
AST* SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed )
};
};
StringCached Content; // Attributes, Comment, Execution, Include
struct
{
SpecifierT ArrSpecs[ ArrSpecs_Cap ]; // Specifiers
AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used.
};
};
union
{
AST* Prev;
AST* Front;
AST* Last;
};
union
{
AST* Next;
AST* Back;
};
parser::Token* Token; // Reference to starting token, only avaialble if it was derived from parsing.
AST* Parent;
StringCached Name;
CodeT Type;
// CodeFlag CodeFlags;
ModuleFlag ModuleFlags;
union
{
b32 IsFunction; // Used by typedef to not serialize the name field.
b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack.
OperatorT Op;
AccessSpec ParentAccess;
s32 NumEntries;
};
};
struct AST_POD
{
union
{
struct
{
AST* InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
AST* Specs; // Destructor, Function, Operator, Typename, Variable
union
{
AST* InitializerList; // Constructor
AST* ParentType; // Class, Struct, ParentType->Next has a possible list of interfaces.
AST* ReturnType; // Function, Operator, Typename
AST* UnderlyingType; // Enum, Typedef
AST* ValueType; // Parameter, Variable
};
union
{
AST* BitfieldSize; // Variable (Class/Struct Data Member)
AST* Params; // Constructor, Function, Operator, Template, Typename
};
union
{
AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
union
{
AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr =
// NextVar->Value )
AST* SuffixSpecs; // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed )
};
};
StringCached Content; // Attributes, Comment, Execution, Include
struct
{
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ]; // Specifiers
AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used.
};
};
union
{
AST* Prev;
AST* Front;
AST* Last;
};
union
{
AST* Next;
AST* Back;
};
parser::Token* Token; // Reference to starting token, only avaialble if it was derived from parsing.
AST* Parent;
StringCached Name;
CodeT Type;
CodeFlag CodeFlags;
ModuleFlag ModuleFlags;
union
{
b32 IsFunction; // Used by typedef to not serialize the name field.
b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack.
OperatorT Op;
AccessSpec ParentAccess;
s32 NumEntries;
};
};
struct test
{
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ]; // Specifiers
AST* NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used.
};
constexpr int pls = sizeof( test );
// 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( AST_POD ), "ERROR: AST IS NOT POD" );
static_assert( sizeof( AST_POD ) == AST_POD_Size, "ERROR: AST POD is not size of AST_POD_Size" );
// Used when the its desired when omission is allowed in a definition.
#define NoCode \
{ \
nullptr \
}
#define CodeInvalid ( *Code::Invalid.ast ) // Uses an implicitly overloaded cast from the AST to the desired code type.
#pragma region Code Types
struct CodeBody
{
Using_Code( CodeBody );
void append( Code other )
{
raw()->append( other.ast );
}
void append( CodeBody body )
{
for ( Code entry : body )
{
append( entry );
}
}
bool has_entries()
{
return rcast( AST*, ast )->has_entries();
}
void to_string( String& result );
void to_string_export( String& result );
AST* raw()
{
return rcast( AST*, ast );
}
AST_Body* operator->()
{
return ast;
}
operator Code()
{
return *rcast( Code*, this );
}
#pragma region Iterator
Code begin()
{
if ( ast )
return { rcast( AST*, ast )->Front };
return { nullptr };
}
Code end()
{
return { rcast( AST*, ast )->Back->Next };
}
#pragma endregion Iterator
AST_Body* ast;
};
struct CodeClass
{
Using_Code( CodeClass );
void add_interface( CodeType interface );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw()
{
return rcast( AST*, ast );
}
operator Code()
{
return *rcast( Code*, this );
}
AST_Class* operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr" );
return nullptr;
}
return ast;
}
AST_Class* ast;
};
struct CodeParam
{
Using_Code( CodeParam );
void append( CodeParam other );
CodeParam get( s32 idx );
bool has_entries();
void to_string( String& result );
AST* raw()
{
return rcast( AST*, ast );
}
AST_Param* operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
operator Code()
{
return { ( AST* )ast };
}
#pragma region Iterator
CodeParam begin()
{
if ( ast )
return { ast };
return { nullptr };
}
CodeParam end()
{
// return { (AST_Param*) rcast( AST*, ast)->Last };
return { nullptr };
}
CodeParam& operator++();
CodeParam operator*()
{
return *this;
}
#pragma endregion Iterator
AST_Param* ast;
};
struct CodeSpecifiers
{
Using_Code( CodeSpecifiers );
bool append( SpecifierT spec )
{
if ( ast == nullptr )
{
log_failure( "CodeSpecifiers: Attempted to append to a null specifiers AST!" );
return false;
}
if ( raw()->NumEntries == AST::ArrSpecs_Cap )
{
log_failure( "CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST::ArrSpecs_Cap );
return false;
}
raw()->ArrSpecs[ raw()->NumEntries ] = spec;
raw()->NumEntries++;
return true;
}
s32 has( SpecifierT spec )
{
for ( s32 idx = 0; idx < raw()->NumEntries; idx++ )
{
if ( raw()->ArrSpecs[ raw()->NumEntries ] == spec )
return idx;
}
return -1;
}
void to_string( String& result );
AST* raw()
{
return rcast( AST*, ast );
}
AST_Specifiers* operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
operator Code()
{
return { ( AST* )ast };
}
#pragma region Iterator
SpecifierT* begin()
{
if ( ast )
return &raw()->ArrSpecs[ 0 ];
return nullptr;
}
SpecifierT* end()
{
return raw()->ArrSpecs + raw()->NumEntries;
}
#pragma endregion Iterator
AST_Specifiers* ast;
};
struct CodeStruct
{
Using_Code( CodeStruct );
void add_interface( CodeType interface );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw()
{
return rcast( AST*, ast );
}
operator Code()
{
return *rcast( Code*, this );
}
AST_Struct* operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr" );
return nullptr;
}
return ast;
}
AST_Struct* ast;
};
#define Define_CodeType( Typename ) \
struct Code##Typename \
{ \
Using_Code( Code##Typename ); \
AST* raw(); \
operator Code(); \
AST_##Typename* operator->(); \
AST_##Typename* ast; \
}
Define_CodeType( Attributes );
// Define_CodeType( BaseClass );
Define_CodeType( Comment );
struct CodeConstructor
{
Using_Code( CodeConstructor );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw();
operator Code();
AST_Constructor* operator->();
AST_Constructor* ast;
};
struct CodeDefine
{
Using_Code( CodeDefine );
void to_string( String& result );
AST* raw();
operator Code();
AST_Define* operator->();
AST_Define* ast;
};
struct CodeDestructor
{
Using_Code( CodeDestructor );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw();
operator Code();
AST_Destructor* operator->();
AST_Destructor* ast;
};
struct CodeEnum
{
Using_Code( CodeEnum );
void to_string_def( String& result );
void to_string_fwd( String& result );
void to_string_class_def( String& result );
void to_string_class_fwd( String& result );
AST* raw();
operator Code();
AST_Enum* operator->();
AST_Enum* ast;
};
Define_CodeType( Exec );
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct CodeExpr
{
Using_Code( CodeExpr );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr* operator->();
AST_Expr* ast;
};
struct CodeExpr_Assign
{
Using_Code( CodeExpr_Assign );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Assign* operator->();
AST_Expr_Assign* ast;
};
struct CodeExpr_Alignof
{
Using_Code( CodeExpr_Alignof );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Alignof* operator->();
AST_Expr_Alignof* ast;
};
struct CodeExpr_Binary
{
Using_Code( CodeExpr_Binary );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Binary* operator->();
AST_Expr_Binary* ast;
};
struct CodeExpr_CStyleCast
{
Using_Code( CodeExpr_CStyleCast );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_CStyleCast* operator->();
AST_Expr_CStyleCast* ast;
};
struct CodeExpr_FunctionalCast
{
Using_Code( CodeExpr_FunctionalCast );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_FunctionalCast* operator->();
AST_Expr_FunctionalCast* ast;
};
struct CodeExpr_CppCast
{
Using_Code( CodeExpr_CppCast );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_CppCast* operator->();
AST_Expr_CppCast* ast;
};
struct CodeExpr_Element
{
Using_Code( CodeExpr_Element );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Element* operator->();
AST_Expr_Element* ast;
};
struct CodeExpr_ProcCall
{
Using_Code( CodeExpr_ProcCall );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_ProcCall* operator->();
AST_Expr_ProcCall* ast;
};
struct CodeExpr_Decltype
{
Using_Code( CodeExpr_Decltype );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Decltype* operator->();
AST_Expr_Decltype* ast;
};
struct CodeExpr_Comma
{
Using_Code( CodeExpr_Comma );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Comma* operator->();
AST_Expr_Comma* ast;
};
struct CodeExpr_AMS
{
Using_Code( CodeExpr_AMS );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_AMS* operator->();
AST_Expr_AMS* ast;
};
struct CodeExpr_Sizeof
{
Using_Code( CodeExpr_Sizeof );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Sizeof* operator->();
AST_Expr_Sizeof* ast;
};
struct CodeExpr_Subscript
{
Using_Code( CodeExpr_Subscript );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Subscript* operator->();
AST_Expr_Subscript* ast;
};
struct CodeExpr_Ternary
{
Using_Code( CodeExpr_Ternary );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_Ternary* operator->();
AST_Expr_Ternary* ast;
};
struct CodeExpr_UnaryPrefix
{
Using_Code( CodeExpr_UnaryPrefix );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_UnaryPrefix* operator->();
AST_Expr_UnaryPrefix* ast;
};
struct CodeExpr_UnaryPostfix
{
Using_Code( CodeExpr_UnaryPostfix );
void to_string( String& result );
AST* raw();
operator Code();
AST_Expr_UnaryPostfix* operator->();
AST_Expr_UnaryPostfix* ast;
};
#endif
struct CodeExtern
{
Using_Code( CodeExtern );
void to_string( String& result );
AST* raw();
operator Code();
AST_Extern* operator->();
AST_Extern* ast;
};
struct CodeInclude
{
Using_Code( CodeInclude );
void to_string( String& result );
AST* raw();
operator Code();
AST_Include* operator->();
AST_Include* ast;
};
struct CodeFriend
{
Using_Code( CodeFriend );
void to_string( String& result );
AST* raw();
operator Code();
AST_Friend* operator->();
AST_Friend* ast;
};
struct CodeFn
{
Using_Code( CodeFn );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw();
operator Code();
AST_Fn* operator->();
AST_Fn* ast;
};
struct CodeModule
{
Using_Code( CodeModule );
void to_string( String& result );
AST* raw();
operator Code();
AST_Module* operator->();
AST_Module* ast;
};
struct CodeNS
{
Using_Code( CodeNS );
void to_string( String& result );
AST* raw();
operator Code();
AST_NS* operator->();
AST_NS* ast;
};
struct CodeOperator
{
Using_Code( CodeOperator );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw();
operator Code();
AST_Operator* operator->();
AST_Operator* ast;
};
struct CodeOpCast
{
Using_Code( CodeOpCast );
void to_string_def( String& result );
void to_string_fwd( String& result );
AST* raw();
operator Code();
AST_OpCast* operator->();
AST_OpCast* ast;
};
struct CodePragma
{
Using_Code( CodePragma );
void to_string( String& result );
AST* raw();
operator Code();
AST_Pragma* operator->();
AST_Pragma* ast;
};
struct CodePreprocessCond
{
Using_Code( CodePreprocessCond );
void to_string_if( String& result );
void to_string_ifdef( String& result );
void to_string_ifndef( String& result );
void to_string_elif( String& result );
void to_string_else( String& result );
void to_string_endif( String& result );
AST* raw();
operator Code();
AST_PreprocessCond* operator->();
AST_PreprocessCond* ast;
};
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct CodeStmt
{
Using_Code( CodeStmt );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt* operator->();
AST_Stmt* ast;
};
struct CodeStmt_Break
{
Using_Code( CodeStmt_Break );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Break* operator->();
AST_Stmt_Break* ast;
};
struct CodeStmt_Case
{
Using_Code( CodeStmt_Case );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Case* operator->();
AST_Stmt_Case* ast;
};
struct CodeStmt_Continue
{
Using_Code( CodeStmt_Continue );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Continue* operator->();
AST_Stmt_Continue* ast;
};
struct CodeStmt_Decl
{
Using_Code( CodeStmt_Decl );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Decl* operator->();
AST_Stmt_Decl* ast;
};
struct CodeStmt_Do
{
Using_Code( CodeStmt_Do );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Do* operator->();
AST_Stmt_Do* ast;
};
struct CodeStmt_Expr
{
Using_Code( CodeStmt_Expr );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Expr* operator->();
AST_Stmt_Expr* ast;
};
struct CodeStmt_Else
{
Using_Code( CodeStmt_Else );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Else* operator->();
AST_Stmt_Else* ast;
};
struct CodeStmt_If
{
Using_Code( CodeStmt_If );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_If* operator->();
AST_Stmt_If* ast;
};
struct CodeStmt_For
{
Using_Code( CodeStmt_For );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_For* operator->();
AST_Stmt_For* ast;
};
struct CodeStmt_Goto
{
Using_Code( CodeStmt_Goto );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Goto* operator->();
AST_Stmt_Goto* ast;
};
struct CodeStmt_Label
{
Using_Code( CodeStmt_Label );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Label* operator->();
AST_Stmt_Label* ast;
};
struct CodeStmt_Switch
{
Using_Code( CodeStmt_Switch );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_Switch* operator->();
AST_Stmt_Switch* ast;
};
struct CodeStmt_While
{
Using_Code( CodeStmt_While );
void to_string( String& result );
AST* raw();
operator Code();
AST_Stmt_While* operator->();
AST_Stmt_While* ast;
};
#endif
struct CodeTemplate
{
Using_Code( CodeTemplate );
void to_string( String& result );
AST* raw();
operator Code();
AST_Template* operator->();
AST_Template* ast;
};
struct CodeType
{
Using_Code( CodeType );
void to_string( String& result );
AST* raw();
operator Code();
AST_Type* operator->();
AST_Type* ast;
};
struct CodeTypedef
{
Using_Code( CodeTypedef );
void to_string( String& result );
AST* raw();
operator Code();
AST_Typedef* operator->();
AST_Typedef* ast;
};
struct CodeUnion
{
Using_Code( CodeUnion );
void to_string( String& result );
AST* raw();
operator Code();
AST_Union* operator->();
AST_Union* ast;
};
struct CodeUsing
{
Using_Code( CodeUsing );
void to_string( String& result );
void to_string_ns( String& result );
AST* raw();
operator Code();
AST_Using* operator->();
AST_Using* ast;
};
struct CodeVar
{
Using_Code( CodeVar );
void to_string( String& result );
AST* raw();
operator Code();
AST_Var* operator->();
AST_Var* ast;
};
#undef Define_CodeType
#undef Using_Code
#pragma endregion Code Types
#pragma region AST Types
/*
Show only relevant members of the AST for its type.
AST* fields are replaced with Code types.
- Guards assignemnts to AST* fields to ensure the AST is duplicated if assigned to another parent.
*/
struct AST_Body
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
Code Front;
Code Back;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) ];
s32 NumEntries;
};
static_assert( sizeof( AST_Body ) == sizeof( AST ), "ERROR: AST_Body is not the same size as AST" );
struct AST_Attributes
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Attributes ) == sizeof( AST ), "ERROR: AST_Attributes is not the same size as AST" );
#if 0
struct AST_BaseClass
{
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ];
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
};
static_assert( sizeof(AST_BaseClass) == sizeof(AST), "ERROR: AST_BaseClass is not the same size as AST");
#endif
struct AST_Comment
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Comment ) == sizeof( AST ), "ERROR: AST_Comment is not the same size as AST" );
struct AST_Class
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt; // Only supported by forward declarations
CodeAttributes Attributes;
char _PAD_SPECS_[ sizeof( AST* ) ];
CodeType ParentType;
char _PAD_PARAMS_[ sizeof( AST* ) ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
CodeType Prev;
CodeType Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
};
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 + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt; // Only supported by forward declarations
char _PAD_PROPERTIES_[ sizeof( AST* ) * 1 ];
CodeSpecifiers Specs;
Code InitializerList;
CodeParam Params;
Code Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) * 2 ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
char _PAD_NAME_[ sizeof( StringCached ) ];
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
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
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 + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof( AST* ) * 1 ];
CodeSpecifiers Specs;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) * 2 ];
Code Body;
char _PAD_PROPERTIES_3_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
char _PAD_NAME_[ sizeof( StringCached ) ];
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
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
char _PAD_SPEC_[ sizeof( AST* ) ];
CodeType UnderlyingType;
char _PAD_PARAMS_[ sizeof( AST* ) ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Enum ) == sizeof( AST ), "ERROR: AST_Enum is not the same size as AST" );
struct AST_Exec
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Exec ) == sizeof( AST ), "ERROR: AST_Exec is not the same size as AST" );
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct AST_Expr
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr ) == sizeof( AST ), "ERROR: AST_Expr is not the same size as AST" );
struct AST_Expr_Assign
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Assign ) == sizeof( AST ), "ERROR: AST_Expr_Assign is not the same size as AST" );
struct AST_Expr_Alignof
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Alignof ) == sizeof( AST ), "ERROR: AST_Expr_Alignof is not the same size as AST" );
struct AST_Expr_Binary
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Binary ) == sizeof( AST ), "ERROR: AST_Expr_Binary is not the same size as AST" );
struct AST_Expr_CStyleCast
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_CStyleCast ) == sizeof( AST ), "ERROR: AST_Expr_CStyleCast is not the same size as AST" );
struct AST_Expr_FunctionalCast
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_FunctionalCast ) == sizeof( AST ), "ERROR: AST_Expr_FunctionalCast is not the same size as AST" );
struct AST_Expr_CppCast
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_CppCast ) == sizeof( AST ), "ERROR: AST_Expr_CppCast is not the same size as AST" );
struct AST_Expr_ProcCall
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_ProcCall ) == sizeof( AST ), "ERROR: AST_Expr_Identifier is not the same size as AST" );
struct AST_Expr_Decltype
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Decltype ) == sizeof( AST ), "ERROR: AST_Expr_Decltype is not the same size as AST" );
struct AST_Expr_Comma
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Comma ) == sizeof( AST ), "ERROR: AST_Expr_Comma is not the same size as AST" );
struct AST_Expr_AMS
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_AMS ) == sizeof( AST ), "ERROR: AST_Expr_AMS is not the same size as AST" );
struct AST_Expr_Sizeof
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Sizeof ) == sizeof( AST ), "ERROR: AST_Expr_Sizeof is not the same size as AST" );
struct AST_Expr_Subscript
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Subscript ) == sizeof( AST ), "ERROR: AST_Expr_Subscript is not the same size as AST" );
struct AST_Expr_Ternary
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Ternary ) == sizeof( AST ), "ERROR: AST_Expr_Ternary is not the same size as AST" );
struct AST_Expr_UnaryPrefix
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_UnaryPrefix ) == sizeof( AST ), "ERROR: AST_Expr_UnaryPrefix is not the same size as AST" );
struct AST_Expr_UnaryPostfix
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_UnaryPostfix ) == sizeof( AST ), "ERROR: AST_Expr_UnaryPostfix is not the same size as AST" );
struct AST_Expr_Element
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Expr_Element ) == sizeof( AST ), "ERROR: AST_Expr_Element is not the same size as AST" );
#endif
struct AST_Extern
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
char _PAD_PROPERTIES_[ sizeof( AST* ) * 5 ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Extern ) == sizeof( AST ), "ERROR: AST_Extern is not the same size as AST" );
struct AST_Include
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Include ) == sizeof( AST ), "ERROR: AST_Include is not the same size as AST" );
struct AST_Friend
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof( AST* ) * 4 ];
Code Declaration;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Friend ) == sizeof( AST ), "ERROR: AST_Friend is not the same size as AST" );
struct AST_Fn
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParam Params;
CodeBody Body;
char _PAD_PROPERTIES_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Fn ) == sizeof( AST ), "ERROR: AST_Fn is not the same size as AST" );
struct AST_Module
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Module ) == sizeof( AST ), "ERROR: AST_Module is not the same size as AST" );
struct AST_NS
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
char _PAD_PROPERTIES_[ sizeof( AST* ) * 5 ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_NS ) == sizeof( AST ), "ERROR: AST_NS is not the same size as AST" );
struct AST_Operator
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParam Params;
CodeBody Body;
char _PAD_PROPERTIES_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
OperatorT Op;
};
static_assert( sizeof( AST_Operator ) == sizeof( AST ), "ERROR: AST_Operator is not the same size as AST" );
struct AST_OpCast
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof( AST* ) ];
CodeSpecifiers Specs;
CodeType ValueType;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
CodeBody Body;
char _PAD_PROPERTIES_3_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_OpCast ) == sizeof( AST ), "ERROR: AST_OpCast is not the same size as AST" );
struct AST_Param
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
char _PAD_PROPERTIES_2_[ sizeof( AST* ) * 3 ];
CodeType ValueType;
char _PAD_PROPERTIES_[ sizeof( AST* ) ];
Code Value;
char _PAD_PROPERTIES_3_[ sizeof( AST* ) ];
};
};
CodeParam Last;
CodeParam Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) ];
s32 NumEntries;
};
static_assert( sizeof( AST_Param ) == sizeof( AST ), "ERROR: AST_Param is not the same size as AST" );
struct AST_Pragma
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Pragma ) == sizeof( AST ), "ERROR: AST_Pragma is not the same size as AST" );
struct AST_PreprocessCond
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
StringCached Content;
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_PreprocessCond ) == sizeof( AST ), "ERROR: AST_PreprocessCond is not the same size as AST" );
struct AST_Specifiers
{
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ];
CodeSpecifiers NextSpecs;
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) ];
s32 NumEntries;
};
static_assert( sizeof( AST_Specifiers ) == sizeof( AST ), "ERROR: AST_Specifier is not the same size as AST" );
#if GEN_EXECUTION_EXPRESSION_SUPPORT
struct AST_Stmt
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt ) == sizeof( AST ), "ERROR: AST_Stmt is not the same size as AST" );
struct AST_Stmt_Break
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Break ) == sizeof( AST ), "ERROR: AST_Stmt_Break is not the same size as AST" );
struct AST_Stmt_Case
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Case ) == sizeof( AST ), "ERROR: AST_Stmt_Case is not the same size as AST" );
struct AST_Stmt_Continue
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Continue ) == sizeof( AST ), "ERROR: AST_Stmt_Continue is not the same size as AST" );
struct AST_Stmt_Decl
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Decl ) == sizeof( AST ), "ERROR: AST_Stmt_Decl is not the same size as AST" );
struct AST_Stmt_Do
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Do ) == sizeof( AST ), "ERROR: AST_Stmt_Do is not the same size as AST" );
struct AST_Stmt_Expr
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Expr ) == sizeof( AST ), "ERROR: AST_Stmt_Expr is not the same size as AST" );
struct AST_Stmt_Else
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Else ) == sizeof( AST ), "ERROR: AST_Stmt_Else is not the same size as AST" );
struct AST_Stmt_If
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_If ) == sizeof( AST ), "ERROR: AST_Stmt_If is not the same size as AST" );
struct AST_Stmt_For
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_For ) == sizeof( AST ), "ERROR: AST_Stmt_For is not the same size as AST" );
struct AST_Stmt_Goto
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Goto ) == sizeof( AST ), "ERROR: AST_Stmt_Goto is not the same size as AST" );
struct AST_Stmt_Label
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Label ) == sizeof( AST ), "ERROR: AST_Stmt_Label is not the same size as AST" );
struct AST_Stmt_Switch
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_Switch ) == sizeof( AST ), "ERROR: AST_Stmt_Switch is not the same size as AST" );
struct AST_Stmt_While
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
} CodeExpr Prev;
CodeExpr Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) + sizeof( u32 ) ];
};
static_assert( sizeof( AST_Stmt_While ) == sizeof( AST ), "ERROR: AST_Stmt_While is not the same size as AST" );
#endif
struct AST_Struct
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
char _PAD_SPECS_[ sizeof( AST* ) ];
CodeType ParentType;
char _PAD_PARAMS_[ sizeof( AST* ) ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
CodeType Prev;
CodeType Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
};
static_assert( sizeof( AST_Struct ) == sizeof( AST ), "ERROR: AST_Struct is not the same size as AST" );
struct AST_Template
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
char _PAD_PROPERTIES_[ sizeof( AST* ) * 4 ];
CodeParam Params;
Code Declaration;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Template ) == sizeof( AST ), "ERROR: AST_Template is not the same size as AST" );
#if 0
// WIP... The type ast is going to become more advanced and lead to a major change to AST design.
struct AST_Type
{
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ];
struct
{
char _PAD_INLINE_CMT_[ sizeof(AST*) ];
CodeAttributes Attributes;
CodeSpecifiers Specs;
Code QualifierID;
// CodeType ReturnType; // Only used for function signatures
// CodeParam Params; // Only used for function signatures
Code ArrExpr;
// CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
b32 IsParamPack;
};
static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same size as AST");
#endif
struct AST_Type
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
char _PAD_INLINE_CMT_[ sizeof( AST* ) ];
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType; // Only used for function signatures
CodeParam Params; // Only used for function signatures
Code ArrExpr;
CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof( ModuleFlag ) ];
b32 IsParamPack;
};
static_assert( sizeof( AST_Type ) == sizeof( AST ), "ERROR: AST_Type is not the same size as AST" );
struct AST_Typedef
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof( AST* ) * 2 ];
Code UnderlyingType;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) * 3 ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
b32 IsFunction;
};
static_assert( sizeof( AST_Typedef ) == sizeof( AST ), "ERROR: AST_Typedef is not the same size as AST" );
struct AST_Union
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
char _PAD_INLINE_CMT_[ sizeof( AST* ) ];
CodeAttributes Attributes;
char _PAD_PROPERTIES_[ sizeof( AST* ) * 3 ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof( AST* ) ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Union ) == sizeof( AST ), "ERROR: AST_Union is not the same size as AST" );
struct AST_Using
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
char _PAD_SPECS_[ sizeof( AST* ) ];
CodeType UnderlyingType;
char _PAD_PROPERTIES_[ sizeof( AST* ) * 3 ];
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Using ) == sizeof( AST ), "ERROR: AST_Using is not the same size as AST" );
struct AST_Var
{
union
{
char _PAD_[ sizeof( SpecifierT ) * AST::ArrSpecs_Cap + sizeof( AST* ) ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ValueType;
Code BitfieldSize;
Code Value;
CodeVar NextVar;
};
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof( u32 ) ];
};
static_assert( sizeof( AST_Var ) == sizeof( AST ), "ERROR: AST_Var is not the same size as AST" );
#pragma endregion AST Types
#pragma endregion AST
#pragma region Gen Interface
// Initialize the library.
// 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();
// Clears the allocations, but doesn't return to the heap, the calls init() again.
// Ease of use.
void reset();
// Used internally to retrive or make string allocations.
// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena)
StringCached get_cached_string( StrC str );
/*
This provides a fresh Code AST.
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_allocator_data_arrays( AllocatorInfo data_array_allocator );
void set_allocator_code_pool( AllocatorInfo pool_allocator );
void set_allocator_lexer( AllocatorInfo lex_allocator );
void set_allocator_string_arena( AllocatorInfo string_allocator );
void set_allocator_string_table( AllocatorInfo string_allocator );
void set_allocator_type_table( AllocatorInfo type_reg_allocator );
#pragma region Upfront
CodeAttributes def_attributes( StrC content );
CodeComment def_comment( StrC content );
CodeClass def_class(
StrC name,
Code body = NoCode,
CodeType parent = NoCode,
AccessSpec access = AccessSpec::Default,
CodeAttributes attributes = NoCode,
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,
ModuleFlag mflags = ModuleFlag::None
);
CodeExec def_execution( StrC content );
CodeExtern def_extern_link( StrC name, Code body );
CodeFriend def_friend( Code symbol );
CodeFn def_function(
StrC name,
CodeParam params = NoCode,
CodeType ret_type = NoCode,
Code body = NoCode,
CodeSpecifiers specifiers = NoCode,
CodeAttributes attributes = NoCode,
ModuleFlag mflags = ModuleFlag::None
);
CodeInclude def_include( StrC content, bool foreign = false );
CodeModule def_module( StrC name, ModuleFlag mflags = ModuleFlag::None );
CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None );
CodeOperator def_operator(
OperatorT op,
StrC nspace,
CodeParam params = NoCode,
CodeType ret_type = NoCode,
Code body = NoCode,
CodeSpecifiers specifiers = NoCode,
CodeAttributes attributes = NoCode,
ModuleFlag mflags = ModuleFlag::None
);
CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode );
CodeParam def_param( CodeType type, StrC name, Code value = NoCode );
CodePragma def_pragma( StrC directive );
CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC content );
CodeSpecifiers def_specifier( SpecifierT specifier );
CodeStruct def_struct(
StrC name,
Code body = NoCode,
CodeType parent = NoCode,
AccessSpec access = AccessSpec::Default,
CodeAttributes attributes = NoCode,
ModuleFlag mflags = ModuleFlag::None,
CodeType* interfaces = nullptr,
s32 num_interfaces = 0
);
CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag::None );
CodeType def_type( StrC name, Code arrayexpr = NoCode, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode );
CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
CodeUnion def_union( StrC name, Code body, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );
CodeUsing def_using( StrC name, CodeType type = NoCode, CodeAttributes attributess = NoCode, ModuleFlag mflags = ModuleFlag::None );
CodeUsing def_using_namespace( StrC name );
CodeVar def_variable(
CodeType type,
StrC name,
Code value = NoCode,
CodeSpecifiers specifiers = NoCode,
CodeAttributes attributes = NoCode,
ModuleFlag mflags = ModuleFlag::None
);
// Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries.
CodeBody def_body( CodeT type );
// There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num,
/// or provide as an array of Code objects.
CodeBody def_class_body( s32 num, ... );
CodeBody def_class_body( s32 num, Code* codes );
CodeBody def_enum_body( s32 num, ... );
CodeBody def_enum_body( s32 num, Code* codes );
CodeBody def_export_body( s32 num, ... );
CodeBody def_export_body( s32 num, Code* codes );
CodeBody def_extern_link_body( s32 num, ... );
CodeBody def_extern_link_body( s32 num, Code* codes );
CodeBody def_function_body( s32 num, ... );
CodeBody def_function_body( s32 num, Code* codes );
CodeBody def_global_body( s32 num, ... );
CodeBody def_global_body( s32 num, Code* codes );
CodeBody def_namespace_body( s32 num, ... );
CodeBody def_namespace_body( s32 num, Code* codes );
CodeParam def_params( s32 num, ... );
CodeParam def_params( s32 num, CodeParam* params );
CodeSpecifiers def_specifiers( s32 num, ... );
CodeSpecifiers def_specifiers( s32 num, SpecifierT* specs );
CodeBody def_struct_body( s32 num, ... );
CodeBody def_struct_body( s32 num, Code* codes );
CodeBody def_union_body( s32 num, ... );
CodeBody def_union_body( s32 num, Code* codes );
#pragma endregion Upfront
#pragma region Parsing
// TODO(Ed) : Implmeent the new parser API design.
#if 0
namespace parser {
struct StackNode
{
StackNode* Prev;
Token Start;
Token Name; // The name of the AST node (if parsed)
StrC FailedProc; // The name of the procedure that failed
};
// Stack nodes are allocated the error's allocator
struct Error
{
String message;
StackNode* context_stack;
};
}
struct ParseInfo
Arena FileMem;
Arena TokMem;
Arena CodeMem;
FileContents FileContent;
Array<parser::Token> Tokens;
Array<parser::Error> Errors;
// Errors are allocated to a dedicated general arena.
;
CodeBody parse_file( StrC path );
#endif
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 );
CodeFriend parse_friend( StrC friend_def );
CodeFn parse_function( StrC fn_def );
CodeBody parse_global_body( StrC body_def );
CodeNS parse_namespace( StrC namespace_def );
CodeOperator parse_operator( StrC operator_def );
CodeOpCast parse_operator_cast( StrC operator_def );
CodeStruct parse_struct( StrC struct_def );
CodeTemplate parse_template( StrC template_def );
CodeType parse_type( StrC type_def );
CodeTypedef parse_typedef( StrC typedef_def );
CodeUnion parse_union( StrC union_def );
CodeUsing parse_using( StrC using_def );
CodeVar parse_variable( StrC var_def );
#pragma endregion Parsing
#pragma region Untyped text
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va );
//! Do not use directly. Use the token_fmt macro instead.
StrC token_fmt_impl( sw, ... );
Code untyped_str( StrC content );
Code untyped_fmt( char const* fmt, ... );
Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... );
#pragma endregion Untyped text
#pragma endregion Gen Interface
#pragma region Inlines
void AST::append( AST* other )
{
if ( other->Parent )
other = other->duplicate();
other->Parent = this;
if ( Front == nullptr )
{
Front = other;
Back = other;
NumEntries++;
return;
}
AST* Current = Back;
Current->Next = other;
other->Prev = Current;
Back = other;
NumEntries++;
}
Code& AST::entry( u32 idx )
{
AST** current = &Front;
while ( idx >= 0 && current != nullptr )
{
if ( idx == 0 )
return *rcast( Code*, current );
current = &( *current )->Next;
idx--;
}
return *rcast( Code*, current );
}
bool AST::has_entries()
{
return NumEntries;
}
char const* AST::type_str()
{
return ECode::to_str( Type );
}
AST::operator Code()
{
return { this };
}
Code& Code::operator++()
{
if ( ast )
ast = ast->Next;
return *this;
}
void CodeClass::add_interface( CodeType type )
{
CodeType possible_slot = ast->ParentType;
if ( possible_slot.ast )
{
// Were adding an interface to parent type, so we need to make sure the parent type is public.
ast->ParentAccess = AccessSpec::Public;
// If your planning on adding a proper parent,
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
}
while ( possible_slot.ast != nullptr )
{
possible_slot.ast = ( AST_Type* )possible_slot->Next.ast;
}
possible_slot.ast = type.ast;
}
void CodeParam::append( CodeParam other )
{
AST* self = ( AST* )ast;
AST* entry = ( AST* )other.ast;
if ( entry->Parent )
entry = entry->duplicate();
entry->Parent = self;
if ( self->Last == nullptr )
{
self->Last = entry;
self->Next = entry;
self->NumEntries++;
return;
}
self->Last->Next = entry;
self->Last = entry;
self->NumEntries++;
}
CodeParam CodeParam::get( s32 idx )
{
CodeParam param = *this;
do
{
if ( ! ++param )
return { nullptr };
return { ( AST_Param* )param.raw()->Next };
} while ( --idx );
return { nullptr };
}
bool CodeParam::has_entries()
{
return ast->NumEntries > 0;
}
CodeParam& CodeParam::operator++()
{
ast = ast->Next.ast;
return *this;
}
void CodeStruct::add_interface( CodeType type )
{
CodeType possible_slot = ast->ParentType;
if ( possible_slot.ast )
{
// Were adding an interface to parent type, so we need to make sure the parent type is public.
ast->ParentAccess = AccessSpec::Public;
// If your planning on adding a proper parent,
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
}
while ( possible_slot.ast != nullptr )
{
possible_slot.ast = ( AST_Type* )possible_slot->Next.ast;
}
possible_slot.ast = type.ast;
}
CodeBody def_body( CodeT type )
{
switch ( type )
{
using namespace ECode;
case Class_Body :
case Enum_Body :
case Export_Body :
case Extern_Linkage :
case Function_Body :
case Global_Body :
case Namespace_Body :
case Struct_Body :
case Union_Body :
break;
default :
log_failure( "def_body: Invalid type %s", ( char const* )ECode::to_str( type ) );
return ( CodeBody )Code::Invalid;
}
Code result = make_code();
result->Type = type;
return ( CodeBody )result;
}
StrC token_fmt_impl( sw num, ... )
{
local_persist thread_local char buf[ GEN_PRINTF_MAXLEN ] = { 0 };
mem_set( buf, 0, GEN_PRINTF_MAXLEN );
va_list va;
va_start( va, num );
sw result = token_fmt_va( buf, GEN_PRINTF_MAXLEN, num, va );
va_end( va );
return { result, buf };
}
#pragma region generated code inline implementation
char const* Code::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code Code::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool Code::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool Code::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void Code::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
Code& Code::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool Code::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool Code::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
Code::operator bool()
{
return ast != nullptr;
}
char const* CodeBody::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeBody::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeBody::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeBody::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeBody::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeBody& CodeBody::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeBody::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeBody::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeBody::operator bool()
{
return ast != nullptr;
}
char const* CodeAttributes::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeAttributes::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeAttributes::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeAttributes::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeAttributes::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeAttributes& CodeAttributes::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeAttributes::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeAttributes::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeAttributes::operator bool()
{
return ast != nullptr;
}
AST* CodeAttributes::raw()
{
return rcast( AST*, ast );
}
CodeAttributes::operator Code()
{
return *rcast( Code*, this );
}
AST_Attributes* CodeAttributes::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeComment::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeComment::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeComment::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeComment::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeComment::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeComment& CodeComment::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeComment::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeComment::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeComment::operator bool()
{
return ast != nullptr;
}
AST* CodeComment::raw()
{
return rcast( AST*, ast );
}
CodeComment::operator Code()
{
return *rcast( Code*, this );
}
AST_Comment* CodeComment::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeConstructor::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeConstructor::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeConstructor::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeConstructor::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeConstructor::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeConstructor& CodeConstructor::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeConstructor::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeConstructor::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeConstructor::operator bool()
{
return ast != nullptr;
}
AST* CodeConstructor::raw()
{
return rcast( AST*, ast );
}
CodeConstructor::operator Code()
{
return *rcast( Code*, this );
}
AST_Constructor* CodeConstructor::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeClass::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeClass::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeClass::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeClass::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeClass::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeClass& CodeClass::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeClass::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeClass::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeClass::operator bool()
{
return ast != nullptr;
}
char const* CodeDefine::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeDefine::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeDefine::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeDefine::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeDefine::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeDefine& CodeDefine::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeDefine::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeDefine::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeDefine::operator bool()
{
return ast != nullptr;
}
AST* CodeDefine::raw()
{
return rcast( AST*, ast );
}
CodeDefine::operator Code()
{
return *rcast( Code*, this );
}
AST_Define* CodeDefine::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeDestructor::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeDestructor::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeDestructor::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeDestructor::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeDestructor::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeDestructor& CodeDestructor::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeDestructor::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeDestructor::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeDestructor::operator bool()
{
return ast != nullptr;
}
AST* CodeDestructor::raw()
{
return rcast( AST*, ast );
}
CodeDestructor::operator Code()
{
return *rcast( Code*, this );
}
AST_Destructor* CodeDestructor::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeEnum::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeEnum::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeEnum::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeEnum::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeEnum::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeEnum& CodeEnum::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeEnum::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeEnum::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeEnum::operator bool()
{
return ast != nullptr;
}
AST* CodeEnum::raw()
{
return rcast( AST*, ast );
}
CodeEnum::operator Code()
{
return *rcast( Code*, this );
}
AST_Enum* CodeEnum::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeExec::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeExec::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeExec::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeExec::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeExec::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeExec& CodeExec::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeExec::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeExec::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeExec::operator bool()
{
return ast != nullptr;
}
AST* CodeExec::raw()
{
return rcast( AST*, ast );
}
CodeExec::operator Code()
{
return *rcast( Code*, this );
}
AST_Exec* CodeExec::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeExtern::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeExtern::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeExtern::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeExtern::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeExtern::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeExtern& CodeExtern::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeExtern::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeExtern::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeExtern::operator bool()
{
return ast != nullptr;
}
AST* CodeExtern::raw()
{
return rcast( AST*, ast );
}
CodeExtern::operator Code()
{
return *rcast( Code*, this );
}
AST_Extern* CodeExtern::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeFriend::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeFriend::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeFriend::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeFriend::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeFriend::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeFriend& CodeFriend::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeFriend::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeFriend::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeFriend::operator bool()
{
return ast != nullptr;
}
AST* CodeFriend::raw()
{
return rcast( AST*, ast );
}
CodeFriend::operator Code()
{
return *rcast( Code*, this );
}
AST_Friend* CodeFriend::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeFn::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeFn::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeFn::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeFn::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeFn::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeFn& CodeFn::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeFn::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeFn::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeFn::operator bool()
{
return ast != nullptr;
}
AST* CodeFn::raw()
{
return rcast( AST*, ast );
}
CodeFn::operator Code()
{
return *rcast( Code*, this );
}
AST_Fn* CodeFn::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeInclude::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeInclude::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeInclude::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeInclude::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeInclude::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeInclude& CodeInclude::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeInclude::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeInclude::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeInclude::operator bool()
{
return ast != nullptr;
}
AST* CodeInclude::raw()
{
return rcast( AST*, ast );
}
CodeInclude::operator Code()
{
return *rcast( Code*, this );
}
AST_Include* CodeInclude::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeModule::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeModule::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeModule::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeModule::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeModule::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeModule& CodeModule::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeModule::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeModule::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeModule::operator bool()
{
return ast != nullptr;
}
AST* CodeModule::raw()
{
return rcast( AST*, ast );
}
CodeModule::operator Code()
{
return *rcast( Code*, this );
}
AST_Module* CodeModule::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeNS::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeNS::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeNS::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeNS::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeNS::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeNS& CodeNS::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeNS::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeNS::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeNS::operator bool()
{
return ast != nullptr;
}
AST* CodeNS::raw()
{
return rcast( AST*, ast );
}
CodeNS::operator Code()
{
return *rcast( Code*, this );
}
AST_NS* CodeNS::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeOperator::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeOperator::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeOperator::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeOperator::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeOperator::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeOperator& CodeOperator::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeOperator::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeOperator::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeOperator::operator bool()
{
return ast != nullptr;
}
AST* CodeOperator::raw()
{
return rcast( AST*, ast );
}
CodeOperator::operator Code()
{
return *rcast( Code*, this );
}
AST_Operator* CodeOperator::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeOpCast::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeOpCast::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeOpCast::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeOpCast::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeOpCast::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeOpCast& CodeOpCast::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeOpCast::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeOpCast::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeOpCast::operator bool()
{
return ast != nullptr;
}
AST* CodeOpCast::raw()
{
return rcast( AST*, ast );
}
CodeOpCast::operator Code()
{
return *rcast( Code*, this );
}
AST_OpCast* CodeOpCast::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeParam::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeParam::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeParam::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeParam::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeParam::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeParam& CodeParam::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeParam::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeParam::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeParam::operator bool()
{
return ast != nullptr;
}
char const* CodePragma::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodePragma::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodePragma::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodePragma::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodePragma::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodePragma& CodePragma::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodePragma::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodePragma::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodePragma::operator bool()
{
return ast != nullptr;
}
AST* CodePragma::raw()
{
return rcast( AST*, ast );
}
CodePragma::operator Code()
{
return *rcast( Code*, this );
}
AST_Pragma* CodePragma::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodePreprocessCond::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodePreprocessCond::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodePreprocessCond::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodePreprocessCond::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodePreprocessCond::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodePreprocessCond& CodePreprocessCond::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodePreprocessCond::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodePreprocessCond::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodePreprocessCond::operator bool()
{
return ast != nullptr;
}
AST* CodePreprocessCond::raw()
{
return rcast( AST*, ast );
}
CodePreprocessCond::operator Code()
{
return *rcast( Code*, this );
}
AST_PreprocessCond* CodePreprocessCond::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeSpecifiers::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeSpecifiers::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeSpecifiers::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeSpecifiers::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeSpecifiers::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeSpecifiers& CodeSpecifiers::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeSpecifiers::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeSpecifiers::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeSpecifiers::operator bool()
{
return ast != nullptr;
}
char const* CodeStruct::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeStruct::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeStruct::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeStruct::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeStruct::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeStruct& CodeStruct::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeStruct::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeStruct::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeStruct::operator bool()
{
return ast != nullptr;
}
char const* CodeTemplate::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeTemplate::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeTemplate::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeTemplate::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeTemplate::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeTemplate& CodeTemplate::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeTemplate::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeTemplate::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeTemplate::operator bool()
{
return ast != nullptr;
}
AST* CodeTemplate::raw()
{
return rcast( AST*, ast );
}
CodeTemplate::operator Code()
{
return *rcast( Code*, this );
}
AST_Template* CodeTemplate::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeType::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeType::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeType::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeType::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeType::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeType& CodeType::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeType::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeType::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeType::operator bool()
{
return ast != nullptr;
}
AST* CodeType::raw()
{
return rcast( AST*, ast );
}
CodeType::operator Code()
{
return *rcast( Code*, this );
}
AST_Type* CodeType::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeTypedef::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeTypedef::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeTypedef::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeTypedef::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeTypedef::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeTypedef& CodeTypedef::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeTypedef::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeTypedef::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeTypedef::operator bool()
{
return ast != nullptr;
}
AST* CodeTypedef::raw()
{
return rcast( AST*, ast );
}
CodeTypedef::operator Code()
{
return *rcast( Code*, this );
}
AST_Typedef* CodeTypedef::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeUnion::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeUnion::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeUnion::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeUnion::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeUnion::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeUnion& CodeUnion::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeUnion::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeUnion::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeUnion::operator bool()
{
return ast != nullptr;
}
AST* CodeUnion::raw()
{
return rcast( AST*, ast );
}
CodeUnion::operator Code()
{
return *rcast( Code*, this );
}
AST_Union* CodeUnion::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeUsing::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeUsing::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeUsing::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeUsing::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeUsing::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeUsing& CodeUsing::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeUsing::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeUsing::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeUsing::operator bool()
{
return ast != nullptr;
}
AST* CodeUsing::raw()
{
return rcast( AST*, ast );
}
CodeUsing::operator Code()
{
return *rcast( Code*, this );
}
AST_Using* CodeUsing::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
char const* CodeVar::debug_str()
{
if ( ast == nullptr )
return "Code::debug_str: AST is null!";
return rcast( AST*, ast )->debug_str();
}
Code CodeVar::duplicate()
{
if ( ast == nullptr )
{
log_failure( "Code::duplicate: Cannot duplicate code, AST is null!" );
return Code::Invalid;
}
return { rcast( AST*, ast )->duplicate() };
}
bool CodeVar::is_equal( Code other )
{
if ( ast == nullptr || other.ast == nullptr )
{
log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
return false;
}
return rcast( AST*, ast )->is_equal( other.ast );
}
bool CodeVar::is_valid()
{
return ( AST* )ast != nullptr && rcast( AST*, ast )->Type != CodeT::Invalid;
}
void CodeVar::set_global()
{
if ( ast == nullptr )
{
log_failure( "Code::set_global: Cannot set code as global, AST is null!" );
return;
}
rcast( AST*, ast )->Parent = Code::Global.ast;
}
CodeVar& CodeVar::operator=( Code other )
{
if ( other.ast && other->Parent )
{
ast = rcast( decltype( ast ), other.ast->duplicate() );
rcast( AST*, ast )->Parent = nullptr;
}
ast = rcast( decltype( ast ), other.ast );
return *this;
}
bool CodeVar::operator==( Code other )
{
return ( AST* )ast == other.ast;
}
bool CodeVar::operator!=( Code other )
{
return ( AST* )ast != other.ast;
}
CodeVar::operator bool()
{
return ast != nullptr;
}
AST* CodeVar::raw()
{
return rcast( AST*, ast );
}
CodeVar::operator Code()
{
return *rcast( Code*, this );
}
AST_Var* CodeVar::operator->()
{
if ( ast == nullptr )
{
log_failure( "Attempt to dereference a nullptr!" );
return nullptr;
}
return ast;
}
#pragma endregion generated code inline implementation
#pragma region generated AST/Code cast implementation
AST::operator CodeBody()
{
return { rcast( AST_Body*, this ) };
}
Code::operator CodeBody() const
{
return { ( AST_Body* )ast };
}
AST::operator CodeAttributes()
{
return { rcast( AST_Attributes*, this ) };
}
Code::operator CodeAttributes() const
{
return { ( AST_Attributes* )ast };
}
AST::operator CodeComment()
{
return { rcast( AST_Comment*, this ) };
}
Code::operator CodeComment() const
{
return { ( AST_Comment* )ast };
}
AST::operator CodeConstructor()
{
return { rcast( AST_Constructor*, this ) };
}
Code::operator CodeConstructor() const
{
return { ( AST_Constructor* )ast };
}
AST::operator CodeClass()
{
return { rcast( AST_Class*, this ) };
}
Code::operator CodeClass() const
{
return { ( AST_Class* )ast };
}
AST::operator CodeDefine()
{
return { rcast( AST_Define*, this ) };
}
Code::operator CodeDefine() const
{
return { ( AST_Define* )ast };
}
AST::operator CodeDestructor()
{
return { rcast( AST_Destructor*, this ) };
}
Code::operator CodeDestructor() const
{
return { ( AST_Destructor* )ast };
}
AST::operator CodeEnum()
{
return { rcast( AST_Enum*, this ) };
}
Code::operator CodeEnum() const
{
return { ( AST_Enum* )ast };
}
AST::operator CodeExec()
{
return { rcast( AST_Exec*, this ) };
}
Code::operator CodeExec() const
{
return { ( AST_Exec* )ast };
}
AST::operator CodeExtern()
{
return { rcast( AST_Extern*, this ) };
}
Code::operator CodeExtern() const
{
return { ( AST_Extern* )ast };
}
AST::operator CodeFriend()
{
return { rcast( AST_Friend*, this ) };
}
Code::operator CodeFriend() const
{
return { ( AST_Friend* )ast };
}
AST::operator CodeFn()
{
return { rcast( AST_Fn*, this ) };
}
Code::operator CodeFn() const
{
return { ( AST_Fn* )ast };
}
AST::operator CodeInclude()
{
return { rcast( AST_Include*, this ) };
}
Code::operator CodeInclude() const
{
return { ( AST_Include* )ast };
}
AST::operator CodeModule()
{
return { rcast( AST_Module*, this ) };
}
Code::operator CodeModule() const
{
return { ( AST_Module* )ast };
}
AST::operator CodeNS()
{
return { rcast( AST_NS*, this ) };
}
Code::operator CodeNS() const
{
return { ( AST_NS* )ast };
}
AST::operator CodeOperator()
{
return { rcast( AST_Operator*, this ) };
}
Code::operator CodeOperator() const
{
return { ( AST_Operator* )ast };
}
AST::operator CodeOpCast()
{
return { rcast( AST_OpCast*, this ) };
}
Code::operator CodeOpCast() const
{
return { ( AST_OpCast* )ast };
}
AST::operator CodeParam()
{
return { rcast( AST_Param*, this ) };
}
Code::operator CodeParam() const
{
return { ( AST_Param* )ast };
}
AST::operator CodePragma()
{
return { rcast( AST_Pragma*, this ) };
}
Code::operator CodePragma() const
{
return { ( AST_Pragma* )ast };
}
AST::operator CodePreprocessCond()
{
return { rcast( AST_PreprocessCond*, this ) };
}
Code::operator CodePreprocessCond() const
{
return { ( AST_PreprocessCond* )ast };
}
AST::operator CodeSpecifiers()
{
return { rcast( AST_Specifiers*, this ) };
}
Code::operator CodeSpecifiers() const
{
return { ( AST_Specifiers* )ast };
}
AST::operator CodeStruct()
{
return { rcast( AST_Struct*, this ) };
}
Code::operator CodeStruct() const
{
return { ( AST_Struct* )ast };
}
AST::operator CodeTemplate()
{
return { rcast( AST_Template*, this ) };
}
Code::operator CodeTemplate() const
{
return { ( AST_Template* )ast };
}
AST::operator CodeType()
{
return { rcast( AST_Type*, this ) };
}
Code::operator CodeType() const
{
return { ( AST_Type* )ast };
}
AST::operator CodeTypedef()
{
return { rcast( AST_Typedef*, this ) };
}
Code::operator CodeTypedef() const
{
return { ( AST_Typedef* )ast };
}
AST::operator CodeUnion()
{
return { rcast( AST_Union*, this ) };
}
Code::operator CodeUnion() const
{
return { ( AST_Union* )ast };
}
AST::operator CodeUsing()
{
return { rcast( AST_Using*, this ) };
}
Code::operator CodeUsing() const
{
return { ( AST_Using* )ast };
}
AST::operator CodeVar()
{
return { rcast( AST_Var*, this ) };
}
Code::operator CodeVar() const
{
return { ( AST_Var* )ast };
}
#pragma endregion generated AST / Code cast implementation
#pragma endregion Inlines
#pragma region Constants
#ifndef GEN_GLOBAL_BUCKET_SIZE
#define GEN_GLOBAL_BUCKET_SIZE megabytes( 8 )
#endif
#ifndef GEN_CODEPOOL_NUM_BLOCKS
#define GEN_CODEPOOL_NUM_BLOCKS kilobytes( 16 )
#endif
#ifndef GEN_SIZE_PER_STRING_ARENA
#define GEN_SIZE_PER_STRING_ARENA megabytes( 1 )
#endif
#ifndef GEN_MAX_COMMENT_LINE_LENGTH
#define GEN_MAX_COMMENT_LINE_LENGTH 1024
#endif
#ifndef GEN_MAX_NAME_LENGTH
#define GEN_MAX_NAME_LENGTH 128
#endif
#ifndef GEN_MAX_UNTYPED_STR_LENGTH
#define GEN_MAX_UNTYPED_STR_LENGTH megabytes( 1 )
#endif
#ifndef GEN_TOKEN_FMT_TOKEN_MAP_MEM_SIZE
#define GEN_TOKEN_FMT_TOKEN_MAP_MEM_SIZE kilobytes( 4 )
#endif
#ifndef GEN_LEX_ALLOCATOR_SIZE
#define GEN_LEX_ALLOCATOR_SIZE megabytes( 4 )
#endif
#ifndef GEN_BUILDER_STR_BUFFER_RESERVE
#define GEN_BUILDER_STR_BUFFER_RESERVE megabytes( 2 )
#endif
// These constexprs are used for allocation behavior of data structures
// or string handling while constructing or serializing.
// Change them to suit your needs.
constexpr s32 InitSize_DataArrays = 16;
// NOTE: This limits the maximum size of an allocation
// If you are generating a string larger than this, increase the size of the bucket here.
constexpr uw Global_BucketSize = GEN_GLOBAL_BUCKET_SIZE;
constexpr s32 CodePool_NumBlocks = GEN_CODEPOOL_NUM_BLOCKS;
constexpr s32 SizePer_StringArena = GEN_SIZE_PER_STRING_ARENA;
constexpr s32 MaxCommentLineLength = GEN_MAX_COMMENT_LINE_LENGTH;
constexpr s32 MaxNameLength = GEN_MAX_NAME_LENGTH;
constexpr s32 MaxUntypedStrLength = GEN_MAX_UNTYPED_STR_LENGTH;
constexpr s32 TokenFmt_TokenMap_MemSize = GEN_TOKEN_FMT_TOKEN_MAP_MEM_SIZE;
constexpr s32 LexAllocator_Size = GEN_LEX_ALLOCATOR_SIZE;
constexpr s32 Builder_StrBufferReserve = GEN_BUILDER_STR_BUFFER_RESERVE;
extern Code access_public;
extern Code access_protected;
extern Code access_private;
extern CodeAttributes attrib_api_export;
extern CodeAttributes attrib_api_import;
extern Code module_global_fragment;
extern Code module_private_fragment;
// Exposed, but this is really used for parsing.
extern Code fmt_newline;
extern CodePragma pragma_once;
extern CodeParam param_varadic;
extern CodePreprocessCond preprocess_else;
extern CodePreprocessCond preprocess_endif;
extern CodeSpecifiers spec_const;
extern CodeSpecifiers spec_consteval;
extern CodeSpecifiers spec_constexpr;
extern CodeSpecifiers spec_constinit;
extern CodeSpecifiers spec_extern_linkage;
extern CodeSpecifiers spec_final;
extern CodeSpecifiers spec_forceinline;
extern CodeSpecifiers spec_global;
extern CodeSpecifiers spec_inline;
extern CodeSpecifiers spec_internal_linkage;
extern CodeSpecifiers spec_local_persist;
extern CodeSpecifiers spec_mutable;
extern CodeSpecifiers spec_neverinline;
extern CodeSpecifiers spec_noexcept;
extern CodeSpecifiers spec_override;
extern CodeSpecifiers spec_ptr;
extern CodeSpecifiers spec_pure;
extern CodeSpecifiers spec_ref;
extern CodeSpecifiers spec_register;
extern CodeSpecifiers spec_rvalue;
extern CodeSpecifiers spec_static_member;
extern CodeSpecifiers spec_thread_local;
extern CodeSpecifiers spec_virtual;
extern CodeSpecifiers spec_volatile;
extern CodeType t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance)
extern CodeType t_auto;
extern CodeType t_void;
extern CodeType t_int;
extern CodeType t_bool;
extern CodeType t_char;
extern CodeType t_wchar_t;
extern CodeType t_class;
extern CodeType t_typename;
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
// Predefined typename codes. Are set to readonly and are setup during gen::init()
extern CodeType t_b32;
extern CodeType t_s8;
extern CodeType t_s16;
extern CodeType t_s32;
extern CodeType t_s64;
extern CodeType t_u8;
extern CodeType t_u16;
extern CodeType t_u32;
extern CodeType t_u64;
extern CodeType t_sw;
extern CodeType t_uw;
extern CodeType t_f32;
extern CodeType t_f64;
#endif
#pragma endregion Constants
#pragma region Macros
#define gen_main main
#define __ NoCode
// Convienence for defining any name used with the gen api.
// Lets you provide the length and string literal to the functions without the need for the DSL.
#define name( Id_ ) \
{ \
sizeof( stringize( Id_ ) ) - 1, stringize( Id_ ) \
}
// Same as name just used to indicate intention of literal for code instead of names.
#define code( ... ) \
{ \
sizeof( stringize( __VA_ARGS__ ) ) - 1, stringize( __VA_ARGS__ ) \
}
#define args( ... ) num_args( __VA_ARGS__ ), __VA_ARGS__
#define code_str( ... ) GEN_NS untyped_str( code( __VA_ARGS__ ) )
#define code_fmt( ... ) GEN_NS untyped_str( token_fmt( __VA_ARGS__ ) )
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
#define token_fmt( ... ) GEN_NS token_fmt_impl( ( num_args( __VA_ARGS__ ) + 1 ) / 2, __VA_ARGS__ )
#pragma endregion Macros
// Used by the lexer to persistently treat all these identifiers as preprocessor defines.
// Populate with strings via gen::get_cached_string.
// Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments.
extern Array< StringCached > PreprocessorDefines;
#ifdef GEN_EXPOSE_BACKEND
// Global allocator used for data with process lifetime.
extern AllocatorInfo GlobalAllocator;
extern Array< Arena > Global_AllocatorBuckets;
extern Array< Pool > CodePools;
extern Array< Arena > StringArenas;
extern StringTable StringCache;
extern Arena LexArena;
extern AllocatorInfo Allocator_DataArrays;
extern AllocatorInfo Allocator_CodePool;
extern AllocatorInfo Allocator_Lexer;
extern AllocatorInfo Allocator_StringArena;
extern AllocatorInfo Allocator_StringTable;
extern AllocatorInfo Allocator_TypeTable;
#endif
GEN_NS_END
#if __clang__
#pragma clang diagnostic pop
#endif
#if __GNUC__
#pragma GCC diagnostic pop
#endif