6517 lines
137 KiB
C++
6517 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,
|
|
Private,
|
|
Protected,
|
|
Public,
|
|
|
|
Num_AccessSpec,
|
|
Invalid,
|
|
};
|
|
|
|
inline char const* to_str( AccessSpec type )
|
|
{
|
|
local_persist char const* lookup[(u32)AccessSpec::Num_AccessSpec] = {
|
|
"",
|
|
"private",
|
|
"protected",
|
|
"public",
|
|
};
|
|
|
|
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,
|
|
New,
|
|
NewArray,
|
|
Delete,
|
|
DeleteArray,
|
|
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( "," ), "," },
|
|
{ sizeof( "new" ), "new" },
|
|
{ sizeof( "new[]" ), "new[]" },
|
|
{ sizeof( "delete" ), "delete" },
|
|
{ sizeof( "delete[]" ), "delete[]" },
|
|
};
|
|
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* Macro; // Parameter
|
|
AST* BitfieldSize; // Variable (Class/Struct Data Member)
|
|
AST* Params; // Constructor, Function, Operator, Template, Typename
|
|
};
|
|
|
|
union
|
|
{
|
|
AST* ArrExpr; // Typename
|
|
AST* Body; // Class, Constructr, Destructor, Enum, Friend, 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* Macro; // Parameter
|
|
AST* BitfieldSize; // Variable (Class/Struct Data Member)
|
|
AST* Params; // Constructor, Function, Operator, Template, Typename
|
|
};
|
|
|
|
union
|
|
{
|
|
AST* ArrExpr; // Typename
|
|
AST* Body; // Class, Constructr, Destructor, Enum, Friend, 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[idx] == 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;
|
|
StringCached Name;
|
|
CodeT Type;
|
|
char _PAD_UNUSED_[sizeof( ModuleFlag ) + sizeof( u32 )];
|
|
};
|
|
|
|
static_assert( sizeof( AST_Constructor ) == sizeof( AST ), "ERROR: AST_Constructor is not the same size as AST" );
|
|
|
|
struct AST_Define
|
|
{
|
|
union
|
|
{
|
|
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;
|
|
StringCached Name;
|
|
CodeT Type;
|
|
char _PAD_UNUSED_[sizeof( ModuleFlag ) + sizeof( u32 )];
|
|
};
|
|
|
|
static_assert( sizeof( AST_Destructor ) == sizeof( AST ), "ERROR: AST_Destructor is not the same size as AST" );
|
|
|
|
struct AST_Enum
|
|
{
|
|
union
|
|
{
|
|
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;
|
|
Code Macro;
|
|
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;
|
|
|
|
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
|