diff --git a/Project/Gasa.sln.DotSettings.user b/Project/Gasa.sln.DotSettings.user index 293c066..5d36be6 100644 --- a/Project/Gasa.sln.DotSettings.user +++ b/Project/Gasa.sln.DotSettings.user @@ -1,3 +1,7 @@  Override + C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe + C:\projects\Unreal\Surgo\UE\Engine\Binaries\ThirdParty\DotNet\8.0.300\win-x64\dotnet.exe + 1114112 + True True \ No newline at end of file diff --git a/Project/Source/GasaEditor/GasaEditor.Build.cs b/Project/Source/GasaEditor/GasaEditor.Build.cs index 3961d50..31a6a4a 100644 --- a/Project/Source/GasaEditor/GasaEditor.Build.cs +++ b/Project/Source/GasaEditor/GasaEditor.Build.cs @@ -28,8 +28,8 @@ public class GasaEditor : ModuleRules PrivateDependencyModuleNames.Add("Gasa"); bWarningsAsErrors = false; - ShadowVariableWarningLevel = UnrealBuildTool.WarningLevel.Warning; - UndefinedIdentifierWarningLevel = UnrealBuildTool.WarningLevel.Warning; + ShadowVariableWarningLevel = UnrealBuildTool.WarningLevel.Off; + UndefinedIdentifierWarningLevel = UnrealBuildTool.WarningLevel.Off; // gencpp related defines PublicDefinitions.Add("Build_Debug=1"); diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.cpp b/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.cpp index 16257a7..8e1d35e 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.cpp +++ b/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.cpp @@ -1,22 +1,22 @@ // This file was generated automatially by gencpp's unreal.cpp (See: https://github.com/Ed94/gencpp) #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-const-variable" -#pragma clang diagnostic ignored "-Wunused-but-set-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" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-const-variable" +# pragma clang diagnostic ignored "-Wunused-but-set-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 #ifdef __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" +# 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 #include "gen.builder.hpp" @@ -27,10 +27,10 @@ Builder Builder::open( char const* path ) { Builder result; - FileError error = file_open_mode( &result.File, EFileMode_WRITE, path ); + FileError error = file_open_mode( & result.File, EFileMode_WRITE, path ); if ( error != EFileError_NONE ) { - log_failure( "gen::File::open - Could not open file: %s", path ); + log_failure( "gen::File::open - Could not open file: %s", path); return result; } @@ -47,16 +47,16 @@ void Builder::pad_lines( s32 num ) void Builder::print( Code code ) { - String str = code->to_string(); - // const sw len = str.length(); + String str = code->to_string(); + // const ssize len = str.length(); // log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data ); Buffer.append( str ); } void Builder::print_fmt( char const* fmt, ... ) { - sw res; - char buf[GEN_PRINTF_MAXLEN] = { 0 }; + ssize res; + char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; va_list va; va_start( va, fmt ); @@ -69,22 +69,22 @@ void Builder::print_fmt( char const* fmt, ... ) void Builder::write() { - b32 result = file_write( &File, Buffer, Buffer.length() ); + b32 result = file_write( & File, Buffer, Buffer.length() ); if ( result == false ) - log_failure( "gen::File::write - Failed to write to file: %s\n", file_name( &File ) ); + log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); log_fmt( "Generated: %s\n", File.filename ); - file_close( &File ); + file_close( & File ); Buffer.free(); } GEN_NS_END #ifdef __clang__ -#pragma clang diagnostic pop +# pragma clang diagnostic pop #endif #ifdef __GNUC__ -#pragma GCC diagnostic pop +# pragma GCC diagnostic pop #endif diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.hpp b/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.hpp index ef56f6d..66f5f01 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.hpp +++ b/Project/Source/GasaEditor/GasaGen/gencpp/gen.builder.hpp @@ -1,22 +1,22 @@ // This file was generated automatially by gencpp's unreal.cpp (See: https://github.com/Ed94/gencpp) #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-const-variable" -#pragma clang diagnostic ignored "-Wunused-but-set-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" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-const-variable" +# pragma clang diagnostic ignored "-Wunused-but-set-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 #ifdef __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" +# 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 @@ -43,9 +43,9 @@ struct Builder GEN_NS_END #ifdef __clang__ -#pragma clang diagnostic pop +# pragma clang diagnostic pop #endif #ifdef __GNUC__ -#pragma GCC diagnostic pop +# pragma GCC diagnostic pop #endif diff --git a/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp b/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp index 5eed464..666f214 100644 --- a/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp +++ b/Project/Source/GasaEditor/GasaGen/gencpp/gen.cpp @@ -1,26 +1,26 @@ // This file was generated automatially by gencpp's unreal.cpp (See: https://github.com/Ed94/gencpp) #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-const-variable" -#pragma clang diagnostic ignored "-Wunused-but-set-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" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-const-variable" +# pragma clang diagnostic ignored "-Wunused-but-set-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 #ifdef __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" +# 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 -#if ! defined( GEN_DONT_ENFORCE_GEN_TIME_GUARD ) && ! defined( GEN_TIME ) -#error Gen.hpp : GEN_TIME not defined +#if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) +# error Gen.hpp : GEN_TIME not defined #endif #include "gen.hpp" @@ -30,12 +30,12 @@ GEN_NS_BEGIN #pragma region StaticData // TODO : Convert global allocation strategy to use a slab allocation strategy. -global AllocatorInfo GlobalAllocator; -global Array Global_AllocatorBuckets; +global AllocatorInfo GlobalAllocator; +global Array Global_AllocatorBuckets; // TODO(Ed) : Make the code pool a dynamic arena -global Array CodePools = { nullptr }; -global Array StringArenas = { nullptr }; +global Array< Pool > CodePools = { nullptr }; +global Array< Arena > StringArenas = { nullptr }; global StringTable StringCache; @@ -106,7 +106,7 @@ global CodeType t_wchar_t; global CodeType t_class; global CodeType t_typename; -global Array PreprocessorDefines; +global Array< StringCached > PreprocessorDefines; #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS global CodeType t_b32; @@ -121,8 +121,8 @@ global CodeType t_u16; global CodeType t_u32; global CodeType t_u64; -global CodeType t_sw; -global CodeType t_uw; +global CodeType t_ssize; +global CodeType t_usize; global CodeType t_f32; global CodeType t_f64; @@ -132,84 +132,84 @@ global CodeType t_f64; #pragma region AST -#define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \ - case PlatformAttributes : \ - case Class_Body : \ - case Enum_Body : \ - case Extern_Linkage : \ - case Function_Body : \ - case Function_Fwd : \ - case Global_Body : \ - case Namespace : \ - case Namespace_Body : \ - case Operator : \ - case Operator_Fwd : \ - case Parameters : \ - case Specifiers : \ - case Struct_Body : \ - case Typename : -#define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES +# define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \ + case PlatformAttributes: \ + case Class_Body: \ + case Enum_Body: \ + case Extern_Linkage: \ + case Function_Body: \ + case Function_Fwd: \ + case Global_Body: \ + case Namespace: \ + case Namespace_Body: \ + case Operator: \ + case Operator_Fwd: \ + case Parameters: \ + case Specifiers: \ + case Struct_Body: \ + case Typename: +# define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES -#define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \ - case Access_Public : \ - case Access_Protected : \ - case Access_Private : \ - case PlatformAttributes : \ - case Class_Body : \ - case Enum_Body : \ - case Extern_Linkage : \ - case Friend : \ - case Function_Body : \ - case Function_Fwd : \ - case Global_Body : \ - case Namespace : \ - case Namespace_Body : \ - case Operator : \ - case Operator_Fwd : \ - case Operator_Member : \ - case Operator_Member_Fwd : \ - case Parameters : \ - case Specifiers : \ - case Struct_Body : \ - case Typename : +# define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \ + case Access_Public: \ + case Access_Protected: \ + case Access_Private: \ + case PlatformAttributes: \ + case Class_Body: \ + case Enum_Body: \ + case Extern_Linkage: \ + case Friend: \ + case Function_Body: \ + case Function_Fwd: \ + case Global_Body: \ + case Namespace: \ + case Namespace_Body: \ + case Operator: \ + case Operator_Fwd: \ + case Operator_Member: \ + case Operator_Member_Fwd: \ + case Parameters: \ + case Specifiers: \ + case Struct_Body: \ + case Typename: -#define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES \ - case Access_Public : \ - case Access_Protected : \ - case Access_Private : \ - case PlatformAttributes : \ - case Class_Body : \ - case Enum_Body : \ - case Execution : \ - case Friend : \ - case Function_Body : \ - case Namespace_Body : \ - case Operator_Member : \ - case Operator_Member_Fwd : \ - case Parameters : \ - case Specifiers : \ - case Struct_Body : \ - case Typename : -#define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES -#define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES +# define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES \ + case Access_Public: \ + case Access_Protected: \ + case Access_Private: \ + case PlatformAttributes: \ + case Class_Body: \ + case Enum_Body: \ + case Execution: \ + case Friend: \ + case Function_Body: \ + case Namespace_Body: \ + case Operator_Member: \ + case Operator_Member_Fwd: \ + case Parameters: \ + case Specifiers: \ + case Struct_Body: \ + case Typename: +# define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES +# define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES -#define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \ - case Access_Public : \ - case Access_Protected : \ - case Access_Private : \ - case PlatformAttributes : \ - case Class_Body : \ - case Enum_Body : \ - case Execution : \ - case Friend : \ - case Function_Body : \ - case Namespace_Body : \ - case Operator_Member : \ - case Operator_Member_Fwd : \ - case Parameters : \ - case Specifiers : \ - case Struct_Body : \ - case Typename : +# define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \ + case Access_Public: \ + case Access_Protected: \ + case Access_Private: \ + case PlatformAttributes: \ + case Class_Body: \ + case Enum_Body: \ + case Execution: \ + case Friend: \ + case Function_Body: \ + case Namespace_Body: \ + case Operator_Member: \ + case Operator_Member_Fwd: \ + case Parameters: \ + case Specifiers: \ + case Struct_Body: \ + case Typename: Code Code::Global; Code Code::Invalid; @@ -217,7 +217,7 @@ Code Code::Invalid; // This serializes all the data-members in a "debug" format, where each member is printed with its associated value. char const* AST::debug_str() { - String result = String::make_reserve( GlobalAllocator, kilobytes( 1 ) ); + String result = String::make_reserve( GlobalAllocator, kilobytes(1) ); if ( Parent ) result.append_fmt( "\n\tParent : %S %S", Parent->type_str(), Name ? Name : "" ); @@ -232,245 +232,245 @@ char const* AST::debug_str() { using namespace ECode; - case Invalid : - case NewLine : - case Access_Private : - case Access_Protected : - case Access_Public : + case Invalid: + case NewLine: + case Access_Private: + case Access_Protected: + case Access_Public: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - break; + break; - case Untyped : - case Execution : - case Comment : - case PlatformAttributes : - case Preprocess_Define : - case Preprocess_Include : - case Preprocess_Pragma : - case Preprocess_If : - case Preprocess_ElIf : - case Preprocess_Else : - case Preprocess_IfDef : - case Preprocess_IfNotDef : + case Untyped: + case Execution: + case Comment: + case PlatformAttributes: + case Preprocess_Define: + case Preprocess_Include: + case Preprocess_Pragma: + case Preprocess_If: + case Preprocess_ElIf: + case Preprocess_Else: + case Preprocess_IfDef: + case Preprocess_IfNotDef: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); result.append_fmt( "\n\tContent: %S", Content ); - break; + break; - case Class : - case Struct : + case Class: + case Struct: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmd : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmd : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess ) : "No Parent" ); - result.append_fmt( "\n\tParentType : %s", ParentType ? ParentType->type_str() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess ) : "No Parent" ); + result.append_fmt( "\n\tParentType : %s", ParentType ? ParentType->type_str() : "Null" ); + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Class_Fwd : - case Struct_Fwd : + case Class_Fwd: + case Struct_Fwd: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmd : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmd : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess ) : "No Parent" ); - result.append_fmt( "\n\tParentType : %s", ParentType ? ParentType->type_str() : "Null" ); - break; + result.append_fmt( "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess ) : "No Parent" ); + result.append_fmt( "\n\tParentType : %s", ParentType ? ParentType->type_str() : "Null" ); + break; - case Constructor : + case Constructor: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tInitializerList: %S", InitializerList ? InitializerList->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Constructor_Fwd : + case Constructor_Fwd: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tInitializerList: %S", InitializerList ? InitializerList->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); - break; + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + break; - case Destructor : + case Destructor: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Destructor_Fwd : - break; + case Destructor_Fwd: + break; - case Enum : - case Enum_Class : + case Enum: + case Enum_Class: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); result.append_fmt( "\n\tUnderlying Type : %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Enum_Fwd : - case Enum_Class_Fwd : + case Enum_Fwd: + case Enum_Class_Fwd: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); result.append_fmt( "\n\tUnderlying Type : %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); - break; + break; - case Extern_Linkage : - case Namespace : + case Extern_Linkage: + case Namespace: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); result.append_fmt( "\n\tBody: %S", Body ? Body->debug_str() : "Null" ); - break; + break; - case Friend : + case Friend: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tDeclaration: %S", Declaration ? Declaration->to_string() : "Null" ); - break; + break; - case Function : + case Function: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Function_Fwd : + case Function_Fwd: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); - break; + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + break; - case Module : + case Module: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - break; + break; - case Operator : - case Operator_Member : + case Operator: + case Operator_Member: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); result.append_fmt( "\n\tOp : %S", to_str( Op ) ); - break; + break; - case Operator_Fwd : - case Operator_Member_Fwd : + case Operator_Fwd: + case Operator_Member_Fwd: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); result.append_fmt( "\n\tOp : %S", to_str( Op ) ); - break; + break; - case Operator_Cast : + case Operator_Cast: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); - result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Operator_Cast_Fwd : + case Operator_Cast_Fwd: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); - result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); - break; + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); + break; - case Parameters : + case Parameters: result.append_fmt( "\n\tNumEntries: %d", NumEntries ); result.append_fmt( "\n\tLast : %S", Last->Name ); result.append_fmt( "\n\tNext : %S", Next->Name ); result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); - result.append_fmt( "\n\tValue : %S", Value ? Value->to_string() : "Null" ); - break; + result.append_fmt( "\n\tValue : %S", Value ? Value->to_string() : "Null" ); + break; - case Specifiers : + case Specifiers: { result.append_fmt( "\n\tNumEntries: %d", NumEntries ); result.append( "\n\tArrSpecs: " ); @@ -487,64 +487,64 @@ char const* AST::debug_str() } break; - case Template : + case Template: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); result.append_fmt( "\n\tDeclaration: %S", Declaration ? Declaration->to_string() : "Null" ); - break; + break; - case Typedef : + case Typedef: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); result.append_fmt( "\n\tUnderlyingType: %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); - break; + break; - case Typename : + case Typename: result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); result.append_fmt( "\n\tReturnType : %S", ReturnType ? ReturnType->to_string() : "Null" ); - result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); - result.append_fmt( "\n\tArrExpr : %S", ArrExpr ? ArrExpr->to_string() : "Null" ); - break; + result.append_fmt( "\n\tParams : %S", Params ? Params->to_string() : "Null" ); + result.append_fmt( "\n\tArrExpr : %S", ArrExpr ? ArrExpr->to_string() : "Null" ); + break; - case Union : + case Union: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tBody : %S", Body ? Body->debug_str() : "Null" ); + break; - case Using : + case Using: if ( Prev ) result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); result.append_fmt( "\n\tUnderlyingType: %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); - break; + break; - case Variable : + case Variable: if ( Parent && Parent->Type == Variable ) { // Its a NextVar - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); - result.append_fmt( "\n\tValue : %S", Value ? Value->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tValue : %S", Value ? Value->to_string() : "Null" ); result.append_fmt( "\n\tBitfieldSize: %S", BitfieldSize ? BitfieldSize->to_string() : "Null" ); - result.append_fmt( "\n\tNextVar : %S", NextVar ? NextVar->debug_str() : "Null" ); + result.append_fmt( "\n\tNextVar : %S", NextVar ? NextVar->debug_str() : "Null" ); break; } @@ -553,14 +553,14 @@ char const* AST::debug_str() if ( Next ) result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); - result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); - result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); - result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); - result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); + result.append_fmt( "\n\tInlineCmt : %S", InlineCmt ? InlineCmt->Content : "Null" ); + result.append_fmt( "\n\tAttributes : %S", Attributes ? Attributes->to_string() : "Null" ); + result.append_fmt( "\n\tSpecs : %S", Specs ? Specs->to_string() : "Null" ); + result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); result.append_fmt( "\n\tBitfieldSize: %S", BitfieldSize ? BitfieldSize->to_string() : "Null" ); - result.append_fmt( "\n\tValue : %S", Value ? Value->to_string() : "Null" ); - result.append_fmt( "\n\tNextVar : %S", NextVar ? NextVar->debug_str() : "Null" ); - break; + result.append_fmt( "\n\tValue : %S", Value ? Value->to_string() : "Null" ); + result.append_fmt( "\n\tNextVar : %S", NextVar ? NextVar->debug_str() : "Null" ); + break; } return result; @@ -587,225 +587,226 @@ String AST::to_string() void AST::to_string( String& result ) { - local_persist thread_local char SerializationLevel = 0; + local_persist thread_local + char SerializationLevel = 0; switch ( Type ) { using namespace ECode; - case Invalid : -#ifdef GEN_DONT_ALLOW_INVALID_CODE - log_failure( "Attempted to serialize invalid code! - %S", Parent ? Parent->debug_str() : Name ); -#else + case Invalid: + #ifdef GEN_DONT_ALLOW_INVALID_CODE + log_failure("Attempted to serialize invalid code! - %S", Parent ? Parent->debug_str() : Name ); + #else result.append_fmt( "Invalid Code!" ); -#endif - break; + #endif + break; - case NewLine : - result.append( "\n" ); - break; + case NewLine: + result.append("\n"); + break; - case Untyped : - case Execution : - case Comment : - case PlatformAttributes : + case Untyped: + case Execution: + case Comment: + case PlatformAttributes: result.append( Content ); - break; + break; - case Access_Private : - case Access_Protected : - case Access_Public : + case Access_Private: + case Access_Protected: + case Access_Public: result.append( Name ); - break; + break; - case Class : + case Class: cast().to_string_def( result ); - break; + break; - case Class_Fwd : + case Class_Fwd: cast().to_string_fwd( result ); - break; + break; - case Constructor : + case Constructor: cast().to_string_def( result ); - break; + break; - case Constructor_Fwd : + case Constructor_Fwd: cast().to_string_fwd( result ); - break; + break; - case Destructor : + case Destructor: cast().to_string_def( result ); - break; + break; - case Destructor_Fwd : + case Destructor_Fwd: cast().to_string_fwd( result ); - break; + break; - case Enum : + case Enum: cast().to_string_def( result ); - break; + break; - case Enum_Fwd : + case Enum_Fwd: cast().to_string_fwd( result ); - break; + break; - case Enum_Class : + case Enum_Class: cast().to_string_class_def( result ); - break; + break; - case Enum_Class_Fwd : + case Enum_Class_Fwd: cast().to_string_class_fwd( result ); - break; + break; - case Export_Body : + case Export_Body: cast().to_string_export( result ); - break; + break; - case Extern_Linkage : + case Extern_Linkage: cast().to_string( result ); - break; + break; - case Friend : + case Friend: cast().to_string( result ); - break; + break; - case Function : + case Function: cast().to_string_def( result ); - break; + break; - case Function_Fwd : + case Function_Fwd: cast().to_string_fwd( result ); - break; + break; - case Module : + case Module: cast().to_string( result ); - break; + break; - case Namespace : + case Namespace: cast().to_string( result ); - break; + break; - case Operator : - case Operator_Member : + case Operator: + case Operator_Member: cast().to_string_def( result ); - break; + break; - case Operator_Fwd : - case Operator_Member_Fwd : + case Operator_Fwd: + case Operator_Member_Fwd: cast().to_string_fwd( result ); - break; + break; - case Operator_Cast : + case Operator_Cast: cast().to_string_def( result ); - break; + break; - case Operator_Cast_Fwd : + case Operator_Cast_Fwd: cast().to_string_fwd( result ); - break; + break; - case Parameters : + case Parameters: cast().to_string( result ); - break; + break; - case Preprocess_Define : + case Preprocess_Define: cast().to_string( result ); - break; + break; - case Preprocess_If : + case Preprocess_If: cast().to_string_if( result ); - break; + break; - case Preprocess_IfDef : + case Preprocess_IfDef: cast().to_string_ifdef( result ); - break; + break; - case Preprocess_IfNotDef : + case Preprocess_IfNotDef: cast().to_string_ifndef( result ); - break; + break; - case Preprocess_Include : + case Preprocess_Include: cast().to_string( result ); - break; + break; - case Preprocess_ElIf : + case Preprocess_ElIf: cast().to_string_elif( result ); - break; + break; - case Preprocess_Else : + case Preprocess_Else: cast().to_string_else( result ); - break; + break; - case Preprocess_EndIf : + case Preprocess_EndIf: cast().to_string_endif( result ); - break; + break; - case Preprocess_Pragma : + case Preprocess_Pragma: cast().to_string( result ); - break; + break; - case Specifiers : + case Specifiers: cast().to_string( result ); - break; + break; - case Struct : + case Struct: cast().to_string_def( result ); - break; + break; - case Struct_Fwd : + case Struct_Fwd: cast().to_string_fwd( result ); - break; + break; - case Template : + case Template: cast().to_string( result ); - break; + break; - case Typedef : + case Typedef: cast().to_string( result ); - break; + break; - case Typename : + case Typename: cast().to_string( result ); - break; + break; - case Union : + case Union: cast().to_string( result ); - break; + break; - case Using : + case Using: cast().to_string( result ); - break; + break; - case Using_Namespace : + case Using_Namespace: cast().to_string_ns( result ); - break; + break; - case Variable : + case Variable: cast().to_string( result ); - break; + break; - case Enum_Body : - case Class_Body : - case Extern_Linkage_Body : - case Function_Body : - case Global_Body : - case Namespace_Body : - case Struct_Body : - case Union_Body : + case Enum_Body: + case Class_Body: + case Extern_Linkage_Body: + case Function_Body: + case Global_Body: + case Namespace_Body: + case Struct_Body: + case Union_Body: cast().to_string( result ); - break; + break; } } bool AST::is_equal( AST* other ) { - /* - AST values are either some u32 value, a cached string, or a pointer to another AST. +/* + AST values are either some u32 value, a cached string, or a pointer to another AST. - u32 values are compared by value. - Cached strings are compared by pointer. - AST nodes are compared with AST::is_equal. - */ + u32 values are compared by value. + Cached strings are compared by pointer. + AST nodes are compared with AST::is_equal. +*/ if ( other == nullptr ) { log_fmt( "AST::is_equal: other is null\nAST: %S", debug_str() ); @@ -814,7 +815,10 @@ bool AST::is_equal( AST* other ) if ( Type != other->Type ) { - log_fmt( "AST::is_equal: Type check failure with other\nAST: %S\nOther: %S", debug_str(), other->debug_str() ); + log_fmt("AST::is_equal: Type check failure with other\nAST: %S\nOther: %S" + , debug_str() + , other->debug_str() + ); return false; } @@ -823,120 +827,109 @@ bool AST::is_equal( AST* other ) { using namespace ECode; -#define check_member_val( val ) \ - if ( val != other->val ) \ - { \ - log_fmt( \ - "\nAST::is_equal: Member - " #val \ - " failed\n" \ - "AST : %S\n" \ - "Other: %S\n", \ - debug_str(), \ - other->debug_str() \ - ); \ - \ - return false; \ + #define check_member_val( val ) \ + if ( val != other->val ) \ + { \ + log_fmt("\nAST::is_equal: Member - " #val " failed\n" \ + "AST : %S\n" \ + "Other: %S\n" \ + , debug_str() \ + , other->debug_str() \ + ); \ + \ + return false; \ } -#define check_member_str( str ) \ - if ( str != other->str ) \ - { \ - log_fmt( \ - "\nAST::is_equal: Member string - " #str \ - " failed\n" \ - "AST : %S\n" \ - "Other: %S\n", \ - debug_str(), \ - other->debug_str() \ - ); \ - \ - return false; \ + #define check_member_str( str ) \ + if ( str != other->str ) \ + { \ + log_fmt("\nAST::is_equal: Member string - "#str " failed\n" \ + "AST : %S\n" \ + "Other: %S\n" \ + , debug_str() \ + , other->debug_str() \ + ); \ + \ + return false; \ } -#define check_member_content( content ) \ - if ( content != other->content ) \ - { \ - log_fmt( \ - "\nAST::is_equal: Member content - " #content \ - " failed\n" \ - "AST : %S\n" \ - "Other: %S\n", \ - debug_str(), \ - other->debug_str() \ - ); \ - \ - log_fmt( \ - "Content cannot be trusted to be unique with this check " \ - "so it must be verified by eye for now\n" \ - "AST Content:\n%S\n" \ - "Other Content:\n%S\n", \ - content.visualize_whitespace(), \ - other->content.visualize_whitespace() \ - ); \ + #define check_member_content( content ) \ + if ( content != other->content ) \ + { \ + log_fmt("\nAST::is_equal: Member content - "#content " failed\n" \ + "AST : %S\n" \ + "Other: %S\n" \ + , debug_str() \ + , other->debug_str() \ + ); \ + \ + log_fmt("Content cannot be trusted to be unique with this check " \ + "so it must be verified by eye for now\n" \ + "AST Content:\n%S\n" \ + "Other Content:\n%S\n" \ + , content.visualize_whitespace() \ + , other->content.visualize_whitespace() \ + ); \ } -#define check_member_ast( ast ) \ - if ( ast ) \ - { \ - if ( other->ast == nullptr ) \ - { \ - log_fmt( \ - "\nAST::is_equal: Failed for member " #ast \ - " other equivalent param is null\n" \ - "AST : %s\n" \ - "Other: %s\n" \ - "For ast member: %s\n", \ - debug_str(), \ - other->debug_str(), \ - ast->debug_str() \ - ); \ - \ - return false; \ - } \ - \ - if ( ! ast->is_equal( other->ast ) ) \ - { \ - log_fmt( \ - "\nAST::is_equal: Failed for " #ast \ - "\n" \ - "AST : %S\n" \ - "Other: %S\n" \ - "For ast member: %S\n" \ - "other's ast member: %S\n", \ - debug_str(), \ - other->debug_str(), \ - ast->debug_str(), \ - other->ast->debug_str() \ - ); \ - \ - return false; \ - } \ + #define check_member_ast( ast ) \ + if ( ast ) \ + { \ + if ( other->ast == nullptr ) \ + { \ + log_fmt("\nAST::is_equal: Failed for member " #ast " other equivalent param is null\n" \ + "AST : %s\n" \ + "Other: %s\n" \ + "For ast member: %s\n" \ + , debug_str() \ + , other->debug_str() \ + , ast->debug_str() \ + ); \ + \ + return false; \ + } \ + \ + if ( ! ast->is_equal( other->ast ) ) \ + { \ + log_fmt( "\nAST::is_equal: Failed for " #ast"\n" \ + "AST : %S\n" \ + "Other: %S\n" \ + "For ast member: %S\n" \ + "other's ast member: %S\n" \ + , debug_str() \ + , other->debug_str() \ + , ast->debug_str() \ + , other->ast->debug_str() \ + ); \ + \ + return false; \ + } \ } - case NewLine : - case Access_Public : - case Access_Protected : - case Access_Private : - case Preprocess_Else : - case Preprocess_EndIf : + case NewLine: + case Access_Public: + case Access_Protected: + case Access_Private: + case Preprocess_Else: + case Preprocess_EndIf: return true; // Comments are not validated. - case Comment : + case Comment: return true; - case Execution : - case PlatformAttributes : - case Untyped : + case Execution: + case PlatformAttributes: + case Untyped: { check_member_content( Content ); return true; } - case Class_Fwd : - case Struct_Fwd : + case Class_Fwd: + case Struct_Fwd: { check_member_str( Name ); check_member_ast( ParentType ); @@ -946,8 +939,8 @@ bool AST::is_equal( AST* other ) return true; } - case Class : - case Struct : + case Class: + case Struct: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -959,7 +952,7 @@ bool AST::is_equal( AST* other ) return true; } - case Constructor : + case Constructor: { check_member_ast( InitializerList ); check_member_ast( Params ); @@ -968,7 +961,7 @@ bool AST::is_equal( AST* other ) return true; } - case Constructor_Fwd : + case Constructor_Fwd: { check_member_ast( InitializerList ); check_member_ast( Params ); @@ -976,7 +969,7 @@ bool AST::is_equal( AST* other ) return true; } - case Destructor : + case Destructor: { check_member_ast( Specs ); check_member_ast( Body ); @@ -984,15 +977,15 @@ bool AST::is_equal( AST* other ) return true; } - case Destructor_Fwd : + case Destructor_Fwd: { check_member_ast( Specs ); return true; } - case Enum : - case Enum_Class : + case Enum: + case Enum_Class: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1003,8 +996,8 @@ bool AST::is_equal( AST* other ) return true; } - case Enum_Fwd : - case Enum_Class_Fwd : + case Enum_Fwd: + case Enum_Class_Fwd: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1014,7 +1007,7 @@ bool AST::is_equal( AST* other ) return true; } - case Extern_Linkage : + case Extern_Linkage: { check_member_str( Name ); check_member_ast( Body ); @@ -1022,7 +1015,7 @@ bool AST::is_equal( AST* other ) return true; } - case Friend : + case Friend: { check_member_str( Name ); check_member_ast( Declaration ); @@ -1030,7 +1023,7 @@ bool AST::is_equal( AST* other ) return true; } - case Function : + case Function: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1043,7 +1036,7 @@ bool AST::is_equal( AST* other ) return true; } - case Function_Fwd : + case Function_Fwd: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1055,7 +1048,7 @@ bool AST::is_equal( AST* other ) return true; } - case Module : + case Module: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1063,7 +1056,7 @@ bool AST::is_equal( AST* other ) return true; } - case Namespace : + case Namespace: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1072,8 +1065,8 @@ bool AST::is_equal( AST* other ) return true; } - case Operator : - case Operator_Member : + case Operator: + case Operator_Member: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1086,8 +1079,8 @@ bool AST::is_equal( AST* other ) return true; } - case Operator_Fwd : - case Operator_Member_Fwd : + case Operator_Fwd: + case Operator_Member_Fwd: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1099,7 +1092,7 @@ bool AST::is_equal( AST* other ) return true; } - case Operator_Cast : + case Operator_Cast: { check_member_str( Name ); check_member_ast( Specs ); @@ -1109,7 +1102,7 @@ bool AST::is_equal( AST* other ) return true; } - case Operator_Cast_Fwd : + case Operator_Cast_Fwd: { check_member_str( Name ); check_member_ast( Specs ); @@ -1118,24 +1111,23 @@ bool AST::is_equal( AST* other ) return true; } - case Parameters : + case Parameters: { if ( NumEntries > 1 ) { AST* curr = this; AST* curr_other = other; - while ( curr != nullptr ) + while ( curr != nullptr ) { if ( curr ) { if ( curr_other == nullptr ) { - log_fmt( - "\nAST::is_equal: Failed for parameter, other equivalent param is null\n" - "AST : %S\n" - "Other: %S\n" - "For ast member: %S\n", - curr->debug_str() + log_fmt("\nAST::is_equal: Failed for parameter, other equivalent param is null\n" + "AST : %S\n" + "Other: %S\n" + "For ast member: %S\n" + , curr->debug_str() ); return false; @@ -1143,48 +1135,45 @@ bool AST::is_equal( AST* other ) if ( curr->Name != curr_other->Name ) { - log_fmt( - "\nAST::is_equal: Failed for parameter name check\n" - "AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n", - debug_str(), - other->debug_str(), - curr->debug_str(), - curr_other->debug_str() + log_fmt( "\nAST::is_equal: Failed for parameter name check\n" + "AST : %S\n" + "Other: %S\n" + "For ast member: %S\n" + "other's ast member: %S\n" + , debug_str() + , other->debug_str() + , curr->debug_str() + , curr_other->debug_str() ); return false; } - if ( curr->ValueType && ! curr->ValueType->is_equal( curr_other->ValueType ) ) + if ( curr->ValueType && ! curr->ValueType->is_equal(curr_other->ValueType) ) { - log_fmt( - "\nAST::is_equal: Failed for parameter value type check\n" - "AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n", - debug_str(), - other->debug_str(), - curr->debug_str(), - curr_other->debug_str() + log_fmt( "\nAST::is_equal: Failed for parameter value type check\n" + "AST : %S\n" + "Other: %S\n" + "For ast member: %S\n" + "other's ast member: %S\n" + , debug_str() + , other->debug_str() + , curr->debug_str() + , curr_other->debug_str() ); return false; } - if ( curr->Value && ! curr->Value->is_equal( curr_other->Value ) ) + if ( curr->Value && ! curr->Value->is_equal(curr_other->Value) ) { - log_fmt( - "\nAST::is_equal: Failed for parameter value check\n" - "AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n", - debug_str(), - other->debug_str(), - curr->debug_str(), - curr_other->debug_str() + log_fmt( "\nAST::is_equal: Failed for parameter value check\n" + "AST : %S\n" + "Other: %S\n" + "For ast member: %S\n" + "other's ast member: %S\n" + , debug_str() + , other->debug_str() + , curr->debug_str() + , curr_other->debug_str() ); return false; } @@ -1207,7 +1196,7 @@ bool AST::is_equal( AST* other ) return true; } - case Preprocess_Define : + case Preprocess_Define: { check_member_str( Name ); check_member_content( Content ); @@ -1215,36 +1204,36 @@ bool AST::is_equal( AST* other ) return true; } - case Preprocess_If : - case Preprocess_IfDef : - case Preprocess_IfNotDef : - case Preprocess_ElIf : + case Preprocess_If: + case Preprocess_IfDef: + case Preprocess_IfNotDef: + case Preprocess_ElIf: { check_member_content( Content ); return true; } - case Preprocess_Include : - case Preprocess_Pragma : + case Preprocess_Include: + case Preprocess_Pragma: { check_member_content( Content ); return true; } - case Specifiers : + case Specifiers: { check_member_val( NumEntries ); check_member_str( Name ); for ( s32 idx = 0; idx < NumEntries; ++idx ) { - check_member_val( ArrSpecs[idx] ); + check_member_val( ArrSpecs[ idx ] ); } return true; } - case Template : + case Template: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1254,7 +1243,7 @@ bool AST::is_equal( AST* other ) return true; } - case Typedef : + case Typedef: { check_member_val( IsFunction ); check_member_val( ModuleFlags ); @@ -1264,7 +1253,7 @@ bool AST::is_equal( AST* other ) return true; } - case Typename : + case Typename: { check_member_val( IsParamPack ); check_member_str( Name ); @@ -1274,7 +1263,7 @@ bool AST::is_equal( AST* other ) return true; } - case Union : + case Union: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1284,8 +1273,8 @@ bool AST::is_equal( AST* other ) return true; } - case Using : - case Using_Namespace : + case Using: + case Using_Namespace: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1295,7 +1284,7 @@ bool AST::is_equal( AST* other ) return true; } - case Variable : + case Variable: { check_member_val( ModuleFlags ); check_member_str( Name ); @@ -1309,13 +1298,13 @@ bool AST::is_equal( AST* other ) return true; } - case Class_Body : - case Enum_Body : - case Export_Body : - case Global_Body : - case Namespace_Body : - case Struct_Body : - case Union_Body : + case Class_Body: + case Enum_Body: + case Export_Body: + case Global_Body: + case Namespace_Body: + case Struct_Body: + case Union_Body: { check_member_ast( Front ); check_member_ast( Back ); @@ -1326,12 +1315,11 @@ bool AST::is_equal( AST* other ) { if ( curr_other == nullptr ) { - log_fmt( - "\nAST::is_equal: Failed for body, other equivalent param is null\n" - "AST : %S\n" - "Other: %S\n" - "For ast member: %S\n", - curr->debug_str() + log_fmt("\nAST::is_equal: Failed for body, other equivalent param is null\n" + "AST : %S\n" + "Other: %S\n" + "For ast member: %S\n" + , curr->debug_str() ); return false; @@ -1339,16 +1327,15 @@ bool AST::is_equal( AST* other ) if ( ! curr->is_equal( curr_other ) ) { - log_fmt( - "\nAST::is_equal: Failed for body\n" - "AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n", - debug_str(), - other->debug_str(), - curr->debug_str(), - curr_other->debug_str() + log_fmt( "\nAST::is_equal: Failed for body\n" + "AST : %S\n" + "Other: %S\n" + "For ast member: %S\n" + "other's ast member: %S\n" + , debug_str() + , other->debug_str() + , curr->debug_str() + , curr_other->debug_str() ); return false; @@ -1363,9 +1350,9 @@ bool AST::is_equal( AST* other ) return true; } -#undef check_member_val -#undef check_member_str -#undef check_member_ast + #undef check_member_val + #undef check_member_str + #undef check_member_ast } return true; @@ -1375,25 +1362,27 @@ bool AST::validate_body() { using namespace ECode; -#define CheckEntries( Unallowed_Types ) \ - do \ - { \ - for ( Code entry : cast() ) \ - { \ - switch ( entry->Type ) \ - { \ - Unallowed_Types log_failure( "AST::validate_body: Invalid entry in body %s", entry.debug_str() ); \ - return false; \ - } \ - } \ - } while ( 0 ); +#define CheckEntries( Unallowed_Types ) \ + do \ + { \ + for ( Code entry : cast() ) \ + { \ + switch ( entry->Type ) \ + { \ + Unallowed_Types \ + log_failure( "AST::validate_body: Invalid entry in body %s", entry.debug_str() ); \ + return false; \ + } \ + } \ + } \ + while (0); switch ( Type ) { - case Class_Body : + case Class_Body: CheckEntries( GEN_AST_BODY_CLASS_UNALLOWED_TYPES ); - break; - case Enum_Body : + break; + case Enum_Body: for ( Code entry : cast() ) { if ( entry->Type != Untyped ) @@ -1402,50 +1391,50 @@ bool AST::validate_body() return false; } } - break; - case Export_Body : + break; + case Export_Body: CheckEntries( GEN_AST_BODY_CLASS_UNALLOWED_TYPES ); - break; - case Extern_Linkage : + break; + case Extern_Linkage: CheckEntries( GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES ); - break; - case Function_Body : + break; + case Function_Body: CheckEntries( GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES ); - break; - case Global_Body : - for ( Code entry : cast() ) + break; + case Global_Body: + for (Code entry : cast()) { - switch ( entry->Type ) + switch (entry->Type) { - case Access_Public : - case Access_Protected : - case Access_Private : - case PlatformAttributes : - case Class_Body : - case Enum_Body : - case Execution : - case Friend : - case Function_Body : - case Global_Body : - case Namespace_Body : - case Operator_Member : - case Operator_Member_Fwd : - case Parameters : - case Specifiers : - case Struct_Body : - case Typename : - log_failure( "AST::validate_body: Invalid entry in body %s", entry.debug_str() ); - return false; + case Access_Public: + case Access_Protected: + case Access_Private: + case PlatformAttributes: + case Class_Body: + case Enum_Body: + case Execution: + case Friend: + case Function_Body: + case Global_Body: + case Namespace_Body: + case Operator_Member: + case Operator_Member_Fwd: + case Parameters: + case Specifiers: + case Struct_Body: + case Typename: + log_failure("AST::validate_body: Invalid entry in body %s", entry.debug_str()); + return false; } } - break; - case Namespace_Body : + break; + case Namespace_Body: CheckEntries( GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES ); - break; - case Struct_Body : + break; + case Struct_Body: CheckEntries( GEN_AST_BODY_STRUCT_UNALLOWED_TYPES ); - break; - case Union_Body : + break; + case Union_Body: for ( Code entry : Body->cast() ) { if ( entry->Type != Untyped ) @@ -1454,9 +1443,9 @@ bool AST::validate_body() return false; } } - break; + break; - default : + default: log_failure( "AST::validate_body: Invalid this AST does not have a body %s", debug_str() ); return false; } @@ -1487,25 +1476,25 @@ String CodeBody::to_string() switch ( ast->Type ) { using namespace ECode; - case Untyped : - case Execution : + case Untyped: + case Execution: result.append( raw()->Content ); - break; + break; - case Enum_Body : - case Class_Body : - case Extern_Linkage_Body : - case Function_Body : - case Global_Body : - case Namespace_Body : - case Struct_Body : - case Union_Body : + case Enum_Body: + case Class_Body: + case Extern_Linkage_Body: + case Function_Body: + case Global_Body: + case Namespace_Body: + case Struct_Body: + case Union_Body: to_string( result ); - break; + break; - case Export_Body : + case Export_Body: to_string_export( result ); - break; + break; } return result; } @@ -1514,7 +1503,7 @@ void CodeBody::to_string( String& result ) { Code curr = ast->Front; s32 left = ast->NumEntries; - while ( left-- ) + while ( left -- ) { result.append_fmt( "%S", curr.to_string() ); ++curr; @@ -1544,15 +1533,15 @@ String CodeComment::to_string() String CodeConstructor::to_string() { String result = String::make( GlobalAllocator, "" ); - switch ( ast->Type ) + switch (ast->Type) { using namespace ECode; - case Constructor : + case Constructor: to_string_def( result ); - break; - case Constructor_Fwd : + break; + case Constructor_Fwd: to_string_fwd( result ); - break; + break; } return result; } @@ -1560,12 +1549,10 @@ String CodeConstructor::to_string() void CodeConstructor::to_string_def( String& result ) { AST* ClassStructParent = ast->Parent->Parent; - if ( ClassStructParent ) - { + if (ClassStructParent) { result.append( ClassStructParent->Name ); } - else - { + else { result.append( ast->Name ); } @@ -1586,21 +1573,19 @@ void CodeConstructor::to_string_def( String& result ) void CodeConstructor::to_string_fwd( String& result ) { AST* ClassStructParent = ast->Parent->Parent; - if ( ClassStructParent ) - { + if (ClassStructParent) { result.append( ClassStructParent->Name ); } - else - { + else { result.append( ast->Name ); } if ( ast->Params ) result.append_fmt( "( %S )", ast->Params.to_string() ); else - result.append_fmt( "()" ); + result.append_fmt("()"); - if ( ast->Body ) + if (ast->Body) result.append_fmt( " = %S", ast->Body.to_string() ); if ( ast->InlineCmt ) @@ -1615,19 +1600,19 @@ String CodeClass::to_string() switch ( ast->Type ) { using namespace ECode; - case Class : + case Class: to_string_def( result ); - break; - case Class_Fwd : + break; + case Class_Fwd: to_string_fwd( result ); - break; + break; } return result; } void CodeClass::to_string_def( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); result.append( "class " ); @@ -1643,14 +1628,14 @@ void CodeClass::to_string_def( String& result ) result.append_fmt( "%S : %s %S", ast->Name, access_level, ast->ParentType.to_string() ); - CodeType interface = ast->ParentType->Next->cast(); + CodeType interface = ast->ParentType->Next->cast< CodeType >(); if ( interface ) result.append( "\n" ); while ( interface ) { result.append_fmt( ", %S", interface.to_string() ); - interface = interface->Next ? interface->Next->cast() : CodeType { nullptr }; + interface = interface->Next ? interface->Next->cast< CodeType >() : CodeType { nullptr }; } } else if ( ast->Name ) @@ -1666,19 +1651,18 @@ void CodeClass::to_string_def( String& result ) result.append_fmt( "\n{\n%S\n}", ast->Body.to_string() ); if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) - result.append( ";\n" ); + result.append(";\n"); } void CodeClass::to_string_fwd( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) result.append_fmt( "class %S %S", ast->Attributes.to_string(), ast->Name ); - else - result.append_fmt( "class %S", ast->Name ); + else result.append_fmt( "class %S", ast->Name ); // Check if it can have an end-statement if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) @@ -1686,7 +1670,7 @@ void CodeClass::to_string_fwd( String& result ) if ( ast->InlineCmt ) result.append_fmt( "; // %S\n", ast->InlineCmt->Content ); else - result.append( ";\n" ); + result.append(";\n"); } } @@ -1706,12 +1690,12 @@ String CodeDestructor::to_string() switch ( ast->Type ) { using namespace ECode; - case Destructor : + case Destructor: to_string_def( result ); - break; - case Destructor_Fwd : + break; + case Destructor_Fwd: to_string_fwd( result ); - break; + break; } return result; } @@ -1746,7 +1730,7 @@ void CodeDestructor::to_string_fwd( String& result ) if ( ast->Specs.has( ESpecifier::Pure ) ) result.append( " = 0;" ); - else if ( ast->Body ) + else if (ast->Body) result.append_fmt( " = %S;", ast->Body.to_string() ); } else @@ -1755,7 +1739,7 @@ void CodeDestructor::to_string_fwd( String& result ) if ( ast->InlineCmt ) result.append_fmt( " %S", ast->InlineCmt->Content ); else - result.append( "\n" ); + result.append("\n"); } String CodeEnum::to_string() @@ -1764,25 +1748,25 @@ String CodeEnum::to_string() switch ( ast->Type ) { using namespace ECode; - case Enum : + case Enum: to_string_def( result ); - break; - case Enum_Fwd : + break; + case Enum_Fwd: to_string_fwd( result ); - break; - case Enum_Class : + break; + case Enum_Class: to_string_class_def( result ); - break; - case Enum_Class_Fwd : + break; + case Enum_Class_Fwd: to_string_class_fwd( result ); - break; + break; } return result; } void CodeEnum::to_string_def( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes || ast->UnderlyingType ) @@ -1793,21 +1777,23 @@ void CodeEnum::to_string_def( String& result ) result.append_fmt( "%S ", ast->Attributes.to_string() ); if ( ast->UnderlyingType ) - result.append_fmt( "%S : %S\n{\n%S\n}", ast->Name, ast->UnderlyingType.to_string(), ast->Body.to_string() ); + result.append_fmt( "%S : %S\n{\n%S\n}" + , ast->Name + , ast->UnderlyingType.to_string() + , ast->Body.to_string() + ); - else - result.append_fmt( "%S\n{\n%S\n}", ast->Name, ast->Body.to_string() ); + else result.append_fmt( "%S\n{\n%S\n}", ast->Name, ast->Body.to_string() ); } - else - result.append_fmt( "enum %S\n{\n%S\n}", ast->Name, ast->Body.to_string() ); + else result.append_fmt( "enum %S\n{\n%S\n}", ast->Name, ast->Body.to_string() ); if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) - result.append( ";\n" ); + result.append(";\n"); } void CodeEnum::to_string_fwd( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) @@ -1818,15 +1804,15 @@ void CodeEnum::to_string_fwd( String& result ) if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) { if ( ast->InlineCmt ) - result.append_fmt( "; %S", ast->InlineCmt->Content ); + result.append_fmt("; %S", ast->InlineCmt->Content ); else - result.append( ";\n" ); + result.append(";\n"); } } void CodeEnum::to_string_class_def( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes || ast->UnderlyingType ) @@ -1853,12 +1839,12 @@ void CodeEnum::to_string_class_def( String& result ) } if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) - result.append( ";\n" ); + result.append(";\n"); } void CodeEnum::to_string_class_fwd( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); result.append( "enum class " ); @@ -1871,9 +1857,9 @@ void CodeEnum::to_string_class_fwd( String& result ) if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) { if ( ast->InlineCmt ) - result.append_fmt( "; %S", ast->InlineCmt->Content ); + result.append_fmt("; %S", ast->InlineCmt->Content ); else - result.append( ";\n" ); + result.append(";\n"); } } @@ -1911,15 +1897,15 @@ void CodeFriend::to_string( String& result ) { result.append_fmt( "friend %S", ast->Declaration->to_string() ); - if ( ast->Declaration->Type != ECode::Function && result[result.length() - 1] != ';' ) + if ( ast->Declaration->Type != ECode::Function && result[ result.length() - 1 ] != ';' ) { result.append( ";" ); } if ( ast->InlineCmt ) - result.append_fmt( " %S", ast->InlineCmt->Content ); + result.append_fmt(" %S", ast->InlineCmt->Content ); else - result.append( "\n" ); + result.append("\n"); } String CodeFn::to_string() @@ -1928,19 +1914,19 @@ String CodeFn::to_string() switch ( ast->Type ) { using namespace ECode; - case Function : + case Function: to_string_def( result ); - break; - case Function_Fwd : + break; + case Function_Fwd: to_string_fwd( result ); - break; + break; } return result; } void CodeFn::to_string_def( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export" ); if ( ast->Attributes ) @@ -1993,7 +1979,7 @@ void CodeFn::to_string_def( String& result ) void CodeFn::to_string_fwd( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) @@ -2004,7 +1990,7 @@ void CodeFn::to_string_fwd( String& result ) { for ( SpecifierT spec : ast->Specs ) { - if ( ! ESpecifier::is_trailing( spec ) || ! ( spec != ESpecifier::Pure ) ) + if ( ! ESpecifier::is_trailing( spec ) || ! (spec != ESpecifier::Pure) ) { StrC spec_str = ESpecifier::to_str( spec ); result.append_fmt( " %.*s", spec_str.Len, spec_str.Ptr ); @@ -2016,7 +2002,7 @@ void CodeFn::to_string_fwd( String& result ) if ( ast->Attributes || prefix_specs ) { - result.append( "\n" ); + result.append("\n" ); } if ( ast->ReturnType ) @@ -2045,7 +2031,7 @@ void CodeFn::to_string_fwd( String& result ) if ( ast->Specs && ast->Specs.has( ESpecifier::Pure ) >= 0 ) result.append( " = 0;" ); - else if ( ast->Body ) + else if (ast->Body) result.append_fmt( " = %S;", ast->Body.to_string() ); if ( ast->InlineCmt ) @@ -2063,11 +2049,11 @@ String CodeModule::to_string() void CodeModule::to_string( String& result ) { - if ( ( ( u32( ModuleFlag::Export ) & u32( ast->ModuleFlags ) ) == u32( ModuleFlag::Export ) ) ) - result.append( "export " ); + if (((u32(ModuleFlag::Export) & u32(ast->ModuleFlags)) == u32(ModuleFlag::Export))) + result.append("export "); - if ( ( ( u32( ModuleFlag::Import ) & u32( ast->ModuleFlags ) ) == u32( ModuleFlag::Import ) ) ) - result.append( "import " ); + if (((u32(ModuleFlag::Import) & u32(ast->ModuleFlags)) == u32(ModuleFlag::Import))) + result.append("import "); result.append_fmt( "%S;\n", ast->Name ); } @@ -2081,10 +2067,10 @@ String CodeNS::to_string() void CodeNS::to_string( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); - result.append_fmt( "namespace %S\n{\n%S\n}\n", ast->Name, ast->Body.to_string() ); + result.append_fmt( "namespace %S\n{\n%S\n}\n", ast->Name , ast->Body.to_string() ); } String CodeOperator::to_string() @@ -2093,21 +2079,21 @@ String CodeOperator::to_string() switch ( ast->Type ) { using namespace ECode; - case Operator : - case Operator_Member : + case Operator: + case Operator_Member: to_string_def( result ); - break; - case Operator_Fwd : - case Operator_Member_Fwd : + break; + case Operator_Fwd: + case Operator_Member_Fwd: to_string_fwd( result ); - break; + break; } return result; } void CodeOperator::to_string_def( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) @@ -2130,7 +2116,7 @@ void CodeOperator::to_string_def( String& result ) if ( ast->Attributes || ast->Specs ) { - result.append( "\n" ); + result.append("\n" ); } if ( ast->ReturnType ) @@ -2154,12 +2140,14 @@ void CodeOperator::to_string_def( String& result ) } } - result.append_fmt( "\n{\n%S\n}\n", ast->Body.to_string() ); + result.append_fmt( "\n{\n%S\n}\n" + , ast->Body.to_string() + ); } void CodeOperator::to_string_fwd( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) @@ -2179,7 +2167,7 @@ void CodeOperator::to_string_fwd( String& result ) if ( ast->Attributes || ast->Specs ) { - result.append( "\n" ); + result.append("\n" ); } result.append_fmt( "%S %S (", ast->ReturnType.to_string(), ast->Name ); @@ -2214,12 +2202,12 @@ String CodeOpCast::to_string() switch ( ast->Type ) { using namespace ECode; - case Operator_Cast : + case Operator_Cast: to_string_def( result ); - break; - case Operator_Cast_Fwd : + break; + case Operator_Cast_Fwd: to_string_fwd( result ); - break; + break; } return result; } @@ -2256,9 +2244,9 @@ void CodeOpCast::to_string_def( String& result ) } if ( ast->Name && ast->Name.length() ) - result.append_fmt( "%Soperator %S()\n{\n%S\n}\n", ast->Name, ast->ValueType.to_string(), ast->Body.to_string() ); + result.append_fmt("%Soperator %S()\n{\n%S\n}\n", ast->Name, ast->ValueType.to_string(), ast->Body.to_string() ); else - result.append_fmt( "operator %S()\n{\n%S\n}\n", ast->ValueType.to_string(), ast->Body.to_string() ); + result.append_fmt("operator %S()\n{\n%S\n}\n", ast->ValueType.to_string(), ast->Body.to_string() ); } void CodeOpCast::to_string_fwd( String& result ) @@ -2293,9 +2281,9 @@ void CodeOpCast::to_string_fwd( String& result ) } if ( ast->InlineCmt ) - result.append_fmt( "operator %S(); %S", ast->ValueType.to_string() ); + result.append_fmt("operator %S(); %S", ast->ValueType.to_string() ); else - result.append_fmt( "operator %S();\n", ast->ValueType.to_string() ); + result.append_fmt("operator %S();\n", ast->ValueType.to_string() ); } String CodeParam::to_string() @@ -2320,13 +2308,14 @@ void CodeParam::to_string( String& result ) result.append_fmt( " %S", ast->Name ); else result.append_fmt( " %S %S", ast->ValueType.to_string(), ast->Name ); + } else if ( ast->ValueType ) result.append_fmt( " %S", ast->ValueType.to_string() ); if ( ast->PostNameMacro ) { - result.append_fmt( " %S", ast->PostNameMacro.to_string() ); + result.append_fmt(" %S", ast->PostNameMacro.to_string() ); } if ( ast->Value ) @@ -2347,24 +2336,24 @@ String CodePreprocessCond::to_string() switch ( ast->Type ) { using namespace ECode; - case Preprocess_If : + case Preprocess_If: to_string_if( result ); - break; - case Preprocess_IfDef : + break; + case Preprocess_IfDef: to_string_ifdef( result ); - break; - case Preprocess_IfNotDef : + break; + case Preprocess_IfNotDef: to_string_ifndef( result ); - break; - case Preprocess_ElIf : + break; + case Preprocess_ElIf: to_string_elif( result ); - break; - case Preprocess_Else : + break; + case Preprocess_Else: to_string_else( result ); - break; - case Preprocess_EndIf : + break; + case Preprocess_EndIf: to_string_endif( result ); - break; + break; } return result; } @@ -2436,19 +2425,19 @@ String CodeStruct::to_string() switch ( ast->Type ) { using namespace ECode; - case Struct : + case Struct: to_string_def( result ); - break; - case Struct_Fwd : + break; + case Struct_Fwd: to_string_fwd( result ); - break; + break; } return result; } void CodeStruct::to_string_def( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); result.append( "struct " ); @@ -2464,14 +2453,14 @@ void CodeStruct::to_string_def( String& result ) result.append_fmt( "%S : %s %S", ast->Name, access_level, ast->ParentType.to_string() ); - CodeType interface = ast->ParentType->Next->cast(); + CodeType interface = ast->ParentType->Next->cast< CodeType >(); if ( interface ) result.append( "\n" ); while ( interface ) { result.append_fmt( ", %S", interface.to_string() ); - interface = interface->Next ? interface->Next->cast() : CodeType { nullptr }; + interface = interface->Next ? interface->Next->cast< CodeType >() : CodeType { nullptr }; } } else if ( ast->Name ) @@ -2487,26 +2476,25 @@ void CodeStruct::to_string_def( String& result ) result.append_fmt( "\n{\n%S\n}", ast->Body.to_string() ); if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) - result.append( ";\n" ); + result.append(";\n"); } void CodeStruct::to_string_fwd( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) result.append_fmt( "struct %S %S", ast->Attributes.to_string(), ast->Name ); - else - result.append_fmt( "struct %S", ast->Name ); + else result.append_fmt( "struct %S", ast->Name ); if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) { if ( ast->InlineCmt ) - result.append_fmt( "; %S", ast->InlineCmt->Content ); + result.append_fmt("; %S", ast->InlineCmt->Content ); else - result.append( ";\n" ); + result.append(";\n"); } } @@ -2519,7 +2507,7 @@ String CodeTemplate::to_string() void CodeTemplate::to_string( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Params ) @@ -2537,10 +2525,10 @@ String CodeTypedef::to_string() void CodeTypedef::to_string( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); - result.append( "typedef " ); + result.append( "typedef "); // Determines if the typedef is a function typename if ( ast->UnderlyingType->ReturnType ) @@ -2565,9 +2553,9 @@ void CodeTypedef::to_string( String& result ) } if ( ast->InlineCmt ) - result.append_fmt( " %S", ast->InlineCmt->Content ); + result.append_fmt(" %S", ast->InlineCmt->Content); else - result.append( "\n" ); + result.append("\n"); } String CodeType::to_string() @@ -2579,37 +2567,37 @@ String CodeType::to_string() void CodeType::to_string( String& result ) { -#if defined( GEN_USE_NEW_TYPENAME_PARSING ) - if ( ast->ReturnType && ast->Params ) - { - if ( ast->Attributes ) - result.append_fmt( "%S ", ast->Attributes.to_string() ); - else + #if defined(GEN_USE_NEW_TYPENAME_PARSING) + if ( ast->ReturnType && ast->Params ) { - if ( ast->Specs ) - result.append_fmt( "%S ( %S ) ( %S ) %S", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string(), ast->Specs.to_string() ); + if ( ast->Attributes ) + result.append_fmt( "%S ", ast->Attributes.to_string() ); else - result.append_fmt( "%S ( %S ) ( %S )", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string() ); - } + { + if ( ast->Specs ) + result.append_fmt( "%S ( %S ) ( %S ) %S", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string(), ast->Specs.to_string() ); + else + result.append_fmt( "%S ( %S ) ( %S )", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string() ); + } - break; - } -#else - if ( ast->ReturnType && ast->Params ) - { - if ( ast->Attributes ) - result.append_fmt( "%S ", ast->Attributes.to_string() ); - else + break; + } + #else + if ( ast->ReturnType && ast->Params ) { - if ( ast->Specs ) - result.append_fmt( "%S %S ( %S ) %S", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string(), ast->Specs.to_string() ); + if ( ast->Attributes ) + result.append_fmt( "%S ", ast->Attributes.to_string() ); else - result.append_fmt( "%S %S ( %S )", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string() ); - } + { + if ( ast->Specs ) + result.append_fmt( "%S %S ( %S ) %S", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string(), ast->Specs.to_string() ); + else + result.append_fmt( "%S %S ( %S )", ast->ReturnType.to_string(), ast->Name, ast->Params.to_string() ); + } - return; - } -#endif + return; + } + #endif if ( ast->Attributes ) result.append_fmt( "%S ", ast->Attributes.to_string() ); @@ -2620,7 +2608,7 @@ void CodeType::to_string( String& result ) result.append_fmt( "%S", ast->Name ); if ( ast->IsParamPack ) - result.append( "..." ); + result.append("..."); } String CodeUnion::to_string() @@ -2632,7 +2620,7 @@ String CodeUnion::to_string() void CodeUnion::to_string( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); result.append( "union " ); @@ -2642,16 +2630,21 @@ void CodeUnion::to_string( String& result ) if ( ast->Name ) { - result.append_fmt( "%S\n{\n%S\n}", ast->Name, ast->Body.to_string() ); + result.append_fmt( "%S\n{\n%S\n}" + , ast->Name + , ast->Body.to_string() + ); } else { // Anonymous union - result.append_fmt( "\n{\n%S\n}", ast->Body.to_string() ); + result.append_fmt( "\n{\n%S\n}" + , ast->Body.to_string() + ); } if ( ast->Parent.ast == nullptr || ( ast->Parent->Type != ECode::Typedef && ast->Parent->Type != ECode::Variable ) ) - result.append( ";\n" ); + result.append(";\n"); } String CodeUsing::to_string() @@ -2660,19 +2653,19 @@ String CodeUsing::to_string() switch ( ast->Type ) { using namespace ECode; - case Using : + case Using: to_string( result ); - break; - case Using_Namespace : + break; + case Using_Namespace: to_string_ns( result ); - break; + break; } return result; } void CodeUsing::to_string( String& result ) { - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes ) @@ -2700,9 +2693,9 @@ void CodeUsing::to_string( String& result ) result.append_fmt( "using %S;", ast->Name ); if ( ast->InlineCmt ) - result.append_fmt( " %S\n", ast->InlineCmt->Content ); + result.append_fmt(" %S\n", ast->InlineCmt->Content ); else - result.append( "\n" ); + result.append("\n"); } void CodeUsing::to_string_ns( String& result ) @@ -2756,12 +2749,12 @@ void CodeVar::to_string( String& result ) result.append_fmt( ", %S", ast->NextVar.to_string() ); if ( ast->VarConstructorInit ) - result.append( " )" ); + result.append( " )"); return; } - if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export ) ) + if ( bitfield_is_equal( u32, ast->ModuleFlags, ModuleFlag::Export )) result.append( "export " ); if ( ast->Attributes || ast->Specs ) @@ -2801,10 +2794,10 @@ void CodeVar::to_string( String& result ) result.append_fmt( ", %S", ast->NextVar.to_string() ); if ( ast->VarConstructorInit ) - result.append( " )" ); + result.append( " )"); if ( ast->InlineCmt ) - result.append_fmt( "; %S", ast->InlineCmt->Content ); + result.append_fmt("; %S", ast->InlineCmt->Content); else result.append( ";\n" ); @@ -2841,72 +2834,72 @@ void CodeVar::to_string( String& result ) result.append_fmt( ", %S", ast->NextVar.to_string() ); if ( ast->VarConstructorInit ) - result.append( " )" ); + result.append( " )"); result.append( ";" ); if ( ast->InlineCmt ) - result.append_fmt( " %S", ast->InlineCmt->Content ); + result.append_fmt(" %S", ast->InlineCmt->Content); else - result.append( "\n" ); + result.append("\n"); } #pragma endregion AST #pragma region Interface -namespace parser -{ - internal void init(); - internal void deinit(); +namespace parser { +internal void init(); +internal void deinit(); } -internal void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) +internal +void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) { - Arena* last = &Global_AllocatorBuckets.back(); + Arena* last = & Global_AllocatorBuckets.back(); switch ( type ) { - case EAllocation_ALLOC : + case EAllocation_ALLOC: { if ( ( last->TotalUsed + size ) > last->TotalSize ) { Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); if ( bucket.PhysicalStart == nullptr ) - GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets" ); + GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); if ( ! Global_AllocatorBuckets.append( bucket ) ) - GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets" ); + GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); - last = &Global_AllocatorBuckets.back(); + last = & Global_AllocatorBuckets.back(); } - return alloc_align( *last, size, alignment ); + return alloc_align( * last, size, alignment ); } - case EAllocation_FREE : + case EAllocation_FREE: { // Doesn't recycle. } break; - case EAllocation_FREE_ALL : + case EAllocation_FREE_ALL: { // Memory::cleanup instead. } break; - case EAllocation_RESIZE : + case EAllocation_RESIZE: { if ( last->TotalUsed + size > last->TotalSize ) { Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); if ( bucket.PhysicalStart == nullptr ) - GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets" ); + GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); if ( ! Global_AllocatorBuckets.append( bucket ) ) - GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets" ); + GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); - last = &Global_AllocatorBuckets.back(); + last = & Global_AllocatorBuckets.back(); } void* result = alloc_align( last->Backing, size, alignment ); @@ -2923,80 +2916,81 @@ internal void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw s return nullptr; } -internal void define_constants() +internal +void define_constants() { Code::Global = make_code(); - Code::Global->Name = get_cached_string( txt( "Global Code" ) ); + Code::Global->Name = get_cached_string( txt("Global Code") ); Code::Global->Content = Code::Global->Name; - Code::Invalid = make_code(); + Code::Invalid = make_code(); Code::Invalid.set_global(); - t_empty = (CodeType)make_code(); - t_empty->Type = ECode::Typename; - t_empty->Name = get_cached_string( txt( "" ) ); + t_empty = (CodeType) make_code(); + t_empty->Type = ECode::Typename; + t_empty->Name = get_cached_string( txt("") ); t_empty.set_global(); access_private = make_code(); access_private->Type = ECode::Access_Private; - access_private->Name = get_cached_string( txt( "private:\n" ) ); + access_private->Name = get_cached_string( txt("private:\n") ); access_private.set_global(); access_protected = make_code(); access_protected->Type = ECode::Access_Protected; - access_protected->Name = get_cached_string( txt( "protected:\n" ) ); + access_protected->Name = get_cached_string( txt("protected:\n") ); access_protected.set_global(); access_public = make_code(); access_public->Type = ECode::Access_Public; - access_public->Name = get_cached_string( txt( "public:\n" ) ); + access_public->Name = get_cached_string( txt("public:\n") ); access_public.set_global(); - attrib_api_export = def_attributes( code( GEN_API_Export_Code ) ); + attrib_api_export = def_attributes( code(GEN_API_Export_Code)); attrib_api_export.set_global(); - attrib_api_import = def_attributes( code( GEN_API_Import_Code ) ); + attrib_api_import = def_attributes( code(GEN_API_Import_Code)); attrib_api_import.set_global(); module_global_fragment = make_code(); module_global_fragment->Type = ECode::Untyped; - module_global_fragment->Name = get_cached_string( txt( "module;" ) ); + module_global_fragment->Name = get_cached_string( txt("module;") ); module_global_fragment->Content = module_global_fragment->Name; module_global_fragment.set_global(); module_private_fragment = make_code(); module_private_fragment->Type = ECode::Untyped; - module_private_fragment->Name = get_cached_string( txt( "module : private;" ) ); + module_private_fragment->Name = get_cached_string( txt("module : private;") ); module_private_fragment->Content = module_private_fragment->Name; module_private_fragment.set_global(); - fmt_newline = make_code(); + fmt_newline = make_code(); fmt_newline->Type = ECode::NewLine; fmt_newline.set_global(); - pragma_once = (CodePragma)make_code(); + pragma_once = (CodePragma) make_code(); pragma_once->Type = ECode::Preprocess_Pragma; - pragma_once->Name = get_cached_string( txt( "once" ) ); + pragma_once->Name = get_cached_string( txt("once") ); pragma_once->Content = pragma_once->Name; pragma_once.set_global(); - param_varadic = (CodeType)make_code(); + param_varadic = (CodeType) make_code(); param_varadic->Type = ECode::Parameters; - param_varadic->Name = get_cached_string( txt( "..." ) ); + param_varadic->Name = get_cached_string( txt("...") ); param_varadic->ValueType = t_empty; param_varadic.set_global(); - preprocess_else = (CodePreprocessCond)make_code(); + preprocess_else = (CodePreprocessCond) make_code(); preprocess_else->Type = ECode::Preprocess_Else; preprocess_else.set_global(); - preprocess_endif = (CodePreprocessCond)make_code(); + preprocess_endif = (CodePreprocessCond) make_code(); preprocess_endif->Type = ECode::Preprocess_EndIf; preprocess_endif.set_global(); -#define def_constant_code_type( Type_ ) \ - t_##Type_ = def_type( name( Type_ ) ); \ - t_##Type_.set_global(); +# define def_constant_code_type( Type_ ) \ + t_##Type_ = def_type( name(Type_) ); \ + t_##Type_.set_global(); def_constant_code_type( auto ); def_constant_code_type( void ); @@ -3008,7 +3002,7 @@ internal void define_constants() def_constant_code_type( typename ); #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS - t_b32 = def_type( name( b32 ) ); + t_b32 = def_type( name(b32) ); def_constant_code_type( s8 ); def_constant_code_type( s16 ); @@ -3020,82 +3014,84 @@ internal void define_constants() def_constant_code_type( u32 ); def_constant_code_type( u64 ); - def_constant_code_type( sw ); - def_constant_code_type( uw ); + def_constant_code_type( ssize ); + def_constant_code_type( usize ); def_constant_code_type( f32 ); def_constant_code_type( f64 ); #endif -#undef def_constant_code_type +# undef def_constant_code_type -#define def_constant_spec( Type_, ... ) \ - spec_##Type_ = def_specifiers( num_args( __VA_ARGS__ ), __VA_ARGS__ ); \ - spec_##Type_.set_global(); +# define def_constant_spec( Type_, ... ) \ + spec_##Type_ = def_specifiers( num_args(__VA_ARGS__), __VA_ARGS__); \ + spec_##Type_.set_global(); -#pragma push_macro( "FORCEINLINE" ) -#pragma push_macro( "global" ) -#pragma push_macro( "internal" ) -#pragma push_macro( "local_persist" ) -#pragma push_macro( "neverinline" ) -#undef FORCEINLINE -#undef global -#undef internal -#undef local_persist -#undef neverinline - def_constant_spec( const, ESpecifier::Const ); - def_constant_spec( consteval, ESpecifier::Consteval ); - def_constant_spec( constexpr, ESpecifier::Constexpr ); - def_constant_spec( constinit, ESpecifier::Constinit ); - def_constant_spec( extern_linkage, ESpecifier::External_Linkage ); - def_constant_spec( final, ESpecifier::Final ); - def_constant_spec( FORCEINLINE, ESpecifier::ForceInline ); - def_constant_spec( global, ESpecifier::Global ); - def_constant_spec( inline, ESpecifier::Inline ); +# pragma push_macro("FORCEINLINE") +# pragma push_macro("global") +# pragma push_macro("internal") +# pragma push_macro("local_persist") +# pragma push_macro("neverinline") +# undef FORCEINLINE +# undef global +# undef internal +# undef local_persist +# undef neverinline + def_constant_spec( const, ESpecifier::Const ); + def_constant_spec( consteval, ESpecifier::Consteval ); + def_constant_spec( constexpr, ESpecifier::Constexpr ); + def_constant_spec( constinit, ESpecifier::Constinit ); + def_constant_spec( extern_linkage, ESpecifier::External_Linkage ); + def_constant_spec( final, ESpecifier::Final ); + def_constant_spec( FORCEINLINE, ESpecifier::ForceInline ); + def_constant_spec( global, ESpecifier::Global ); + def_constant_spec( inline, ESpecifier::Inline ); def_constant_spec( internal_linkage, ESpecifier::Internal_Linkage ); - def_constant_spec( local_persist, ESpecifier::Local_Persist ); - def_constant_spec( mutable, ESpecifier::Mutable ); - def_constant_spec( neverinline, ESpecifier::NeverInline ); - def_constant_spec( noexcept, ESpecifier::NoExceptions ); - def_constant_spec( override, ESpecifier::Override ); - def_constant_spec( ptr, ESpecifier::Ptr ); - def_constant_spec( pure, ESpecifier::Pure ) def_constant_spec( ref, ESpecifier::Ref ); - def_constant_spec( register, ESpecifier::Register ); - def_constant_spec( rvalue, ESpecifier::RValue ); - def_constant_spec( static_member, ESpecifier::Static ); - def_constant_spec( thread_local, ESpecifier::Thread_Local ); - def_constant_spec( virtual, ESpecifier::Virtual ); - def_constant_spec( volatile, ESpecifier::Volatile ) + def_constant_spec( local_persist, ESpecifier::Local_Persist ); + def_constant_spec( mutable, ESpecifier::Mutable ); + def_constant_spec( neverinline, ESpecifier::NeverInline ); + def_constant_spec( noexcept, ESpecifier::NoExceptions ); + def_constant_spec( override, ESpecifier::Override ); + def_constant_spec( ptr, ESpecifier::Ptr ); + def_constant_spec( pure, ESpecifier::Pure ) + def_constant_spec( ref, ESpecifier::Ref ); + def_constant_spec( register, ESpecifier::Register ); + def_constant_spec( rvalue, ESpecifier::RValue ); + def_constant_spec( static_member, ESpecifier::Static ); + def_constant_spec( thread_local, ESpecifier::Thread_Local ); + def_constant_spec( virtual, ESpecifier::Virtual ); + def_constant_spec( volatile, ESpecifier::Volatile) - spec_local_persist = def_specifiers( 1, ESpecifier::Local_Persist ); + spec_local_persist = def_specifiers( 1, ESpecifier::Local_Persist ); spec_local_persist.set_global(); -#pragma pop_macro( "FORCEINLINE" ) -#pragma pop_macro( "global" ) -#pragma pop_macro( "internal" ) -#pragma pop_macro( "local_persist" ) -#pragma pop_macro( "neverinline" ) +# pragma pop_macro("FORCEINLINE") +# pragma pop_macro("global") +# pragma pop_macro("internal") +# pragma pop_macro("local_persist") +# pragma pop_macro("neverinline") -#undef def_constant_spec +# undef def_constant_spec } void init() { // Setup global allocator { - GlobalAllocator = AllocatorInfo { &Global_Allocator_Proc, nullptr }; + GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr }; Global_AllocatorBuckets = Array::init_reserve( heap(), 128 ); if ( Global_AllocatorBuckets == nullptr ) - GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets" ); + GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets"); Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); if ( bucket.PhysicalStart == nullptr ) - GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets" ); + GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets"); Global_AllocatorBuckets.append( bucket ); + } // Setup the arrays @@ -3113,14 +3109,14 @@ void init() // Setup the code pool and code entries arena. { - Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof( AST ) ); + Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); if ( code_pool.PhysicalStart == nullptr ) GEN_FATAL( "gen::init: Failed to initialize the code pool" ); CodePools.append( code_pool ); - LexArena = Arena::init_from_allocator( Allocator_Lexer, LexAllocator_Size ); + LexArena = Arena::init_from_allocator( Allocator_Lexer, LexAllocator_Size ); Arena string_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); @@ -3135,11 +3131,11 @@ void init() StringCache = StringTable::init( Allocator_StringTable ); if ( StringCache.Entries == nullptr ) - GEN_FATAL( "gen::init: Failed to initialize the StringCache" ); + GEN_FATAL( "gen::init: Failed to initialize the StringCache"); } // Preprocessor Defines - PreprocessorDefines = Array::init_reserve( GlobalAllocator, kilobytes( 1 ) ); + PreprocessorDefines = Array::init_reserve( GlobalAllocator, kilobytes(1) ); define_constants(); parser::init(); @@ -3147,23 +3143,25 @@ void init() void deinit() { - uw index = 0; - uw left = CodePools.num(); + usize index = 0; + usize left = CodePools.num(); do { - Pool* code_pool = &CodePools[index]; + Pool* code_pool = & CodePools[index]; code_pool->free(); index++; - } while ( left--, left ); + } + while ( left--, left ); index = 0; left = StringArenas.num(); do { - Arena* string_arena = &StringArenas[index]; + Arena* string_arena = & StringArenas[index]; string_arena->free(); index++; - } while ( left--, left ); + } + while ( left--, left ); StringCache.destroy(); @@ -3178,10 +3176,11 @@ void deinit() left = Global_AllocatorBuckets.num(); do { - Arena* bucket = &Global_AllocatorBuckets[index]; + Arena* bucket = & Global_AllocatorBuckets[ index ]; bucket->free(); index++; - } while ( left--, left ); + } + while ( left--, left ); Global_AllocatorBuckets.free(); parser::deinit(); @@ -3193,20 +3192,21 @@ void reset() s32 left = CodePools.num(); do { - Pool* code_pool = &CodePools[index]; + Pool* code_pool = & CodePools[index]; code_pool->clear(); index++; - } while ( left--, left ); + } + while ( left--, left ); index = 0; left = StringArenas.num(); do { - Arena* string_arena = &StringArenas[index]; - string_arena->TotalUsed = 0; - ; + Arena* string_arena = & StringArenas[index]; + string_arena->TotalUsed = 0;; index++; - } while ( left--, left ); + } + while ( left--, left ); StringCache.clear(); @@ -3215,33 +3215,33 @@ void reset() AllocatorInfo get_string_allocator( s32 str_length ) { - Arena* last = &StringArenas.back(); + Arena* last = & StringArenas.back(); - uw size_req = str_length + sizeof( String::Header ) + sizeof( char* ); + usize size_req = str_length + sizeof(String::Header) + sizeof(char*); - if ( last->TotalUsed + sw( size_req ) > last->TotalSize ) + if ( last->TotalUsed + ssize(size_req) > last->TotalSize ) { Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); if ( ! StringArenas.append( new_arena ) ) GEN_FATAL( "gen::get_string_allocator: Failed to allocate a new string arena" ); - last = &StringArenas.back(); + last = & StringArenas.back(); } - return *last; + return * last; } // Will either make or retrive a code string. StringCached get_cached_string( StrC str ) { - s32 hash_length = str.Len > kilobytes( 1 ) ? kilobytes( 1 ) : str.Len; + s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len; u64 key = crc32( str.Ptr, hash_length ); { StringCached* result = StringCache.get( key ); if ( result ) - return *result; + return * result; } String result = String::make( get_string_allocator( str.Len ), str ); @@ -3253,10 +3253,10 @@ StringCached get_cached_string( StrC str ) // Used internally to retireve a Code object form the CodePool. Code make_code() { - Pool* allocator = &CodePools.back(); + Pool* allocator = & CodePools.back(); if ( allocator->FreeList == nullptr ) { - Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof( AST ) ); + Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); if ( code_pool.PhysicalStart == nullptr ) GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." ); @@ -3264,11 +3264,11 @@ Code make_code() if ( ! CodePools.append( code_pool ) ) GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." ); - allocator = &CodePools.back(); + allocator = & CodePools.back(); } - Code result { rcast( AST*, alloc( *allocator, sizeof( AST ) ) ) }; - mem_set( result.ast, 0, sizeof( AST ) ); + Code result { rcast( AST*, alloc( * allocator, sizeof(AST) )) }; + mem_set( result.ast, 0, sizeof(AST) ); // result->Type = ECode::Invalid; // result->Content = { nullptr }; @@ -3324,46 +3324,45 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy if ( op == EOperator::Invalid ) { - log_failure( "gen::def_operator: op cannot be invalid" ); + log_failure("gen::def_operator: op cannot be invalid"); return OpValidateResult::Fail; } #pragma region Helper Macros -#define check_params() \ - if ( ! params_code ) \ - { \ - log_failure( "gen::def_operator: params is null and operator%s requires it", to_str( op ) ); \ - return OpValidateResult::Fail; \ - } \ - if ( params_code->Type != ECode::Parameters ) \ - { \ - log_failure( "gen::def_operator: params is not of Parameters type - %s", params_code.debug_str() ); \ - return OpValidateResult::Fail; \ +# define check_params() \ + if ( ! params_code ) \ + { \ + log_failure("gen::def_operator: params is null and operator%s requires it", to_str(op)); \ + return OpValidateResult::Fail; \ + } \ + if ( params_code->Type != ECode::Parameters ) \ + { \ + log_failure("gen::def_operator: params is not of Parameters type - %s", params_code.debug_str()); \ + return OpValidateResult::Fail; \ } -#define check_param_eq_ret() \ - if ( ! is_member_symbol && ! params_code->ValueType.is_equal( ret_type ) ) \ - { \ - log_failure( \ - "gen::def_operator: operator%s requires first parameter to equal return type\n" \ - "param types: %s\n" \ - "return type: %s", \ - to_str( op ).Ptr, \ - params_code.debug_str(), \ - ret_type.debug_str() \ - ); \ - return OpValidateResult::Fail; \ +# define check_param_eq_ret() \ + if ( ! is_member_symbol && ! params_code->ValueType.is_equal( ret_type) ) \ + { \ + log_failure("gen::def_operator: operator%s requires first parameter to equal return type\n" \ + "param types: %s\n" \ + "return type: %s", \ + to_str(op).Ptr, \ + params_code.debug_str(), \ + ret_type.debug_str() \ + ); \ + return OpValidateResult::Fail; \ } #pragma endregion Helper Macros if ( ! ret_type ) { - log_failure( "gen::def_operator: ret_type is null but is required by operator%s", to_str( op ) ); + log_failure("gen::def_operator: ret_type is null but is required by operator%s", to_str(op)); } if ( ret_type->Type != ECode::Typename ) { - log_failure( "gen::def_operator: ret_type is not of typename type - %s", ret_type.debug_str() ); + log_failure("gen::def_operator: ret_type is not of typename type - %s", ret_type.debug_str()); return OpValidateResult::Fail; } @@ -3371,17 +3370,16 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy switch ( op ) { -#define specs( ... ) num_args( __VA_ARGS__ ), __VA_ARGS__ - case Assign : +# define specs( ... ) num_args( __VA_ARGS__ ), __VA_ARGS__ + case Assign: check_params(); if ( params_code->NumEntries > 1 ) { - log_failure( - "gen::def_operator: " - "operator%s does not support non-member definition (more than one parameter provided) - %s", - to_str( op ), - params_code.debug_str() + log_failure("gen::def_operator: " + "operator%s does not support non-member definition (more than one parameter provided) - %s", + to_str(op), + params_code.debug_str() ); return OpValidateResult::Fail; } @@ -3389,16 +3387,16 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy is_member_symbol = true; break; - case Assign_Add : - case Assign_Subtract : - case Assign_Multiply : - case Assign_Divide : - case Assign_Modulo : - case Assign_BAnd : - case Assign_BOr : - case Assign_BXOr : - case Assign_LShift : - case Assign_RShift : + case Assign_Add: + case Assign_Subtract: + case Assign_Multiply: + case Assign_Divide: + case Assign_Modulo: + case Assign_BAnd: + case Assign_BOr: + case Assign_BXOr: + case Assign_LShift: + case Assign_RShift: check_params(); if ( params_code->NumEntries == 1 ) @@ -3407,32 +3405,34 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy else check_param_eq_ret(); - if ( params_code->NumEntries > 2 ) + if (params_code->NumEntries > 2 ) { - log_failure( - "gen::def_operator: operator%s may not be defined with more than two parametes - param count; %d\n%s", - to_str( op ), - params_code->NumEntries, - params_code.debug_str() + log_failure("gen::def_operator: operator%s may not be defined with more than two parametes - param count; %d\n%s" + , to_str(op) + , params_code->NumEntries + , params_code.debug_str() ); return OpValidateResult::Fail; } break; - case Increment : - case Decrement : + case Increment: + case Decrement: // If its not set, it just means its a prefix member op. if ( params_code ) { if ( params_code->Type != ECode::Parameters ) { - log_failure( "gen::def_operator: operator%s params code provided is not of Parameters type - %s", to_str( op ), params_code.debug_str() ); + log_failure("gen::def_operator: operator%s params code provided is not of Parameters type - %s" + , to_str(op) + , params_code.debug_str() + ); return OpValidateResult::Fail; } switch ( params_code->NumEntries ) { - case 1 : + case 1: if ( params_code->ValueType.is_equal( t_int ) ) is_member_symbol = true; @@ -3440,33 +3440,31 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy check_param_eq_ret(); break; - case 2 : + case 2: check_param_eq_ret(); - if ( ! params_code.get( 1 ).is_equal( t_int ) ) + if ( ! params_code.get(1).is_equal( t_int ) ) { - log_failure( - "gen::def_operator: " - "operator%s requires second parameter of non-member definition to be int for post-decrement", - to_str( op ) + log_failure("gen::def_operator: " + "operator%s requires second parameter of non-member definition to be int for post-decrement", + to_str(op) ); return OpValidateResult::Fail; } break; - default : - log_failure( - "gen::def_operator: operator%s recieved unexpected number of parameters recived %d instead of 0-2", - to_str( op ), - params_code->NumEntries + default: + log_failure("gen::def_operator: operator%s recieved unexpected number of parameters recived %d instead of 0-2" + , to_str(op) + , params_code->NumEntries ); return OpValidateResult::Fail; } } break; - case Unary_Plus : - case Unary_Minus : + case Unary_Plus: + case Unary_Minus: if ( ! params_code ) is_member_symbol = true; @@ -3474,45 +3472,43 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy { if ( params_code->Type != ECode::Parameters ) { - log_failure( "gen::def_operator: params is not of Parameters type - %s", params_code.debug_str() ); + log_failure("gen::def_operator: params is not of Parameters type - %s", params_code.debug_str()); return OpValidateResult::Fail; } if ( params_code->ValueType.is_equal( ret_type ) ) { - log_failure( - "gen::def_operator: " - "operator%s is non-member symbol yet first paramter does not equal return type\n" - "param type: %s\n" - "return type: %s\n", - params_code.debug_str(), - ret_type.debug_str() + log_failure("gen::def_operator: " + "operator%s is non-member symbol yet first paramter does not equal return type\n" + "param type: %s\n" + "return type: %s\n" + , params_code.debug_str() + , ret_type.debug_str() ); return OpValidateResult::Fail; } if ( params_code->NumEntries > 1 ) { - log_failure( - "gen::def_operator: operator%s may not have more than one parameter - param count: %d", - to_str( op ), - params_code->NumEntries + log_failure("gen::def_operator: operator%s may not have more than one parameter - param count: %d" + , to_str(op) + , params_code->NumEntries ); return OpValidateResult::Fail; } } break; - case BNot : + case BNot: { // Some compilers let you do this... -#if 0 + #if 0 if ( ! ret_type.is_equal( t_bool) ) { log_failure( "gen::def_operator: return type is not a boolean - %s", params_code.debug_str() ); return OpValidateResult::Fail; } -#endif + #endif if ( ! params_code ) is_member_symbol = true; @@ -3538,50 +3534,48 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy break; } - case Add : - case Subtract : - case Multiply : - case Divide : - case Modulo : - case BAnd : - case BOr : - case BXOr : - case LShift : - case RShift : + case Add: + case Subtract: + case Multiply: + case Divide: + case Modulo: + case BAnd: + case BOr: + case BXOr: + case LShift: + case RShift: check_params(); switch ( params_code->NumEntries ) { - case 1 : + case 1: is_member_symbol = true; break; - case 2 : + case 2: if ( ! params_code->ValueType.is_equal( ret_type ) ) { - log_failure( - "gen::def_operator: " - "operator%s is non-member symbol yet first paramter does not equal return type\n" - "param type: %s\n" - "return type: %s\n", - params_code.debug_str(), - ret_type.debug_str() + log_failure("gen::def_operator: " + "operator%s is non-member symbol yet first paramter does not equal return type\n" + "param type: %s\n" + "return type: %s\n" + , params_code.debug_str() + , ret_type.debug_str() ); return OpValidateResult::Fail; } break; - default : - log_failure( - "gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 0-2", - to_str( op ), - params_code->NumEntries + default: + log_failure("gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 0-2" + , to_str(op) + , params_code->NumEntries ); return OpValidateResult::Fail; } break; - case UnaryNot : + case UnaryNot: if ( ! params_code ) is_member_symbol = true; @@ -3589,66 +3583,66 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy { if ( params_code->Type != ECode::Parameters ) { - log_failure( "gen::def_operator: params is not of Parameters type - %s", params_code.debug_str() ); + log_failure("gen::def_operator: params is not of Parameters type - %s", params_code.debug_str()); return OpValidateResult::Fail; } if ( params_code->NumEntries != 1 ) { - log_failure( - "gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 0-1", - to_str( op ), - params_code->NumEntries + log_failure("gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 0-1" + , to_str(op) + , params_code->NumEntries ); return OpValidateResult::Fail; } } - if ( ! ret_type.is_equal( t_bool ) ) + if ( ! ret_type.is_equal( t_bool )) { - log_failure( "gen::def_operator: operator%s return type must be of type bool - %s", to_str( op ), ret_type.debug_str() ); + log_failure("gen::def_operator: operator%s return type must be of type bool - %s" + , to_str(op) + , ret_type.debug_str() + ); return OpValidateResult::Fail; } break; - case LAnd : - case LOr : - case LEqual : - case LNot : - case Lesser : - case Greater : - case LesserEqual : - case GreaterEqual : + case LAnd: + case LOr: + case LEqual: + case LNot: + case Lesser: + case Greater: + case LesserEqual: + case GreaterEqual: check_params(); switch ( params_code->NumEntries ) { - case 1 : + case 1: is_member_symbol = true; break; - case 2 : + case 2: break; - default : - log_failure( - "gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 1-2", - to_str( op ), - params_code->NumEntries + default: + log_failure("gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 1-2" + , to_str(op) + , params_code->NumEntries ); return OpValidateResult::Fail; } break; - case Indirection : - case AddressOf : - case MemberOfPointer : - if ( params_code && params_code->NumEntries > 1 ) + case Indirection: + case AddressOf: + case MemberOfPointer: + if ( params_code && params_code->NumEntries > 1) { - log_failure( - "gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 0-1", - to_str( op ), - params_code->NumEntries + log_failure("gen::def_operator: operator%s recieved unexpected number of paramters recived %d instead of 0-1" + , to_str(op) + , params_code->NumEntries ); return OpValidateResult::Fail; } @@ -3658,77 +3652,79 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy } break; - case PtrToMemOfPtr : + case PtrToMemOfPtr: if ( params_code ) { - log_failure( "gen::def_operator: operator%s expects no paramters - %s", to_str( op ), params_code.debug_str() ); + log_failure("gen::def_operator: operator%s expects no paramters - %s", to_str(op), params_code.debug_str()); return OpValidateResult::Fail; } break; - case Subscript : - case FunctionCall : - case Comma : + case Subscript: + case FunctionCall: + case Comma: check_params(); break; - case New : - case Delete : + case New: + case Delete: // This library doesn't support validating new and delete yet. break; -#undef specs +# undef specs } return is_member_symbol ? OpValidateResult::Member : OpValidateResult::Global; -#undef check_params -#undef check_ret_type -#undef check_param_eq_ret +# undef check_params +# undef check_ret_type +# undef check_param_eq_ret } + #pragma region Helper Marcos // This snippet is used in nearly all the functions. -#define name_check( Context_, Name_ ) \ - { \ - if ( Name_.Len <= 0 ) \ - { \ - log_failure( "gen::" stringize( Context_ ) ": Invalid name length provided - %d", Name_.Len ); \ - return CodeInvalid; \ - } \ - \ - if ( Name_.Ptr == nullptr ) \ - { \ - log_failure( "gen::" stringize( Context_ ) ": name is null" ); \ - return CodeInvalid; \ - } \ +#define name_check( Context_, Name_ ) \ +{ \ + if ( Name_.Len <= 0 ) \ + { \ + log_failure( "gen::" stringize(Context_) ": Invalid name length provided - %d", Name_.Len ); \ + return CodeInvalid; \ + } \ + \ + if ( Name_.Ptr == nullptr ) \ + { \ + log_failure( "gen::" stringize(Context_) ": name is null" ); \ + return CodeInvalid; \ + } \ +} + +#define null_check( Context_, Code_ ) \ + if ( ! Code_ ) \ + { \ + log_failure( "gen::" stringize(Context_) ": " stringize(Code_) " provided is null" ); \ + return CodeInvalid; \ } -#define null_check( Context_, Code_ ) \ - if ( ! Code_ ) \ - { \ - log_failure( "gen::" stringize( Context_ ) ": " stringize( Code_ ) " provided is null" ); \ - return CodeInvalid; \ - } - -#define null_or_invalid_check( Context_, Code_ ) \ - { \ - if ( ! Code_ ) \ - { \ - log_failure( "gen::" stringize( Context_ ) ": " stringize( Code_ ) " provided is null" ); \ - return CodeInvalid; \ - } \ - \ - if ( Code_->is_invalid() ) \ - { \ - log_failure( "gen::" stringize( Context_ ) ": " stringize( Code_ ) " provided is invalid" ); \ - return CodeInvalid; \ - } \ - } +#define null_or_invalid_check( Context_, Code_ ) \ +{ \ + if ( ! Code_ ) \ + { \ + log_failure( "gen::" stringize(Context_) ": " stringize(Code_) " provided is null" ); \ + return CodeInvalid; \ + } \ + \ + if ( Code_->is_invalid() ) \ + { \ + log_failure("gen::" stringize(Context_) ": " stringize(Code_) " provided is invalid" ); \ + return CodeInvalid; \ + } \ +} #define not_implemented( Context_ ) \ log_failure( "gen::%s: This function is not implemented" ); \ return CodeInvalid; #pragma endregion Helper Marcos + /* The implementaiton of the upfront constructors involves doing three things: * Validate the arguments given to construct the intended type of AST is valid. @@ -3749,12 +3745,13 @@ CodeAttributes def_attributes( StrC content ) return CodeInvalid; } - Code result = make_code(); + Code + result = make_code(); result->Type = ECode::PlatformAttributes; result->Name = get_cached_string( content ); result->Content = result->Name; - return (CodeAttributes)result; + return (CodeAttributes) result; } CodeComment def_comment( StrC content ) @@ -3765,9 +3762,9 @@ CodeComment def_comment( StrC content ) return CodeInvalid; } - static char line[MaxCommentLineLength]; + static char line[ MaxCommentLineLength ]; - String cmt_formatted = String::make_reserve( GlobalAllocator, kilobytes( 1 ) ); + String cmt_formatted = String::make_reserve( GlobalAllocator, kilobytes(1) ); char const* end = content.Ptr + content.Len; char const* scanner = content.Ptr; s32 curr = 0; @@ -3775,7 +3772,7 @@ CodeComment def_comment( StrC content ) { char const* next = scanner; s32 length = 0; - while ( next != end && scanner[length] != '\n' ) + while ( next != end && scanner[ length ] != '\n' ) { next = scanner + length; length++; @@ -3787,19 +3784,21 @@ CodeComment def_comment( StrC content ) mem_set( line, 0, MaxCommentLineLength ); scanner += length; - } while ( scanner <= end ); + } + while ( scanner <= end ); if ( cmt_formatted.back() != '\n' ) cmt_formatted.append( "\n" ); - Code result = make_code(); + Code + result = make_code(); result->Type = ECode::Comment; result->Name = get_cached_string( cmt_formatted ); result->Content = result->Name; cmt_formatted.free(); - return (CodeComment)result; + return (CodeComment) result; } CodeConstructor def_constructor( CodeParam params, Code initializer_list, Code body ) @@ -3808,11 +3807,12 @@ CodeConstructor def_constructor( CodeParam params, Code initializer_list, Code b if ( params && params->Type != Parameters ) { - log_failure( "gen::def_constructor: params must be of Parameters type - %s", params.debug_str() ); + log_failure("gen::def_constructor: params must be of Parameters type - %s", params.debug_str()); return CodeInvalid; } - CodeConstructor result = (CodeConstructor)make_code(); + CodeConstructor + result = (CodeConstructor) make_code(); if ( params ) { @@ -3828,12 +3828,12 @@ CodeConstructor def_constructor( CodeParam params, Code initializer_list, Code b { switch ( body->Type ) { - case Function_Body : - case Untyped : - break; + case Function_Body: + case Untyped: + break; - default : - log_failure( "gen::def_constructor: body must be either of Function_Body or Untyped type - %s", body.debug_str() ); + default: + log_failure("gen::def_constructor: body must be either of Function_Body or Untyped type - %s", body.debug_str()); return CodeInvalid; } @@ -3848,16 +3848,12 @@ CodeConstructor def_constructor( CodeParam params, Code initializer_list, Code b return result; } -CodeClass def_class( - StrC name, - Code body, - CodeType parent, - AccessSpec parent_access, - CodeAttributes attributes, - ModuleFlag mflags, - CodeType* interfaces, - s32 num_interfaces -) +CodeClass def_class( StrC name + , Code body + , CodeType parent, AccessSpec parent_access + , CodeAttributes attributes + , ModuleFlag mflags + , CodeType* interfaces, s32 num_interfaces ) { using namespace ECode; @@ -3875,7 +3871,8 @@ CodeClass def_class( return CodeInvalid; } - CodeClass result = (CodeClass)make_code(); + CodeClass + result = (CodeClass) make_code(); result->Name = get_cached_string( name ); result->ModuleFlags = mflags; @@ -3883,18 +3880,18 @@ CodeClass def_class( { switch ( body->Type ) { - case Class_Body : - case Untyped : - break; + case Class_Body: + case Untyped: + break; - default : - log_failure( "gen::def_class: body must be either of Class_Body or Untyped type - %s", body.debug_str() ); + default: + log_failure("gen::def_class: body must be either of Class_Body or Untyped type - %s", body.debug_str()); return CodeInvalid; } - result->Type = Class; - result->Body = body; - result->Body->Parent = result; // TODO(Ed): Review this? + result->Type = Class; + result->Body = body; + result->Body->Parent = result; // TODO(Ed): Review this? } else { @@ -3912,7 +3909,7 @@ CodeClass def_class( if ( interfaces ) { - for ( s32 idx = 0; idx < num_interfaces; idx++ ) + for (s32 idx = 0; idx < num_interfaces; idx++ ) { result.add_interface( interfaces[idx] ); } @@ -3936,12 +3933,13 @@ CodeDefine def_define( StrC name, StrC content ) } #endif - CodeDefine result = (CodeDefine)make_code(); - result->Type = Preprocess_Define; - result->Name = get_cached_string( name ); + CodeDefine + result = (CodeDefine) make_code(); + result->Type = Preprocess_Define; + result->Name = get_cached_string( name ); if ( content.Len <= 0 || content.Ptr == nullptr ) { - result->Content = get_cached_string( txt( "" ) ); + result->Content = get_cached_string( txt("") ); } else result->Content = get_cached_string( content ); @@ -3959,7 +3957,7 @@ CodeDestructor def_destructor( Code body, CodeSpecifiers specifiers ) return CodeInvalid; } - CodeDestructor result = (CodeDestructor)make_code(); + CodeDestructor result = (CodeDestructor) make_code(); if ( specifiers ) result->Specs = specifiers; @@ -3968,12 +3966,12 @@ CodeDestructor def_destructor( Code body, CodeSpecifiers specifiers ) { switch ( body->Type ) { - case Function_Body : - case Untyped : - break; + case Function_Body: + case Untyped: + break; - default : - log_failure( "gen::def_destructor: body must be either of Function_Body or Untyped type - %s", body.debug_str() ); + default: + log_failure("gen::def_destructor: body must be either of Function_Body or Untyped type - %s", body.debug_str()); return CodeInvalid; } @@ -3988,7 +3986,10 @@ CodeDestructor def_destructor( Code body, CodeSpecifiers specifiers ) return result; } -CodeEnum def_enum( StrC name, Code body, CodeType type, EnumT specifier, CodeAttributes attributes, ModuleFlag mflags ) +CodeEnum def_enum( StrC name + , Code body, CodeType type + , EnumT specifier, CodeAttributes attributes + , ModuleFlag mflags ) { using namespace ECode; @@ -4006,7 +4007,8 @@ CodeEnum def_enum( StrC name, Code body, CodeType type, EnumT specifier, CodeAtt return CodeInvalid; } - CodeEnum result = (CodeEnum)make_code(); + CodeEnum + result = (CodeEnum) make_code(); result->Name = get_cached_string( name ); result->ModuleFlags = mflags; @@ -4014,22 +4016,24 @@ CodeEnum def_enum( StrC name, Code body, CodeType type, EnumT specifier, CodeAtt { switch ( body->Type ) { - case Enum_Body : - case Untyped : - break; + case Enum_Body: + case Untyped: + break; - default : - log_failure( "gen::def_enum: body must be of Enum_Body or Untyped type %s", body.debug_str() ); + default: + log_failure( "gen::def_enum: body must be of Enum_Body or Untyped type %s", body.debug_str()); return CodeInvalid; } - result->Type = specifier == EnumClass ? Enum_Class : Enum; + result->Type = specifier == EnumClass ? + Enum_Class : Enum; result->Body = body; } else { - result->Type = specifier == EnumClass ? Enum_Class_Fwd : Enum_Fwd; + result->Type = specifier == EnumClass ? + Enum_Class_Fwd : Enum_Fwd; } if ( attributes ) @@ -4056,12 +4060,13 @@ CodeExec def_execution( StrC content ) return CodeInvalid; } - Code result = make_code(); + Code + result = make_code(); result->Type = ECode::Execution; result->Name = get_cached_string( content ); result->Content = result->Name; - return (CodeExec)result; + return (CodeExec) result; } CodeExtern def_extern_link( StrC name, Code body ) @@ -4073,16 +4078,17 @@ CodeExtern def_extern_link( StrC name, Code body ) if ( body->Type != Extern_Linkage_Body && body->Type != Untyped ) { - log_failure( "gen::def_extern_linkage: body is not of extern_linkage or untyped type %s", body->debug_str() ); + log_failure("gen::def_extern_linkage: body is not of extern_linkage or untyped type %s", body->debug_str()); return CodeInvalid; } - CodeExtern result = (CodeExtern)make_code(); - result->Type = Extern_Linkage; - result->Name = get_cached_string( name ); - result->Body = body; + CodeExtern + result = (CodeExtern)make_code(); + result->Type = Extern_Linkage; + result->Name = get_cached_string( name ); + result->Body = body; - return (CodeExtern)result; + return (CodeExtern) result; } CodeFriend def_friend( Code declaration ) @@ -4093,30 +4099,34 @@ CodeFriend def_friend( Code declaration ) switch ( declaration->Type ) { - case Class_Fwd : - case Function_Fwd : - case Operator_Fwd : - case Struct_Fwd : - case Class : - case Function : - case Operator : - case Struct : - break; + case Class_Fwd: + case Function_Fwd: + case Operator_Fwd: + case Struct_Fwd: + case Class: + case Function: + case Operator: + case Struct: + break; - default : - log_failure( "gen::def_friend: requires declartion to have class, function, operator, or struct - %s", declaration->debug_str() ); + default: + log_failure("gen::def_friend: requires declartion to have class, function, operator, or struct - %s", declaration->debug_str()); return CodeInvalid; } - CodeFriend result = (CodeFriend)make_code(); - result->Type = Friend; + CodeFriend + result = (CodeFriend) make_code(); + result->Type = Friend; result->Declaration = declaration; return result; } -CodeFn def_function( StrC name, CodeParam params, CodeType ret_type, Code body, CodeSpecifiers specifiers, CodeAttributes attributes, ModuleFlag mflags ) +CodeFn def_function( StrC name + , CodeParam params , CodeType ret_type, Code body + , CodeSpecifiers specifiers, CodeAttributes attributes + , ModuleFlag mflags ) { using namespace ECode; @@ -4146,7 +4156,8 @@ CodeFn def_function( StrC name, CodeParam params, CodeType ret_type, Code body, return CodeInvalid; } - CodeFn result = (CodeFn)make_code(); + CodeFn + result = (CodeFn) make_code(); result->Name = get_cached_string( name ); result->ModuleFlags = mflags; @@ -4154,14 +4165,14 @@ CodeFn def_function( StrC name, CodeParam params, CodeType ret_type, Code body, { switch ( body->Type ) { - case Function_Body : - case Execution : - case Untyped : + case Function_Body: + case Execution: + case Untyped: break; - default : + default: { - log_failure( "gen::def_function: body must be either of Function_Body, Execution, or Untyped type. %s", body->debug_str() ); + log_failure("gen::def_function: body must be either of Function_Body, Execution, or Untyped type. %s", body->debug_str()); return CodeInvalid; } } @@ -4203,27 +4214,31 @@ CodeInclude def_include( StrC path, bool foreign ) return CodeInvalid; } - StrC content = foreign ? to_str( str_fmt_buf( "<%.*s>", path.Len, path.Ptr ) ) : to_str( str_fmt_buf( "\"%.*s\"", path.Len, path.Ptr ) ); + StrC content = foreign ? + to_str( str_fmt_buf( "<%.*s>", path.Len, path.Ptr )) + : to_str( str_fmt_buf( "\"%.*s\"", path.Len, path.Ptr )); - Code result = make_code(); + Code + result = make_code(); result->Type = ECode::Preprocess_Include; result->Name = get_cached_string( content ); result->Content = result->Name; - return (CodeInclude)result; + return (CodeInclude) result; } CodeModule def_module( StrC name, ModuleFlag mflags ) { name_check( def_module, name ); - Code result = make_code(); + Code + result = make_code(); result->Type = ECode::Module; result->Name = get_cached_string( name ); result->Content = result->Name; result->ModuleFlags = mflags; - return (CodeModule)result; + return (CodeModule) result; } CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags ) @@ -4235,11 +4250,12 @@ CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags ) if ( body->Type != Namespace_Body && body->Type != Untyped ) { - log_failure( "gen::def_namespace: body is not of namespace or untyped type %s", body.debug_str() ); + log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body.debug_str()); return CodeInvalid; } - CodeNS result = (CodeNS)make_code(); + CodeNS + result = (CodeNS) make_code(); result->Type = Namespace; result->Name = get_cached_string( name ); result->ModuleFlags = mflags; @@ -4248,16 +4264,10 @@ CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags ) return result; } -CodeOperator def_operator( - OperatorT op, - StrC nspace, - CodeParam params_code, - CodeType ret_type, - Code body, - CodeSpecifiers specifiers, - CodeAttributes attributes, - ModuleFlag mflags -) +CodeOperator def_operator( OperatorT op, StrC nspace + , CodeParam params_code, CodeType ret_type, Code body + , CodeSpecifiers specifiers, CodeAttributes attributes + , ModuleFlag mflags ) { using namespace ECode; @@ -4282,13 +4292,14 @@ CodeOperator def_operator( char const* name = nullptr; - StrC op_str = to_str( op ); + StrC op_str = to_str( op ); if ( nspace.Len > 0 ) name = str_fmt_buf( "%.*soperator %.*s", nspace.Len, nspace.Ptr, op_str.Len, op_str.Ptr ); else name = str_fmt_buf( "operator %.*s", op_str.Len, op_str.Ptr ); - CodeOperator result = (CodeOperator)make_code(); - result->Name = get_cached_string( { str_len( name ), name } ); + CodeOperator + result = (CodeOperator) make_code(); + result->Name = get_cached_string( { str_len(name), name } ); result->ModuleFlags = mflags; result->Op = op; @@ -4296,25 +4307,27 @@ CodeOperator def_operator( { switch ( body->Type ) { - case Function_Body : - case Execution : - case Untyped : + case Function_Body: + case Execution: + case Untyped: break; - default : + default: { - log_failure( "gen::def_operator: body must be either of Function_Body, Execution, or Untyped type. %s", body->debug_str() ); + log_failure("gen::def_operator: body must be either of Function_Body, Execution, or Untyped type. %s", body->debug_str()); return CodeInvalid; } } - result->Type = check_result == OpValidateResult::Global ? Operator : Operator_Member; + result->Type = check_result == OpValidateResult::Global ? + Operator : Operator_Member; result->Body = body; } else { - result->Type = check_result == OpValidateResult::Global ? Operator_Fwd : Operator_Member_Fwd; + result->Type = check_result == OpValidateResult::Global ? + Operator_Fwd : Operator_Member_Fwd; } if ( attributes ) @@ -4325,7 +4338,7 @@ CodeOperator def_operator( result->ReturnType = ret_type; - if ( params_code ) + if (params_code) result->Params = params_code; return result; @@ -4342,9 +4355,9 @@ CodeOpCast def_operator_cast( CodeType type, Code body, CodeSpecifiers const_spe return CodeInvalid; } - CodeOpCast result = (CodeOpCast)make_code(); + CodeOpCast result = (CodeOpCast) make_code(); - if ( body ) + if (body) { result->Type = Operator_Cast; @@ -4389,9 +4402,10 @@ CodeParam def_param( CodeType type, StrC name, Code value ) return CodeInvalid; } - CodeParam result = (CodeParam)make_code(); - result->Type = Parameters; - result->Name = get_cached_string( name ); + CodeParam + result = (CodeParam) make_code(); + result->Type = Parameters; + result->Name = get_cached_string( name ); result->ValueType = type; @@ -4413,9 +4427,10 @@ CodePragma def_pragma( StrC directive ) return CodeInvalid; } - CodePragma result = (CodePragma)make_code(); - result->Type = Preprocess_Pragma; - result->Content = get_cached_string( directive ); + CodePragma + result = (CodePragma) make_code(); + result->Type = Preprocess_Pragma; + result->Content = get_cached_string( directive ); return result; } @@ -4430,23 +4445,24 @@ CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC expr ) return CodeInvalid; } - CodePreprocessCond result = (CodePreprocessCond)make_code(); - result->Content = get_cached_string( expr ); + CodePreprocessCond + result = (CodePreprocessCond) make_code(); + result->Content = get_cached_string( expr ); - switch ( type ) + switch (type) { - case EPreprocessCond::If : + case EPreprocessCond::If: result->Type = Preprocess_If; - break; - case EPreprocessCond::IfDef : + break; + case EPreprocessCond::IfDef: result->Type = Preprocess_IfDef; - break; - case EPreprocessCond::IfNotDef : + break; + case EPreprocessCond::IfNotDef: result->Type = Preprocess_IfNotDef; - break; - case EPreprocessCond::ElIf : + break; + case EPreprocessCond::ElIf: result->Type = Preprocess_ElIf; - break; + break; } return result; @@ -4454,23 +4470,20 @@ CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC expr ) CodeSpecifiers def_specifier( SpecifierT spec ) { - CodeSpecifiers result = (CodeSpecifiers)make_code(); - result->Type = ECode::Specifiers; + CodeSpecifiers + result = (CodeSpecifiers) make_code(); + result->Type = ECode::Specifiers; result.append( spec ); return result; } -CodeStruct def_struct( - StrC name, - Code body, - CodeType parent, - AccessSpec parent_access, - CodeAttributes attributes, - ModuleFlag mflags, - CodeType* interfaces, - s32 num_interfaces -) +CodeStruct def_struct( StrC name + , Code body + , CodeType parent, AccessSpec parent_access + , CodeAttributes attributes + , ModuleFlag mflags + , CodeType* interfaces, s32 num_interfaces ) { using namespace ECode; @@ -4492,7 +4505,8 @@ CodeStruct def_struct( return CodeInvalid; } - CodeStruct result = (CodeStruct)make_code(); + CodeStruct + result = (CodeStruct) make_code(); result->ModuleFlags = mflags; if ( name ) @@ -4519,7 +4533,7 @@ CodeStruct def_struct( if ( interfaces ) { - for ( s32 idx = 0; idx < num_interfaces; idx++ ) + for (s32 idx = 0; idx < num_interfaces; idx++ ) { result.add_interface( interfaces[idx] ); } @@ -4538,20 +4552,21 @@ CodeTemplate def_template( CodeParam params, Code declaration, ModuleFlag mflags return CodeInvalid; } - switch ( declaration->Type ) + switch (declaration->Type ) { - case ECode::Class : - case ECode::Function : - case ECode::Struct : - case ECode::Variable : - case ECode::Using : - break; + case ECode::Class: + case ECode::Function: + case ECode::Struct: + case ECode::Variable: + case ECode::Using: + break; - default : + default: log_failure( "gen::def_template: declaration is not of class, function, struct, variable, or using type - %s", declaration.debug_str() ); } - CodeTemplate result = (CodeTemplate)make_code(); + CodeTemplate + result = (CodeTemplate) make_code(); result->Type = ECode::Template; result->ModuleFlags = mflags; result->Params = params; @@ -4582,9 +4597,10 @@ CodeType def_type( StrC name, Code arrayexpr, CodeSpecifiers specifiers, CodeAtt return CodeInvalid; } - CodeType result = (CodeType)make_code(); - result->Name = get_cached_string( name ); - result->Type = ECode::Typename; + CodeType + result = (CodeType) make_code(); + result->Name = get_cached_string( name ); + result->Type = ECode::Typename; if ( attributes ) result->Attributes = attributes; @@ -4606,19 +4622,19 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module switch ( type->Type ) { - case Class : - case Class_Fwd : - case Enum : - case Enum_Fwd : - case Enum_Class : - case Enum_Class_Fwd : - case Function_Fwd : - case Struct : - case Struct_Fwd : - case Union : - case Typename : + case Class: + case Class_Fwd: + case Enum: + case Enum_Fwd: + case Enum_Class: + case Enum_Class_Fwd: + case Function_Fwd: + case Struct: + case Struct_Fwd: + case Union: + case Typename: break; - default : + default: log_failure( "gen::def_typedef: type was not a Class, Enum, Function Forward, Struct, Typename, or Union - %s", type.debug_str() ); return CodeInvalid; } @@ -4638,15 +4654,16 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module return CodeInvalid; } - CodeTypedef result = (CodeTypedef)make_code(); - result->Type = ECode::Typedef; - result->ModuleFlags = mflags; + CodeTypedef + result = (CodeTypedef) make_code(); + result->Type = ECode::Typedef; + result->ModuleFlags = mflags; result->UnderlyingType = type; - if ( name.Len <= 0 ) + if ( name.Len <= 0 ) { - if ( type->Type != Untyped ) + if (type->Type != Untyped) { log_failure( "gen::def_typedef: name was empty and type was not untyped (indicating its a function typedef) - %s", type.debug_str() ); return CodeInvalid; @@ -4680,7 +4697,8 @@ CodeUnion def_union( StrC name, Code body, CodeAttributes attributes, ModuleFlag return CodeInvalid; } - CodeUnion result = (CodeUnion)make_code(); + CodeUnion + result = (CodeUnion) make_code(); result->ModuleFlags = mflags; result->Type = ECode::Union; @@ -4695,7 +4713,9 @@ CodeUnion def_union( StrC name, Code body, CodeAttributes attributes, ModuleFlag return result; } -CodeUsing def_using( StrC name, CodeType type, CodeAttributes attributes, ModuleFlag mflags ) +CodeUsing def_using( StrC name, CodeType type + , CodeAttributes attributes + , ModuleFlag mflags ) { name_check( def_using, name ); null_check( def_using, type ); @@ -4714,10 +4734,11 @@ CodeUsing def_using( StrC name, CodeType type, CodeAttributes attributes, Module return CodeInvalid; } - CodeUsing result = (CodeUsing)make_code(); - result->Name = get_cached_string( name ); - result->ModuleFlags = mflags; - result->Type = ECode::Using; + CodeUsing + result = (CodeUsing) make_code(); + result->Name = get_cached_string( name ); + result->ModuleFlags = mflags; + result->Type = ECode::Using; result->UnderlyingType = type; @@ -4731,15 +4752,18 @@ CodeUsing def_using_namespace( StrC name ) { name_check( def_using_namespace, name ); - Code result = make_code(); + Code + result = make_code(); result->Name = get_cached_string( name ); result->Content = result->Name; result->Type = ECode::Using_Namespace; - return (CodeUsing)result; + return (CodeUsing) result; } -CodeVar def_variable( CodeType type, StrC name, Code value, CodeSpecifiers specifiers, CodeAttributes attributes, ModuleFlag mflags ) +CodeVar def_variable( CodeType type, StrC name, Code value + , CodeSpecifiers specifiers, CodeAttributes attributes + , ModuleFlag mflags ) { name_check( def_variable, name ); null_check( def_variable, type ); @@ -4768,12 +4792,13 @@ CodeVar def_variable( CodeType type, StrC name, Code value, CodeSpecifiers speci return CodeInvalid; } - CodeVar result = (CodeVar)make_code(); + CodeVar + result = (CodeVar) make_code(); result->Name = get_cached_string( name ); result->Type = ECode::Variable; result->ModuleFlags = mflags; - result->ValueType = type; + result->ValueType = type; if ( attributes ) result->Attributes = attributes; @@ -4788,74 +4813,68 @@ CodeVar def_variable( CodeType type, StrC name, Code value, CodeSpecifiers speci } #pragma region Helper Macros for def_**_body functions -#define def_body_start( Name_ ) \ - using namespace ECode; \ - \ - if ( num <= 0 ) \ - { \ - log_failure( "gen::" stringize( Name_ ) ": num cannot be zero or negative" ); \ - return CodeInvalid; \ - } +#define def_body_start( Name_ ) \ +using namespace ECode; \ + \ +if ( num <= 0 ) \ +{ \ + log_failure("gen::" stringize(Name_) ": num cannot be zero or negative"); \ + return CodeInvalid; \ +} -#define def_body_code_array_start( Name_ ) \ - using namespace ECode; \ - \ - if ( num <= 0 ) \ - { \ - log_failure( "gen::" stringize( Name_ ) ": num cannot be zero or negative" ); \ - return CodeInvalid; \ - } \ - \ - if ( codes == nullptr ) \ - { \ - log_failure( "gen::" stringize( Name_ ) " : Provided a null array of codes" ); \ - return CodeInvalid; \ - } +#define def_body_code_array_start( Name_ ) \ +using namespace ECode; \ + \ +if ( num <= 0 ) \ +{ \ + log_failure("gen::" stringize(Name_) ": num cannot be zero or negative"); \ + return CodeInvalid; \ +} \ + \ +if ( codes == nullptr ) \ +{ \ + log_failure("gen::" stringize(Name_)" : Provided a null array of codes"); \ + return CodeInvalid; \ +} -#pragma endregion Helper Macros for def_** _body functions +#pragma endregion Helper Macros for def_**_body functions CodeBody def_class_body( s32 num, ... ) { def_body_start( def_class_body ); - CodeBody result = (CodeBody)make_code(); + CodeBody result = ( CodeBody )make_code(); result->Type = Class_Body; va_list va; va_start( va, num ); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_class_body" - ": Provided an null entry" - ); + log_failure("gen::" + "def_class_body" + ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_CLASS_UNALLOWED_TYPES - log_failure( - "gen::" - "def_class_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_class_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -4864,41 +4883,34 @@ CodeBody def_class_body( s32 num, Code* codes ) { def_body_code_array_start( def_class_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Function_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Function_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_class_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_class_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_CLASS_UNALLOWED_TYPES - log_failure( - "gen::" - "def_class_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_class_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); + result.append(entry); + } + while (num--, num > 0); return result; } @@ -4907,41 +4919,44 @@ CodeBody def_enum_body( s32 num, ... ) { def_body_start( def_enum_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Enum_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Enum_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); if ( ! entry ) { - log_failure( "gen::def_enum_body: Provided a null entry" ); + log_failure("gen::def_enum_body: Provided a null entry"); return CodeInvalid; } if ( entry->Type != Untyped && entry->Type != Comment ) { - log_failure( "gen::def_enum_body: Entry type is not allowed - %s. Must be of untyped or comment type.", entry.debug_str() ); + log_failure("gen::def_enum_body: Entry type is not allowed - %s. Must be of untyped or comment type.", entry.debug_str() ); return CodeInvalid; } result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + } + while ( num--, num > 0 ); + va_end(va); - return (CodeBody)result; + return (CodeBody) result; } CodeBody def_enum_body( s32 num, Code* codes ) { def_body_code_array_start( def_enum_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Enum_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Enum_Body; do { @@ -4949,18 +4964,19 @@ CodeBody def_enum_body( s32 num, Code* codes ) if ( ! entry ) { - log_failure( "gen::def_enum_body: Provided a null entry" ); + log_failure("gen::def_enum_body: Provided a null entry"); return CodeInvalid; } if ( entry->Type != Untyped && entry->Type != Comment ) { - log_failure( "gen::def_enum_body: Entry type is not allowed: %s", entry.debug_str() ); + log_failure("gen::def_enum_body: Entry type is not allowed: %s", entry.debug_str() ); return CodeInvalid; } result.append( entry ); - } while ( codes++, num--, num > 0 ); + } + while ( codes++, num--, num > 0 ); return result; } @@ -4969,44 +4985,37 @@ CodeBody def_export_body( s32 num, ... ) { def_body_start( def_export_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Export_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Export_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_export_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_export_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_EXPORT_UNALLOWED_TYPES - log_failure( - "gen::" - "def_export_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_export_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -5015,41 +5024,34 @@ CodeBody def_export_body( s32 num, Code* codes ) { def_body_code_array_start( def_export_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Export_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Export_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_export_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_export_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_EXPORT_UNALLOWED_TYPES - log_failure( - "gen::" - "def_export_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_export_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); + result.append(entry); + } + while (num--, num > 0); return result; } @@ -5058,44 +5060,37 @@ CodeBody def_extern_link_body( s32 num, ... ) { def_body_start( def_extern_linkage_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Extern_Linkage_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Extern_Linkage_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_extern_linkage_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_extern_linkage_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES - log_failure( - "gen::" - "def_extern_linkage_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_extern_linkage_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -5104,42 +5099,35 @@ CodeBody def_extern_link_body( s32 num, Code* codes ) { def_body_code_array_start( def_extern_linkage_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Extern_Linkage_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Extern_Linkage_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_extern_linkage_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_extern_linkage_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES - log_failure( - "gen::" - "def_extern_linkage_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_extern_linkage_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); + result.append(entry); - } while ( num--, num > 0 ); + } + while (num--, num > 0); return result; } @@ -5148,36 +5136,38 @@ CodeBody def_function_body( s32 num, ... ) { def_body_start( def_function_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Function_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Function_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( "gen::" stringize( def_function_body ) ": Provided an null entry" ); + log_failure("gen::" stringize(def_function_body) ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES - log_failure( "gen::" stringize( def_function_body ) ": Entry type is not allowed: %s", entry.debug_str() ); - return CodeInvalid; + log_failure("gen::" stringize(def_function_body) ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -5186,40 +5176,33 @@ CodeBody def_function_body( s32 num, Code* codes ) { def_body_code_array_start( def_function_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Function_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Function_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_function_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_function_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES - log_failure( - "gen::" - "def_function_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_function_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); + result.append(entry); + } + while (num--, num > 0); return result; } @@ -5228,48 +5211,41 @@ CodeBody def_global_body( s32 num, ... ) { def_body_start( def_global_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Global_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Global_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_global_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_global_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { - case Global_Body : - result.append( entry.cast() ); + case Global_Body: + result.append( entry.cast() ) ; continue; - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES - log_failure( - "gen::" - "def_global_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return ( *Code::Invalid.ast ); + GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES + log_failure("gen::" "def_global_body" ": Entry type is not allowed: %s", entry.debug_str()); + return (*Code::Invalid.ast); - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -5278,45 +5254,38 @@ CodeBody def_global_body( s32 num, Code* codes ) { def_body_code_array_start( def_global_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Global_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Global_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_global_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_global_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { - case Global_Body : - result.append( entry.cast() ); + case Global_Body: + result.append( entry.cast() ) ; continue; - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES - log_failure( - "gen::" - "def_global_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); + GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES + log_failure("gen::" "def_global_body" ": Entry type is not allowed: %s", entry.debug_str()); return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); + result.append(entry); + } + while (num--, num > 0); return result; } @@ -5325,44 +5294,37 @@ CodeBody def_namespace_body( s32 num, ... ) { def_body_start( def_namespace_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Namespace_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Namespace_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_namespace_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_namespace_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES - log_failure( - "gen::" - "def_namespace_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_namespace_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -5371,41 +5333,33 @@ CodeBody def_namespace_body( s32 num, Code* codes ) { def_body_code_array_start( def_namespace_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Global_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Global_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_namespace_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_namespace_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES - log_failure( - "gen::" - "def_namespace_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_namespace_body" ": Entry type is not allowed: %s", entry.debug_str() ); + return CodeInvalid; - default : - break; + default: break; } - result.append( entry ); - } while ( num--, num > 0 ); + result.append(entry); + } + while (num--, num > 0); return result; } @@ -5415,9 +5369,9 @@ CodeParam def_params( s32 num, ... ) def_body_start( def_params ); va_list va; - va_start( va, num ); + va_start(va, num); - Code_POD pod = va_arg( va, Code_POD ); + Code_POD pod = va_arg(va, Code_POD); CodeParam param = pcast( CodeParam, pod ); null_check( def_params, param ); @@ -5428,11 +5382,11 @@ CodeParam def_params( s32 num, ... ) return CodeInvalid; } - CodeParam result = (CodeParam)param.duplicate(); + CodeParam result = (CodeParam) param.duplicate(); - while ( --num ) + while ( -- num ) { - pod = va_arg( va, Code_POD ); + pod = va_arg(va, Code_POD); param = pcast( CodeParam, pod ); if ( param->Type != Parameters ) @@ -5443,7 +5397,7 @@ CodeParam def_params( s32 num, ... ) result.append( param ); } - va_end( va ); + va_end(va); return result; } @@ -5452,33 +5406,34 @@ CodeParam def_params( s32 num, CodeParam* codes ) { def_body_code_array_start( def_params ); -#define check_current() \ +# define check_current() \ if ( current.ast == nullptr ) \ { \ - log_failure( "gen::def_params: Provide a null code in codes array" ); \ + log_failure("gen::def_params: Provide a null code in codes array"); \ return CodeInvalid; \ } \ - \ - if ( current->Type != Parameters ) \ + \ + if (current->Type != Parameters ) \ { \ - log_failure( "gen::def_params: Code in coes array is not of paramter type - %s", current.debug_str() ); \ + log_failure("gen::def_params: Code in coes array is not of paramter type - %s", current.debug_str() ); \ return CodeInvalid; \ } - CodeParam current = (CodeParam)codes->duplicate(); + CodeParam current = (CodeParam) codes->duplicate(); check_current(); - CodeParam result = (CodeParam)make_code(); + CodeParam + result = (CodeParam) make_code(); result->Name = current->Name; result->Type = current->Type; result->ValueType = current->ValueType; - while ( codes++, current = *codes, num--, num > 0 ) + while( codes++, current = * codes, num--, num > 0 ) { check_current(); result.append( current ); } -#undef check_current +# undef check_current return result; } @@ -5487,28 +5442,30 @@ CodeSpecifiers def_specifiers( s32 num, ... ) { if ( num <= 0 ) { - log_failure( "gen::def_specifiers: num cannot be zero or less" ); + log_failure("gen::def_specifiers: num cannot be zero or less"); return CodeInvalid; } if ( num > AST::ArrSpecs_Cap ) { - log_failure( "gen::def_specifiers: num of speciifers to define AST larger than AST specicifier capacity - %d", num ); + log_failure("gen::def_specifiers: num of speciifers to define AST larger than AST specicifier capacity - %d", num); return CodeInvalid; } - CodeSpecifiers result = (CodeSpecifiers)make_code(); - result->Type = ECode::Specifiers; + CodeSpecifiers + result = (CodeSpecifiers) make_code(); + result->Type = ECode::Specifiers; va_list va; - va_start( va, num ); + va_start(va, num); do { - SpecifierT type = (SpecifierT)va_arg( va, int ); + SpecifierT type = (SpecifierT)va_arg(va, int); result.append( type ); - } while ( --num, num ); - va_end( va ); + } + while ( --num, num ); + va_end(va); return result; } @@ -5517,25 +5474,27 @@ CodeSpecifiers def_specifiers( s32 num, SpecifierT* specs ) { if ( num <= 0 ) { - log_failure( "gen::def_specifiers: num cannot be zero or less" ); + log_failure("gen::def_specifiers: num cannot be zero or less"); return CodeInvalid; } if ( num > AST::ArrSpecs_Cap ) { - log_failure( "gen::def_specifiers: num of speciifers to define AST larger than AST specicifier capacity - %d", num ); + log_failure("gen::def_specifiers: num of speciifers to define AST larger than AST specicifier capacity - %d", num); return CodeInvalid; } - CodeSpecifiers result = (CodeSpecifiers)make_code(); - result->Type = ECode::Specifiers; + CodeSpecifiers + result = (CodeSpecifiers) make_code(); + result->Type = ECode::Specifiers; - s32 idx = 0; + s32 idx = 0; do { result.append( specs[idx] ); idx++; - } while ( --num, num ); + } + while ( --num, num ); return result; } @@ -5544,44 +5503,37 @@ CodeBody def_struct_body( s32 num, ... ) { def_body_start( def_struct_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Struct_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Struct_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); - Code entry = pcast( Code, pod ); + Code_POD pod = va_arg(va, Code_POD); + Code entry = pcast(Code, pod); - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_struct_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_struct_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_STRUCT_UNALLOWED_TYPES - log_failure( - "gen::" - "def_struct_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_struct_body" ": Entry type is not allowed: %s", entry.debug_str()); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + result.append(entry); + } + while (num--, num > 0); + va_end(va); return result; } @@ -5590,41 +5542,34 @@ CodeBody def_struct_body( s32 num, Code* codes ) { def_body_code_array_start( def_struct_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Struct_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Struct_Body; do { Code entry = *codes; codes++; - if ( ! entry ) + if (!entry) { - log_failure( - "gen::" - "def_struct_body" - ": Provided an null entry" - ); + log_failure("gen::" "def_struct_body" ": Provided an null entry"); return CodeInvalid; } - switch ( entry->Type ) + switch (entry->Type) { GEN_AST_BODY_STRUCT_UNALLOWED_TYPES - log_failure( - "gen::" - "def_struct_body" - ": Entry type is not allowed: %s", - entry.debug_str() - ); - return CodeInvalid; + log_failure("gen::" "def_struct_body" ": Entry type is not allowed: %s", entry.debug_str() ); + return CodeInvalid; - default : - break; + default: + break; } - result.append( entry ); - } while ( num--, num > 0 ); + result.append(entry); + } + while (num--, num > 0); return result; } @@ -5633,31 +5578,33 @@ CodeBody def_union_body( s32 num, ... ) { def_body_start( def_union_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Union_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Union_Body; va_list va; - va_start( va, num ); + va_start(va, num); do { - Code_POD pod = va_arg( va, Code_POD ); + Code_POD pod = va_arg(va, Code_POD); Code entry = pcast( Code, pod ); if ( ! entry ) { - log_failure( "gen::def_union_body: Provided a null entry" ); + log_failure("gen::def_union_body: Provided a null entry"); return CodeInvalid; } if ( entry->Type != Untyped && entry->Type != Comment ) { - log_failure( "gen::def_union_body: Entry type is not allowed - %s. Must be of untyped or comment type.", entry.debug_str() ); + log_failure("gen::def_union_body: Entry type is not allowed - %s. Must be of untyped or comment type.", entry.debug_str() ); return CodeInvalid; } result.append( entry ); - } while ( num--, num > 0 ); - va_end( va ); + } + while ( num--, num > 0 ); + va_end(va); return result; } @@ -5666,8 +5613,9 @@ CodeBody def_union_body( s32 num, CodeUnion* codes ) { def_body_code_array_start( def_union_body ); - CodeBody result = (CodeBody)make_code(); - result->Type = Union_Body; + CodeBody + result = (CodeBody) make_code(); + result->Type = Union_Body; do { @@ -5675,27 +5623,28 @@ CodeBody def_union_body( s32 num, CodeUnion* codes ) if ( ! entry ) { - log_failure( "gen::def_union_body: Provided a null entry" ); + log_failure("gen::def_union_body: Provided a null entry"); return CodeInvalid; } if ( entry->Type != Untyped && entry->Type != Comment ) { - log_failure( "gen::def_union_body: Entry type is not allowed: %s", entry.debug_str() ); + log_failure("gen::def_union_body: Entry type is not allowed: %s", entry.debug_str() ); return CodeInvalid; } result.append( entry ); - } while ( codes++, num--, num > 0 ); + } + while ( codes++, num--, num > 0 ); - return (CodeBody)result; + return (CodeBody) result; } -#undef name_check -#undef null_check -#undef null_or_invalid_check -#undef def_body_start -#undef def_body_code_array_start +# undef name_check +# undef null_check +# undef null_or_invalid_check +# undef def_body_start +# undef def_body_code_array_start #pragma endregion Upfront @@ -5705,11 +5654,11 @@ namespace parser { namespace ETokType { -#define GEN_DEFINE_ATTRIBUTE_TOKENS \ - Entry( Attribute_API_Export, "GEN_API_Export_Code" ) Entry( Attribute_API_Import, "GEN_API_Import_Code" ) \ - Entry( Attribute_UE_DEPRECATED, "UE_DEPRECATED" ) Entry( Attribute_UMG_API, "UMG_API" ) Entry( Attribute_COREUOBJECT_API, "COREUOBJECT_API" ) \ - Entry( Attribute_ENGINE_API, "ENGINE_API" ) Entry( Attribute_GAMEPLAYABILITIES_API, "GAMEPLAYABILITIES_API" ) \ - Entry( Attribute_GASA_API, "GASA_API" ) +#define GEN_DEFINE_ATTRIBUTE_TOKENS \ + Entry( Attribute_API_Export, "GEN_API_Export_Code" ) Entry( Attribute_API_Import, "GEN_API_Import_Code" ) \ + Entry( Attribute_COREUOBJECT_API, "COREUOBJECT_API" ) Entry( Attribute_ENGINE_API, "ENGINE_API" ) \ + Entry( Attribute_GAMEPLAYABILITIES_API, "GAMEPLAYABILITIES_API" ) Entry( Attribute_UMG_API, "UMG_API" ) \ + Entry( Attribute_UE_DEPRECATED, "UE_DEPRECATED" ) enum Type : u32 { @@ -5810,12 +5759,11 @@ namespace parser __Attributes_Start, Attribute_API_Export, Attribute_API_Import, - Attribute_UE_DEPRECATED, - Attribute_UMG_API, Attribute_COREUOBJECT_API, Attribute_ENGINE_API, Attribute_GAMEPLAYABILITIES_API, - Attribute_GASA_API, + Attribute_UMG_API, + Attribute_UE_DEPRECATED, NumTokens }; @@ -5919,12 +5867,11 @@ namespace parser { sizeof( "__attrib_start__" ), "__attrib_start__" }, { sizeof( "GEN_API_Export_Code" ), "GEN_API_Export_Code" }, { sizeof( "GEN_API_Import_Code" ), "GEN_API_Import_Code" }, - { sizeof( "UE_DEPRECATED" ), "UE_DEPRECATED" }, - { sizeof( "UMG_API" ), "UMG_API" }, { sizeof( "COREUOBJECT_API" ), "COREUOBJECT_API" }, { sizeof( "ENGINE_API" ), "ENGINE_API" }, { sizeof( "GAMEPLAYABILITIES_API" ), "GAMEPLAYABILITIES_API" }, - { sizeof( "GASA_API" ), "GASA_API" }, + { sizeof( "UMG_API" ), "UMG_API" }, + { sizeof( "UE_DEPRECATED" ), "UE_DEPRECATED" }, }; return lookup[type]; } @@ -5952,183 +5899,186 @@ namespace parser } // namespace parser -namespace parser +namespace parser { + +enum TokFlags : u32 { + TF_Operator = bit(0), + TF_Assign = bit(1), + TF_Preprocess = bit(2), + TF_Preprocess_Cond = bit(3), + TF_Attribute = bit(6), + TF_AccessOperator = bit( 7 ), + TF_AccessSpecifier = bit( 8 ), + TF_Specifier = bit( 9 ), + TF_EndDefinition = bit( 10 ), // Either ; or } + TF_Formatting = bit( 11 ), + TF_Literal = bit( 12 ), - enum TokFlags : u32 + TF_Null = 0, +}; + +struct Token +{ + char const* Text; + sptr Length; + TokType Type; + s32 Line; + s32 Column; + u32 Flags; + + operator bool() { - TF_Operator = bit( 0 ), - TF_Assign = bit( 1 ), - TF_Preprocess = bit( 2 ), - TF_Preprocess_Cond = bit( 3 ), - TF_Attribute = bit( 6 ), - TF_AccessOperator = bit( 7 ), - TF_AccessSpecifier = bit( 8 ), - TF_Specifier = bit( 9 ), - TF_EndDefinition = bit( 10 ), // Either ; or } - TF_Formatting = bit( 11 ), - TF_Literal = bit( 12 ), + return Text && Length && Type != TokType::Invalid; + } - TF_Null = 0, - }; - - struct Token + operator StrC() { - char const* Text; - sptr Length; - TokType Type; - s32 Line; - s32 Column; - u32 Flags; + return { Length, Text }; + } - operator bool() - { - return Text && Length && Type != TokType::Invalid; - } - - operator StrC() - { - return { Length, Text }; - } - - bool is_access_operator() - { - return bitfield_is_equal( u32, Flags, TF_AccessOperator ); - } - - bool is_access_specifier() - { - return bitfield_is_equal( u32, Flags, TF_AccessSpecifier ); - } - - bool is_attribute() - { - return bitfield_is_equal( u32, Flags, TF_Attribute ); - } - - bool is_operator() - { - return bitfield_is_equal( u32, Flags, TF_Operator ); - } - - bool is_preprocessor() - { - return bitfield_is_equal( u32, Flags, TF_Preprocess ); - } - - bool is_preprocess_cond() - { - return bitfield_is_equal( u32, Flags, TF_Preprocess_Cond ); - } - - bool is_specifier() - { - return bitfield_is_equal( u32, Flags, TF_Specifier ); - } - - bool is_end_definition() - { - return bitfield_is_equal( u32, Flags, TF_EndDefinition ); - } - - AccessSpec to_access_specifier() - { - return scast( AccessSpec, Type ); - } - - String to_string() - { - String result = String::make_reserve( GlobalAllocator, kilobytes( 4 ) ); - - StrC type_str = ETokType::to_str( Type ); - - result.append_fmt( "Line: %d Column: %d, Type: %.*s Content: %.*s", Line, Column, type_str.Len, type_str.Ptr, Length, Text ); - - return result; - } - }; - - constexpr Token NullToken { nullptr, 0, TokType::Invalid, false, 0, TF_Null }; - - struct TokArray + bool is_access_operator() { - Array Arr; - s32 Idx; + return bitfield_is_equal( u32, Flags, TF_AccessOperator ); + } - bool __eat( TokType type ); + bool is_access_specifier() + { + return bitfield_is_equal( u32, Flags, TF_AccessSpecifier ); + } - Token& current( bool skip_formatting = true ) + bool is_attribute() + { + return bitfield_is_equal( u32, Flags, TF_Attribute ); + } + + bool is_operator() + { + return bitfield_is_equal( u32, Flags, TF_Operator ); + } + + bool is_preprocessor() + { + return bitfield_is_equal( u32, Flags, TF_Preprocess ); + } + + bool is_preprocess_cond() + { + return bitfield_is_equal( u32, Flags, TF_Preprocess_Cond ); + } + + bool is_specifier() + { + return bitfield_is_equal( u32, Flags, TF_Specifier ); + } + + bool is_end_definition() + { + return bitfield_is_equal( u32, Flags, TF_EndDefinition ); + } + + AccessSpec to_access_specifier() + { + return scast(AccessSpec, Type); + } + + String to_string() + { + String result = String::make_reserve( GlobalAllocator, kilobytes(4) ); + + StrC type_str = ETokType::to_str( Type ); + + result.append_fmt( "Line: %d Column: %d, Type: %.*s Content: %.*s" + , Line, Column + , type_str.Len, type_str.Ptr + , Length, Text + ); + + return result; + } +}; + +constexpr Token NullToken { nullptr, 0, TokType::Invalid, false, 0, TF_Null }; + +struct TokArray +{ + Array Arr; + s32 Idx; + + bool __eat( TokType type ); + + Token& current( bool skip_formatting = true ) + { + if ( skip_formatting ) { - if ( skip_formatting ) - { - while ( Arr[Idx].Type == TokType::NewLine || Arr[Idx].Type == TokType::Comment ) - Idx++; - } - - return Arr[Idx]; + while ( Arr[Idx].Type == TokType::NewLine || Arr[Idx].Type == TokType::Comment ) + Idx++; } - Token& previous( bool skip_formatting = false ) + return Arr[Idx]; + } + + Token& previous( bool skip_formatting = false ) + { + s32 idx = this->Idx; + + if ( skip_formatting ) { - s32 idx = this->Idx; + while ( Arr[idx].Type == TokType::NewLine ) + idx--; - if ( skip_formatting ) - { - while ( Arr[idx].Type == TokType::NewLine ) - idx--; - - return Arr[idx]; - } - - return Arr[idx - 1]; + return Arr[idx]; } - Token& next( bool skip_formatting = false ) + return Arr[idx - 1]; + } + + Token& next( bool skip_formatting = false ) + { + s32 idx = this->Idx; + + if ( skip_formatting ) { - s32 idx = this->Idx; - - if ( skip_formatting ) - { - while ( Arr[idx].Type == TokType::NewLine ) - idx++; - - return Arr[idx + 1]; - } + while ( Arr[idx].Type == TokType::NewLine ) + idx++; return Arr[idx + 1]; } - Token& operator[]( s32 idx ) - { - return Arr[idx]; - } - }; - - global Arena_256KB defines_map_arena; - global HashTable defines; - global Array Tokens; - -#define current ( *scanner ) - -#define move_forward() \ - { \ - if ( current == '\n' ) \ - { \ - line++; \ - column = 1; \ - } \ - else \ - { \ - column++; \ - } \ - left--; \ - scanner++; \ + return Arr[idx + 1]; } -#define SkipWhitespace() \ - while ( left && char_is_space( current ) ) \ - { \ - move_forward(); \ + Token& operator []( s32 idx ) + { + return Arr[idx]; + } +}; + +global Arena_256KB defines_map_arena; +global HashTable defines; +global Array Tokens; + +#define current ( * scanner ) + +#define move_forward() \ + { \ + if ( current == '\n' ) \ + { \ + line++; \ + column = 1; \ + } \ + else \ + { \ + column++; \ + } \ + left--; \ + scanner++; \ + } + +#define SkipWhitespace() \ + while ( left && char_is_space( current ) ) \ + { \ + move_forward(); \ } #define end_line() \ @@ -6147,195 +6097,48 @@ namespace parser { \ move_forward(); \ } \ - } while ( 0 ) + } \ + while (0) - enum +enum +{ + Lex_Continue, + Lex_ReturnNull, +}; + +FORCEINLINE +s32 lex_preprocessor_directive( + StrC& content + , s32& left + , char const*& scanner + , s32& line + , s32& column + , HashTable& defines + , Token& token ) +{ + char const* hash = scanner; + Tokens.append( { hash, 1, TokType::Preprocess_Hash, line, column, TF_Preprocess } ); + + move_forward(); + SkipWhitespace(); + + token.Text = scanner; + while (left && ! char_is_space(current) ) { - Lex_Continue, - Lex_ReturnNull, - }; - - FORCEINLINE - s32 lex_preprocessor_directive( StrC& content, s32& left, char const*& scanner, s32& line, s32& column, HashTable& defines, Token& token ) - { - char const* hash = scanner; - Tokens.append( { hash, 1, TokType::Preprocess_Hash, line, column, TF_Preprocess } ); - move_forward(); - SkipWhitespace(); + token.Length++; + } - token.Text = scanner; - while ( left && ! char_is_space( current ) ) - { - move_forward(); - token.Length++; - } + token.Type = ETokType::to_type( token ); - token.Type = ETokType::to_type( token ); - - bool is_preprocessor = token.Type >= TokType::Preprocess_Define && token.Type <= TokType::Preprocess_Pragma; - if ( ! is_preprocessor ) - { - token.Type = TokType::Preprocess_Unsupported; - - // Its an unsupported directive, skip it - s32 within_string = false; - s32 within_char = false; - while ( left ) - { - if ( current == '"' && ! within_char ) - within_string ^= true; - - if ( current == '\'' && ! within_string ) - within_char ^= true; - - if ( current == '\\' && ! within_string && ! within_char ) - { - move_forward(); - token.Length++; - - if ( current == '\r' ) - { - move_forward(); - token.Length++; - } - - if ( current == '\n' ) - { - move_forward(); - token.Length++; - continue; - } - else - { - log_failure( - "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" - " in preprocessor directive (%d, %d)\n%.100s", - current, - line, - column, - token.Line, - token.Column, - token.Text - ); - break; - } - } - - if ( current == '\r' ) - { - move_forward(); - token.Length++; - } - - if ( current == '\n' ) - { - move_forward(); - token.Length++; - break; - } - - move_forward(); - token.Length++; - } - - token.Length = token.Length + token.Text - hash; - token.Text = hash; - Tokens.append( token ); - return Lex_Continue; // Skip found token, its all handled here. - } - - if ( token.Type == TokType::Preprocess_Else || token.Type == TokType::Preprocess_EndIf ) - { - token.Flags |= TF_Preprocess_Cond; - Tokens.append( token ); - end_line(); - return Lex_Continue; - } - else if ( token.Type >= TokType::Preprocess_If && token.Type <= TokType::Preprocess_ElIf ) - { - token.Flags |= TF_Preprocess_Cond; - } - - Tokens.append( token ); - - SkipWhitespace(); - - if ( token.Type == TokType::Preprocess_Define ) - { - Token name = { scanner, 0, TokType::Identifier, line, column, TF_Preprocess }; - - name.Text = scanner; - name.Length = 1; - move_forward(); - - while ( left && ( char_is_alphanumeric( current ) || current == '_' ) ) - { - move_forward(); - name.Length++; - } - - if ( left && current == '(' ) - { - move_forward(); - name.Length++; - } - - Tokens.append( name ); - - u64 key = crc32( name.Text, name.Length ); - defines.set( key, name ); - } - - Token preprocess_content = { scanner, 0, TokType::Preprocess_Content, line, column, TF_Preprocess }; - - if ( token.Type == TokType::Preprocess_Include ) - { - preprocess_content.Type = TokType::String; - - if ( current != '"' && current != '<' ) - { - String directive_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 80, left + preprocess_content.Length ), token.Text ); - - log_failure( - "gen::Parser::lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s", - current, - preprocess_content.Line, - preprocess_content.Column, - directive_str.Data - ); - return Lex_ReturnNull; - } - move_forward(); - preprocess_content.Length++; - - while ( left && current != '"' && current != '>' ) - { - move_forward(); - preprocess_content.Length++; - } - - move_forward(); - preprocess_content.Length++; - - if ( current == '\r' && scanner[1] == '\n' ) - { - move_forward(); - move_forward(); - } - else if ( current == '\n' ) - { - move_forward(); - } - - Tokens.append( preprocess_content ); - return Lex_Continue; // Skip found token, its all handled here. - } + bool is_preprocessor = token.Type >= TokType::Preprocess_Define && token.Type <= TokType::Preprocess_Pragma; + if ( ! is_preprocessor ) + { + token.Type = TokType::Preprocess_Unsupported; + // Its an unsupported directive, skip it s32 within_string = false; s32 within_char = false; - - // SkipWhitespace(); while ( left ) { if ( current == '"' && ! within_char ) @@ -6347,36 +6150,26 @@ namespace parser if ( current == '\\' && ! within_string && ! within_char ) { move_forward(); - preprocess_content.Length++; + token.Length++; if ( current == '\r' ) { move_forward(); - preprocess_content.Length++; + token.Length++; } if ( current == '\n' ) { move_forward(); - preprocess_content.Length++; + token.Length++; continue; } else { - String directive_str = String::make_length( GlobalAllocator, token.Text, token.Length ); - String content_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 400, left + preprocess_content.Length ), preprocess_content.Text ); - - log_failure( - "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" - " in preprocessor directive '%s' (%d, %d)\n%s", - current, - line, - column, - directive_str, - preprocess_content.Line, - preprocess_content.Column, - content_str - ); + log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" + " in preprocessor directive (%d, %d)\n%.100s" + , current, line, column + , token.Line, token.Column, token.Text ); break; } } @@ -6384,1135 +6177,1358 @@ namespace parser if ( current == '\r' ) { move_forward(); + token.Length++; } if ( current == '\n' ) { move_forward(); + token.Length++; break; } + move_forward(); + token.Length++; + } + + token.Length = token.Length + token.Text - hash; + token.Text = hash; + Tokens.append( token ); + return Lex_Continue; // Skip found token, its all handled here. + } + + if ( token.Type == TokType::Preprocess_Else || token.Type == TokType::Preprocess_EndIf ) + { + token.Flags |= TF_Preprocess_Cond; + Tokens.append( token ); + end_line(); + return Lex_Continue; + } + else if ( token.Type >= TokType::Preprocess_If && token.Type <= TokType::Preprocess_ElIf ) + { + token.Flags |= TF_Preprocess_Cond; + } + + Tokens.append( token ); + + SkipWhitespace(); + + if ( token.Type == TokType::Preprocess_Define ) + { + Token name = { scanner, 0, TokType::Identifier, line, column, TF_Preprocess }; + + name.Text = scanner; + name.Length = 1; + move_forward(); + + while ( left && ( char_is_alphanumeric(current) || current == '_' ) ) + { + move_forward(); + name.Length++; + } + + if ( left && current == '(' ) + { + move_forward(); + name.Length++; + } + + Tokens.append( name ); + + u64 key = crc32( name.Text, name.Length ); + defines.set( key, name ); + } + + Token preprocess_content = { scanner, 0, TokType::Preprocess_Content, line, column, TF_Preprocess }; + + if ( token.Type == TokType::Preprocess_Include ) + { + preprocess_content.Type = TokType::String; + + if ( current != '"' && current != '<' ) + { + String directive_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 80, left + preprocess_content.Length ), token.Text ); + + log_failure( "gen::Parser::lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s" + , current + , preprocess_content.Line + , preprocess_content.Column + , directive_str.Data + ); + return Lex_ReturnNull; + } + move_forward(); + preprocess_content.Length++; + + while ( left && current != '"' && current != '>' ) + { move_forward(); preprocess_content.Length++; } + move_forward(); + preprocess_content.Length++; + + if ( current == '\r' && scanner[1] == '\n' ) + { + move_forward(); + move_forward(); + } + else if ( current == '\n' ) + { + move_forward(); + } + Tokens.append( preprocess_content ); - return Lex_Continue; // Skip found token, its all handled here. + return Lex_Continue; // Skip found token, its all handled here. } - FORCEINLINE - void lex_found_token( StrC& content, s32& left, char const*& scanner, s32& line, s32& column, HashTable& defines, Token& token ) + s32 within_string = false; + s32 within_char = false; + + // SkipWhitespace(); + while ( left ) { - if ( token.Type != TokType::Invalid ) + if ( current == '"' && ! within_char ) + within_string ^= true; + + if ( current == '\'' && ! within_string ) + within_char ^= true; + + if ( current == '\\' && ! within_string && ! within_char ) { - Tokens.append( token ); - return; - } + move_forward(); + preprocess_content.Length++; - TokType type = ETokType::to_type( token ); - - if ( type <= TokType::Access_Public && type >= TokType::Access_Private ) - { - token.Flags |= TF_AccessSpecifier; - } - - if ( type > TokType::__Attributes_Start ) - { - token.Flags |= TF_Attribute; - } - - if ( type == ETokType::Decl_Extern_Linkage ) - { - SkipWhitespace(); - - if ( current != '"' ) - { - type = ETokType::Spec_Extern; - token.Flags |= TF_Specifier; - } - - token.Type = type; - Tokens.append( token ); - return; - } - - if ( ( type <= TokType::Star && type >= TokType::Spec_Alignas ) || type == TokType::Ampersand || type == TokType::Ampersand_DBL ) - { - token.Type = type; - token.Flags |= TF_Specifier; - Tokens.append( token ); - return; - } - - - if ( type != TokType::Invalid ) - { - token.Type = type; - Tokens.append( token ); - return; - } - - u64 key = 0; - if ( current == '(' ) - key = crc32( token.Text, token.Length + 1 ); - else - key = crc32( token.Text, token.Length ); - - StrC* define = defines.get( key ); - if ( define ) - { - token.Type = TokType::Preprocess_Macro; - - // Want to ignore any arguments the define may have as they can be execution expressions. - if ( left && current == '(' ) + if ( current == '\r' ) { move_forward(); - token.Length++; - - s32 level = 0; - while ( left && ( current != ')' || level > 0 ) ) - { - if ( current == '(' ) - level++; - - else if ( current == ')' && level > 0 ) - level--; - - move_forward(); - token.Length++; - } - - move_forward(); - token.Length++; + preprocess_content.Length++; } - if ( current == '\r' && scanner[1] == '\n' ) + if ( current == '\n' ) { move_forward(); + preprocess_content.Length++; + continue; } - else if ( current == '\n' ) + else { - move_forward(); + String directive_str = String::make_length( GlobalAllocator, token.Text, token.Length ); + String content_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 400, left + preprocess_content.Length ), preprocess_content.Text ); + + log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" + " in preprocessor directive '%s' (%d, %d)\n%s" + , current, line, column + , directive_str, preprocess_content.Line, preprocess_content.Column + , content_str ); + break; } } - else + + if ( current == '\r' ) { - token.Type = TokType::Identifier; + move_forward(); } + if ( current == '\n' ) + { + move_forward(); + break; + } + + move_forward(); + preprocess_content.Length++; + } + + Tokens.append( preprocess_content ); + return Lex_Continue; // Skip found token, its all handled here. +} + +FORCEINLINE +void lex_found_token( StrC& content + , s32& left + , char const*& scanner + , s32& line + , s32& column + , HashTable& defines + , Token& token ) +{ + if ( token.Type != TokType::Invalid ) + { Tokens.append( token ); + return; } - neverinline - // TokArray lex( Array tokens, StrC content ) - TokArray - lex( StrC content ) + TokType type = ETokType::to_type( token ); + + if (type <= TokType::Access_Public && type >= TokType::Access_Private ) { - s32 left = content.Len; - char const* scanner = content.Ptr; + token.Flags |= TF_AccessSpecifier; + } - char const* word = scanner; - s32 word_length = 0; - - s32 line = 1; - s32 column = 1; + if ( type > TokType::__Attributes_Start ) + { + token.Flags |= TF_Attribute; + } + if ( type == ETokType::Decl_Extern_Linkage ) + { SkipWhitespace(); - if ( left <= 0 ) + + if ( current != '"' ) { - log_failure( "gen::lex: no tokens found (only whitespace provided)" ); - return { { nullptr }, 0 }; + type = ETokType::Spec_Extern; + token.Flags |= TF_Specifier; } - for ( StringCached entry : PreprocessorDefines ) + token.Type = type; + Tokens.append( token ); + return; + } + + if ( ( type <= TokType::Star && type >= TokType::Spec_Alignas) + || type == TokType::Ampersand + || type == TokType::Ampersand_DBL ) + { + token.Type = type; + token.Flags |= TF_Specifier; + Tokens.append( token ); + return; + } + + + if ( type != TokType::Invalid ) + { + token.Type = type; + Tokens.append( token ); + return; + } + + u64 key = 0; + if ( current == '(') + key = crc32( token.Text, token.Length + 1 ); + else + key = crc32( token.Text, token.Length ); + + StrC* define = defines.get( key ); + if ( define ) + { + token.Type = TokType::Preprocess_Macro; + + // Want to ignore any arguments the define may have as they can be execution expressions. + if ( left && current == '(' ) { - s32 length = 0; - char const* scanner = entry.Data; - while ( entry.length() > length && ( char_is_alphanumeric( *scanner ) || *scanner == '_' ) ) + move_forward(); + token.Length++; + + s32 level = 0; + while ( left && (current != ')' || level > 0) ) { - scanner++; - length++; - } - if ( scanner[0] == '(' ) - { - length++; + if ( current == '(' ) + level++; + + else if ( current == ')' && level > 0 ) + level--; + + move_forward(); + token.Length++; } - u64 key = crc32( entry.Data, length ); - defines.set( key, entry ); + move_forward(); + token.Length++; } - Tokens.clear(); - - while ( left ) + if ( current == '\r' && scanner[1] == '\n' ) { -#if 0 + move_forward(); + } + else if ( current == '\n' ) + { + move_forward(); + } + } + else + { + token.Type = TokType::Identifier; + } + + Tokens.append( token ); +} + + +neverinline +// TokArray lex( Array tokens, StrC content ) +TokArray lex( StrC content ) +{ + s32 left = content.Len; + char const* scanner = content.Ptr; + + char const* word = scanner; + s32 word_length = 0; + + s32 line = 1; + s32 column = 1; + + SkipWhitespace(); + if ( left <= 0 ) + { + log_failure( "gen::lex: no tokens found (only whitespace provided)" ); + return { { nullptr }, 0 }; + } + + for ( StringCached entry : PreprocessorDefines ) + { + s32 length = 0; + char const* scanner = entry.Data; + while ( entry.length() > length && (char_is_alphanumeric( *scanner ) || *scanner == '_') ) + { + scanner++; + length ++; + } + if ( scanner[0] == '(' ) + { + length++; + } + + u64 key = crc32( entry.Data, length ); + defines.set( key, entry ); + } + + Tokens.clear(); + + while (left ) + { + #if 0 if (Tokens.num()) { log_fmt("\nLastTok: %S", Tokens.back().to_string()); } -#endif + #endif - Token token = { scanner, 0, TokType::Invalid, line, column, TF_Null }; + Token token = { scanner, 0, TokType::Invalid, line, column, TF_Null }; - bool is_define = false; + bool is_define = false; - if ( column == 1 ) + if ( column == 1 ) + { + if ( current == '\r') { - if ( current == '\r' ) - { - move_forward(); - token.Length = 1; - } - - if ( current == '\n' ) - { - move_forward(); - - token.Type = TokType::NewLine; - token.Length++; - - Tokens.append( token ); - continue; - } + move_forward(); + token.Length = 1; } - token.Length = 0; - - SkipWhitespace(); - if ( left <= 0 ) - break; - - switch ( current ) + if ( current == '\n' ) { - case '#' : - { - s32 result = lex_preprocessor_directive( content, left, scanner, line, column, defines, token ); - switch ( result ) - { - case Lex_Continue : - continue; + move_forward(); - case Lex_ReturnNull : - return { { nullptr }, 0 }; - } + token.Type = TokType::NewLine; + token.Length++; + + Tokens.append( token ); + continue; + } + } + + token.Length = 0; + + SkipWhitespace(); + if ( left <= 0 ) + break; + + switch ( current ) + { + case '#': + { + s32 result = lex_preprocessor_directive( content, left, scanner, line, column, defines, token ); + switch ( result ) + { + case Lex_Continue: + continue; + + case Lex_ReturnNull: + return { { nullptr }, 0 }; } - case '.' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Access_MemberSymbol; - token.Flags = TF_AccessOperator; - - if ( left ) - { - move_forward(); - } - - if ( current == '.' ) - { - move_forward(); - if ( current == '.' ) - { - token.Length = 3; - token.Type = TokType::Varadic_Argument; - token.Flags = TF_Null; - move_forward(); - } - else - { - String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) ); - - log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", current, line, column, context_str ); - } - } - - goto FoundToken; - } - case '&' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Ampersand; - token.Flags |= TF_Operator; - token.Flags |= TF_Specifier; - - if ( left ) - move_forward(); - - if ( current == '&' ) // && - { - token.Length = 2; - token.Type = TokType::Ampersand_DBL; - - if ( left ) - move_forward(); - } - - goto FoundToken; - } - case ':' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Assign_Classifer; - // Can be either a classifier (ParentType, Bitfield width), or ternary else - // token.Type = TokType::Colon; - - if ( left ) - move_forward(); - - if ( current == ':' ) - { - move_forward(); - token.Type = TokType::Access_StaticSymbol; - token.Length++; - } - goto FoundToken; - } - case '{' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::BraceCurly_Open; - - if ( left ) - move_forward(); - goto FoundToken; - } - case '}' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::BraceCurly_Close; - token.Flags = TF_EndDefinition; - - if ( left ) - move_forward(); - - end_line(); - goto FoundToken; - } - case '[' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::BraceSquare_Open; - if ( left ) - { - move_forward(); - - if ( current == ']' ) - { - token.Length = 2; - token.Type = TokType::Operator; - move_forward(); - } - } - goto FoundToken; - } - case ']' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::BraceSquare_Close; - - if ( left ) - move_forward(); - goto FoundToken; - } - case '(' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Capture_Start; - - if ( left ) - move_forward(); - goto FoundToken; - } - case ')' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Capture_End; - - if ( left ) - move_forward(); - goto FoundToken; - } - case '\'' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Char; - token.Flags = TF_Literal; + } + case '.': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Access_MemberSymbol; + token.Flags = TF_AccessOperator; + if (left) { move_forward(); - - if ( left && current == '\\' ) - { - move_forward(); - token.Length++; - - if ( current == '\'' ) - { - move_forward(); - token.Length++; - } - } - - while ( left && current != '\'' ) - { - move_forward(); - token.Length++; - } - - if ( left ) - { - move_forward(); - token.Length++; - } - goto FoundToken; } - case ',' : + + if ( current == '.' ) { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Comma; - token.Flags = TF_Operator; - - if ( left ) - move_forward(); - goto FoundToken; - } - case '*' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Star; - token.Flags |= TF_Specifier; - token.Flags |= TF_Operator; - - if ( left ) - move_forward(); - - if ( current == '=' ) - { - token.Length++; - token.Flags |= TF_Assign; - // token.Type = TokType::Assign_Multiply; - - if ( left ) - move_forward(); - } - - goto FoundToken; - } - case ';' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Statement_End; - token.Flags = TF_EndDefinition; - - if ( left ) - move_forward(); - - end_line(); - goto FoundToken; - } - case '"' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::String; - token.Flags |= TF_Literal; - move_forward(); - while ( left ) + if( current == '.' ) { - if ( current == '"' ) - { - move_forward(); - break; - } - - if ( current == '\\' ) - { - move_forward(); - token.Length++; - - if ( left ) - { - move_forward(); - token.Length++; - } - continue; - } - + token.Length = 3; + token.Type = TokType::Varadic_Argument; + token.Flags = TF_Null; move_forward(); - token.Length++; - } - goto FoundToken; - } - case '?' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Operator; - // token.Type = TokType::Ternary; - token.Flags = TF_Operator; - - if ( left ) - move_forward(); - - goto FoundToken; - } - case '=' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Operator; - // token.Type = TokType::Assign; - token.Flags = TF_Operator; - token.Flags |= TF_Assign; - - if ( left ) - move_forward(); - - if ( current == '=' ) - { - token.Length++; - token.Flags = TF_Operator; - - if ( left ) - move_forward(); - } - - goto FoundToken; - } - case '+' : - { - // token.Type = TokType::Add - } - case '%' : - { - // token.Type = TokType::Modulo; - } - case '^' : - { - // token.Type = TokType::B_XOr; - } - case '~' : - { - // token.Type = TokType::Unary_Not; - } - case '!' : - { - // token.Type = TokType::L_Not; - } - case '<' : - { - // token.Type = TokType::Lesser; - } - case '>' : - { - // token.Type = TokType::Greater; - } - case '|' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Operator; - token.Flags = TF_Operator; - // token.Type = TokType::L_Or; - - if ( left ) - move_forward(); - - if ( current == '=' ) - { - token.Length++; - token.Flags |= TF_Assign; - // token.Flags |= TokFlags::Assignment; - // token.Type = TokType::Assign_L_Or; - - if ( left ) - move_forward(); } else - while ( left && current == *( scanner - 1 ) && token.Length < 3 ) - { - token.Length++; - - if ( left ) - move_forward(); - } - goto FoundToken; - } - - // Dash is unfortunatlly a bit more complicated... - case '-' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Operator; - // token.Type = TokType::Subtract; - token.Flags = TF_Operator; - if ( left ) { - move_forward(); + String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) ); - if ( current == '>' ) - { - token.Length++; - // token.Type = TokType::Access_PointerToMemberSymbol; - token.Flags |= TF_AccessOperator; - move_forward(); - - if ( current == '*' ) - { - // token.Type = TokType::Access_PointerToMemberOfPointerSymbol; - token.Length++; - move_forward(); - } - } - else if ( current == '=' ) - { - token.Length++; - // token.Type = TokType::Assign_Subtract; - token.Flags |= TF_Assign; - - if ( left ) - move_forward(); - } - else - while ( left && current == *( scanner - 1 ) && token.Length < 3 ) - { - token.Length++; - - if ( left ) - move_forward(); - } + log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", current, line, column, context_str ); } - goto FoundToken; - } - case '/' : - { - token.Text = scanner; - token.Length = 1; - token.Type = TokType::Operator; - // token.Type = TokType::Divide; - token.Flags = TF_Operator; - move_forward(); - - if ( left ) - { - if ( current == '=' ) - { - // token.Type = TokeType::Assign_Divide; - move_forward(); - token.Length++; - token.Flags = TF_Assign; - } - else if ( current == '/' ) - { - token.Type = TokType::Comment; - token.Length = 2; - token.Flags = TF_Null; - move_forward(); - - while ( left && current != '\n' && current != '\r' ) - { - move_forward(); - token.Length++; - } - - if ( current == '\r' ) - { - move_forward(); - token.Length++; - } - if ( current == '\n' ) - { - move_forward(); - token.Length++; - } - Tokens.append( token ); - continue; - } - else if ( current == '*' ) - { - token.Type = TokType::Comment; - token.Length = 2; - token.Flags = TF_Null; - move_forward(); - - bool star = current == '*'; - bool slash = scanner[1] == '/'; - bool at_end = star && slash; - while ( left && ! at_end ) - { - move_forward(); - token.Length++; - - star = current == '*'; - slash = scanner[1] == '/'; - at_end = star && slash; - } - token.Length += 2; - move_forward(); - move_forward(); - - if ( current == '\r' ) - { - move_forward(); - token.Length++; - } - if ( current == '\n' ) - { - move_forward(); - token.Length++; - } - Tokens.append( token ); - // end_line(); - continue; - } - } - goto FoundToken; - } - } - - if ( char_is_alpha( current ) || current == '_' ) - { - token.Text = scanner; - token.Length = 1; - move_forward(); - - while ( left && ( char_is_alphanumeric( current ) || current == '_' ) ) - { - move_forward(); - token.Length++; } goto FoundToken; } - else if ( char_is_digit( current ) ) + case '&' : { - // This is a very brute force lex, no checks are done for validity of literal. - token.Text = scanner; token.Length = 1; - token.Type = TokType::Number; + token.Type = TokType::Ampersand; + token.Flags |= TF_Operator; + token.Flags |= TF_Specifier; + + if (left) + move_forward(); + + if ( current == '&' ) // && + { + token.Length = 2; + token.Type = TokType::Ampersand_DBL; + + if (left) + move_forward(); + } + + goto FoundToken; + } + case ':': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Assign_Classifer; + // Can be either a classifier (ParentType, Bitfield width), or ternary else + // token.Type = TokType::Colon; + + if (left) + move_forward(); + + if ( current == ':' ) + { + move_forward(); + token.Type = TokType::Access_StaticSymbol; + token.Length++; + } + goto FoundToken; + } + case '{': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::BraceCurly_Open; + + if (left) + move_forward(); + goto FoundToken; + } + case '}': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::BraceCurly_Close; + token.Flags = TF_EndDefinition; + + if (left) + move_forward(); + + end_line(); + goto FoundToken; + } + case '[': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::BraceSquare_Open; + if ( left ) + { + move_forward(); + + if ( current == ']' ) + { + token.Length = 2; + token.Type = TokType::Operator; + move_forward(); + } + } + goto FoundToken; + } + case ']': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::BraceSquare_Close; + + if (left) + move_forward(); + goto FoundToken; + } + case '(': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Capture_Start; + + if (left) + move_forward(); + goto FoundToken; + } + case ')': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Capture_End; + + if (left) + move_forward(); + goto FoundToken; + } + case '\'': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Char; token.Flags = TF_Literal; + move_forward(); - if ( left && ( current == 'x' || current == 'X' || current == 'b' || current == 'B' || current == 'o' || current == 'O' ) ) + if ( left && current == '\\' ) { move_forward(); token.Length++; - while ( left && char_is_hex_digit( current ) ) + if ( current == '\'' ) { move_forward(); token.Length++; } - - goto FoundToken; } - while ( left && char_is_digit( current ) ) + while ( left && current != '\'' ) { move_forward(); token.Length++; } - if ( left && current == '.' ) + if ( left ) { move_forward(); token.Length++; + } + goto FoundToken; + } + case ',': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Comma; + token.Flags = TF_Operator; - while ( left && char_is_digit( current ) ) - { + if (left) + move_forward(); + goto FoundToken; + } + case '*': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Star; + token.Flags |= TF_Specifier; + token.Flags |= TF_Operator; + + if (left) + move_forward(); + + if ( current == '=' ) + { + token.Length++; + token.Flags |= TF_Assign; + // token.Type = TokType::Assign_Multiply; + + if ( left ) move_forward(); - token.Length++; - } - - // Handle number literal suffixes in a botched way - if ( left - && ( current == 'l' || current == 'L' || // long/long long - current == 'u' || current == 'U' || // unsigned - current == 'f' || current == 'F' || // float - current == 'i' || current == 'I' || // imaginary - current == 'z' || current == 'Z' ) ) // complex - { - char prev = current; - move_forward(); - token.Length++; - - // Handle 'll'/'LL' as a special case when we just processed an 'l'/'L' - if ( left && ( prev == 'l' || prev == 'L' ) && ( current == 'l' || current == 'L' ) ) - { - move_forward(); - token.Length++; - } - } } goto FoundToken; } - else + case ';': { - s32 start = max( 0, Tokens.num() - 100 ); - log_fmt( "\n%d\n", start ); - for ( s32 idx = start; idx < Tokens.num(); idx++ ) + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Statement_End; + token.Flags = TF_EndDefinition; + + if (left) + move_forward(); + + end_line(); + goto FoundToken; + } + case '"': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::String; + token.Flags |= TF_Literal; + + move_forward(); + while ( left ) { - log_fmt( "Token %d Type: %s : %.*s\n", idx, ETokType::to_str( Tokens[idx].Type ).Ptr, Tokens[idx].Length, Tokens[idx].Text ); + if ( current == '"' ) + { + move_forward(); + break; + } + + if ( current == '\\' ) + { + move_forward(); + token.Length++; + + if ( left ) + { + move_forward(); + token.Length++; + } + continue; + } + + move_forward(); + token.Length++; + } + goto FoundToken; + } + case '?': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Operator; + // token.Type = TokType::Ternary; + token.Flags = TF_Operator; + + if (left) + move_forward(); + + goto FoundToken; + } + case '=': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Operator; + // token.Type = TokType::Assign; + token.Flags = TF_Operator; + token.Flags |= TF_Assign; + + if (left) + move_forward(); + + if ( current == '=' ) + { + token.Length++; + token.Flags = TF_Operator; + + if (left) + move_forward(); } - String context_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 100, left ), scanner ); - log_failure( "Failed to lex token '%c' (%d, %d)\n%s", current, line, column, context_str ); + goto FoundToken; + } + case '+': + { + // token.Type = TokType::Add - // Skip to next whitespace since we can't know if anything else is valid until then. - while ( left && ! char_is_space( current ) ) + } + case '%': + { + // token.Type = TokType::Modulo; + + } + case '^': + { + // token.Type = TokType::B_XOr; + } + case '~': + { + // token.Type = TokType::Unary_Not; + + } + case '!': + { + // token.Type = TokType::L_Not; + } + case '<': + { + // token.Type = TokType::Lesser; + + } + case '>': + { + // token.Type = TokType::Greater; + + } + case '|': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Operator; + token.Flags = TF_Operator; + // token.Type = TokType::L_Or; + + if (left) + move_forward(); + + if ( current == '=' ) + { + token.Length++; + token.Flags |= TF_Assign; + // token.Flags |= TokFlags::Assignment; + // token.Type = TokType::Assign_L_Or; + + if (left) + move_forward(); + } + else while ( left && current == *(scanner - 1) && token.Length < 3 ) + { + token.Length++; + + if (left) + move_forward(); + } + goto FoundToken; + } + + // Dash is unfortunatlly a bit more complicated... + case '-': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Operator; + // token.Type = TokType::Subtract; + token.Flags = TF_Operator; + if ( left ) { move_forward(); + + if ( current == '>' ) + { + token.Length++; +// token.Type = TokType::Access_PointerToMemberSymbol; + token.Flags |= TF_AccessOperator; + move_forward(); + + if ( current == '*' ) + { +// token.Type = TokType::Access_PointerToMemberOfPointerSymbol; + token.Length++; + move_forward(); + } + } + else if ( current == '=' ) + { + token.Length++; + // token.Type = TokType::Assign_Subtract; + token.Flags |= TF_Assign; + + if (left) + move_forward(); + } + else while ( left && current == *(scanner - 1) && token.Length < 3 ) + { + token.Length++; + + if (left) + move_forward(); + } + } + goto FoundToken; + } + case '/': + { + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Operator; + // token.Type = TokType::Divide; + token.Flags = TF_Operator; + move_forward(); + + if ( left ) + { + if ( current == '=' ) + { + // token.Type = TokeType::Assign_Divide; + move_forward(); + token.Length++; + token.Flags = TF_Assign; + } + else if ( current == '/' ) + { + token.Type = TokType::Comment; + token.Length = 2; + token.Flags = TF_Null; + move_forward(); + + while ( left && current != '\n' && current != '\r' ) + { + move_forward(); + token.Length++; + } + + if ( current == '\r' ) + { + move_forward(); + token.Length++; + } + if ( current == '\n' ) + { + move_forward(); + token.Length++; + } + Tokens.append( token ); + continue; + } + else if ( current == '*' ) + { + token.Type = TokType::Comment; + token.Length = 2; + token.Flags = TF_Null; + move_forward(); + + bool star = current == '*'; + bool slash = scanner[1] == '/'; + bool at_end = star && slash; + while ( left && ! at_end ) + { + move_forward(); + token.Length++; + + star = current == '*'; + slash = scanner[1] == '/'; + at_end = star && slash; + } + token.Length += 2; + move_forward(); + move_forward(); + + if ( current == '\r' ) + { + move_forward(); + token.Length++; + } + if ( current == '\n' ) + { + move_forward(); + token.Length++; + } + Tokens.append( token ); + // end_line(); + continue; + } + } + goto FoundToken; + } + } + + if ( char_is_alpha( current ) || current == '_' ) + { + token.Text = scanner; + token.Length = 1; + move_forward(); + + while ( left && ( char_is_alphanumeric(current) || current == '_' ) ) + { + move_forward(); + token.Length++; + } + + goto FoundToken; + } + else if ( char_is_digit(current) ) + { + // This is a very brute force lex, no checks are done for validity of literal. + + token.Text = scanner; + token.Length = 1; + token.Type = TokType::Number; + token.Flags = TF_Literal; + move_forward(); + + if (left + && ( current == 'x' || current == 'X' + || current == 'b' || current == 'B' + || current == 'o' || current == 'O' ) + ) + { + move_forward(); + token.Length++; + + while ( left && char_is_hex_digit(current) ) + { + move_forward(); + token.Length++; + } + + goto FoundToken; + } + + while ( left && char_is_digit(current) ) + { + move_forward(); + token.Length++; + } + + if ( left && current == '.' ) + { + move_forward(); + token.Length++; + + while ( left && char_is_digit(current) ) + { + move_forward(); + token.Length++; + } + + // Handle number literal suffixes in a botched way + if (left && ( + current == 'l' || current == 'L' || // long/long long + current == 'u' || current == 'U' || // unsigned + current == 'f' || current == 'F' || // float + current == 'i' || current == 'I' || // imaginary + current == 'z' || current == 'Z')) // complex + { + char prev = current; + move_forward(); + token.Length++; + + // Handle 'll'/'LL' as a special case when we just processed an 'l'/'L' + if (left && (prev == 'l' || prev == 'L') && (current == 'l' || current == 'L')) + { + move_forward(); + token.Length++; + } } } - FoundToken: - lex_found_token( content, left, scanner, line, column, defines, token ); + goto FoundToken; } - - if ( Tokens.num() == 0 ) + else { - log_failure( "Failed to lex any tokens" ); - return { { nullptr }, 0 }; + s32 start = max( 0, Tokens.num() - 100 ); + log_fmt("\n%d\n", start); + for ( s32 idx = start; idx < Tokens.num(); idx++ ) + { + log_fmt( "Token %d Type: %s : %.*s\n" + , idx + , ETokType::to_str( Tokens[ idx ].Type ).Ptr + , Tokens[ idx ].Length, Tokens[ idx ].Text + ); + } + + String context_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 100, left ), scanner ); + log_failure( "Failed to lex token '%c' (%d, %d)\n%s", current, line, column, context_str ); + + // Skip to next whitespace since we can't know if anything else is valid until then. + while ( left && ! char_is_space( current ) ) + { + move_forward(); + } } - defines.clear(); - // defines_map_arena.free(); - return { Tokens, 0 }; + FoundToken: + lex_found_token( content, left, scanner, line, column, defines, token ); } + if ( Tokens.num() == 0 ) + { + log_failure( "Failed to lex any tokens" ); + return { { nullptr }, 0 }; + } + + defines.clear(); + // defines_map_arena.free(); + return { Tokens, 0 }; +} #undef current #undef move_forward #undef SkipWhitespace - // namespace parser -} // namespace parser +// namespace parser +} -namespace parser +namespace parser { + +// TODO(Ed) : Rename ETokType::Capture_Start, ETokType::Capture_End to Open_Parenthesis adn Close_Parenthesis + +constexpr bool dont_skip_formatting = false; + +struct StackNode { + StackNode* Prev; - // TODO(Ed) : Rename ETokType::Capture_Start, ETokType::Capture_End to Open_Parenthesis adn Close_Parenthesis + Token Start; + Token Name; // The name of the AST node (if parsed) + StrC ProcName; // The name of the procedure +}; - constexpr bool dont_skip_formatting = false; +struct ParseContext +{ + TokArray Tokens; + StackNode* Scope; - struct StackNode + void push( StackNode* node ) { - StackNode* Prev; + node->Prev = Scope; + Scope = node; - Token Start; - Token Name; // The name of the AST node (if parsed) - StrC ProcName; // The name of the procedure - }; - - struct ParseContext - { - TokArray Tokens; - StackNode* Scope; - - void push( StackNode* node ) - { - node->Prev = Scope; - Scope = node; - -#if 0 && Build_Debug + #if 0 && Build_Debug log_fmt("\tEntering Context: %.*s\n", Scope->ProcName.Len, Scope->ProcName.Ptr ); -#endif - } + #endif + } - void pop() - { -#if 0 && Build_Debug + void pop() + { + #if 0 && Build_Debug log_fmt("\tPopping Context: %.*s\n", Scope->ProcName.Len, Scope->ProcName.Ptr ); -#endif - Scope = Scope->Prev; + #endif + Scope = Scope->Prev; + } + + String to_string() + { + String result = String::make_reserve( GlobalAllocator, kilobytes(4) ); + + Token scope_start = Scope->Start; + Token last_valid = Tokens.Idx >= Tokens.Arr.num() ? Tokens.Arr[Tokens.Arr.num() -1] : Tokens.current(); + + sptr length = scope_start.Length; + char const* current = scope_start.Text + length; + while ( current <= Tokens.Arr.back().Text && *current != '\n' && length < 74 ) + { + current++; + length++; } - String to_string() + String line = String::make( GlobalAllocator, { length, scope_start.Text } ); + result.append_fmt("\tScope : %s\n", line ); + line.free(); + + sptr dist = (sptr)last_valid.Text - (sptr)scope_start.Text + 2; + sptr length_from_err = dist; + String line_from_err = String::make( GlobalAllocator, { length_from_err, last_valid.Text } ); + + if ( length_from_err < 100 ) + result.append_fmt("\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' ); + else + result.append_fmt("\t(%d, %d)\n", last_valid.Line, last_valid.Column ); + + StackNode* curr_scope = Scope; + s32 level = 0; + do { - String result = String::make_reserve( GlobalAllocator, kilobytes( 4 ) ); - - Token scope_start = Scope->Start; - Token last_valid = Tokens.Idx >= Tokens.Arr.num() ? Tokens.Arr[Tokens.Arr.num() - 1] : Tokens.current(); - - sptr length = scope_start.Length; - char const* current = scope_start.Text + length; - while ( current <= Tokens.Arr.back().Text && *current != '\n' && length < 74 ) + if ( curr_scope->Name ) { - current++; - length++; + result.append_fmt("\t%d: %s, AST Name: %.*s\n", level, curr_scope->ProcName.Ptr, curr_scope->Name.Length, curr_scope->Name.Text ); + } + else + { + result.append_fmt("\t%d: %s\n", level, curr_scope->ProcName.Ptr ); } - String line = String::make( GlobalAllocator, { length, scope_start.Text } ); - result.append_fmt( "\tScope : %s\n", line ); - line.free(); - - sptr dist = (sptr)last_valid.Text - (sptr)scope_start.Text + 2; - sptr length_from_err = dist; - String line_from_err = String::make( GlobalAllocator, { length_from_err, last_valid.Text } ); - - if ( length_from_err < 100 ) - result.append_fmt( "\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' ); - else - result.append_fmt( "\t(%d, %d)\n", last_valid.Line, last_valid.Column ); - - StackNode* curr_scope = Scope; - s32 level = 0; - do - { - if ( curr_scope->Name ) - { - result.append_fmt( "\t%d: %s, AST Name: %.*s\n", level, curr_scope->ProcName.Ptr, curr_scope->Name.Length, curr_scope->Name.Text ); - } - else - { - result.append_fmt( "\t%d: %s\n", level, curr_scope->ProcName.Ptr ); - } - - curr_scope = curr_scope->Prev; - level++; - } while ( curr_scope ); - return result; + curr_scope = curr_scope->Prev; + level++; } - }; + while ( curr_scope ); + return result; + } +}; - global ParseContext Context; +global ParseContext Context; - bool TokArray::__eat( TokType type ) +bool TokArray::__eat( TokType type ) +{ + if ( Arr.num() - Idx <= 0 ) { - if ( Arr.num() - Idx <= 0 ) - { - log_failure( "No tokens left.\n%s", Context.to_string() ); - return false; - } + log_failure( "No tokens left.\n%s", Context.to_string() ); + return false; + } - if ( ( Arr[Idx].Type == TokType::NewLine && type != TokType::NewLine ) || ( Arr[Idx].Type == TokType::Comment && type != TokType::Comment ) ) - { - Idx++; - } + if ( ( Arr[ Idx ].Type == TokType::NewLine && type != TokType::NewLine ) + || ( Arr[ Idx ].Type == TokType::Comment && type != TokType::Comment ) ) + { + Idx++; + } - if ( Arr[Idx].Type != type ) - { - log_failure( - "Parse Error, TokArray::eat, Expected: ' %s ' not ' %.*s ' (%d, %d)`\n%s", - ETokType::to_str( type ).Ptr, - Arr[Idx].Length, - Arr[Idx].Text, - current().Line, - current().Column, - Context.to_string() - ); + if ( Arr[Idx].Type != type ) + { + log_failure( "Parse Error, TokArray::eat, Expected: ' %s ' not ' %.*s ' (%d, %d)`\n%s" + , ETokType::to_str(type).Ptr + , Arr[Idx].Length, Arr[Idx].Text + , current().Line + , current().Column + , Context.to_string() + ); - return false; - } + return false; + } #if 0 && Build_Debug log_fmt("Ate: %S\n", Arr[Idx].to_string() ); #endif - Idx++; - return true; - } + Idx++; + return true; +} - internal void init() - { - Tokens = Array::init_reserve( LexArena, ( LexAllocator_Size - sizeof( Array::Header ) ) / sizeof( Token ) ); +internal +void init() +{ + Tokens = Array::init_reserve( LexArena + , ( LexAllocator_Size - sizeof( Array::Header ) ) / sizeof(Token) + ); - defines_map_arena = Arena_256KB::init(); - defines = HashTable::init_reserve( defines_map_arena, 256 ); - } + defines_map_arena = Arena_256KB::init(); + defines = HashTable::init_reserve( defines_map_arena, 256 ); +} - internal void deinit() - { - parser::Tokens = { nullptr }; - } +internal +void deinit() +{ + parser::Tokens = { nullptr }; +} #pragma region Helper Macros -#define check_parse_args( def ) \ - if ( def.Len <= 0 ) \ - { \ - log_failure( "gen::" stringize( __func__ ) ": length must greater than 0" ); \ - parser::Context.pop(); \ - return CodeInvalid; \ - } \ - if ( def.Ptr == nullptr ) \ - { \ - log_failure( "gen::" stringize( __func__ ) ": def was null" ); \ - parser::Context.pop(); \ - return CodeInvalid; \ - } +# define check_parse_args( def ) \ +if ( def.Len <= 0 ) \ +{ \ + log_failure( "gen::" stringize(__func__) ": length must greater than 0" ); \ + parser::Context.pop(); \ + return CodeInvalid; \ +} \ +if ( def.Ptr == nullptr ) \ +{ \ + log_failure( "gen::" stringize(__func__) ": def was null" ); \ + parser::Context.pop(); \ + return CodeInvalid; \ +} -#define currtok_noskip Context.Tokens.current( dont_skip_formatting ) -#define currtok Context.Tokens.current() -#define prevtok Context.Tokens.previous() -#define nexttok Context.Tokens.next() -#define eat( Type_ ) Context.Tokens.__eat( Type_ ) -#define left ( Context.Tokens.Arr.num() - Context.Tokens.Idx ) +# define currtok_noskip Context.Tokens.current( dont_skip_formatting ) +# define currtok Context.Tokens.current() +# define prevtok Context.Tokens.previous() +# define nexttok Context.Tokens.next() +# define eat( Type_ ) Context.Tokens.__eat( Type_ ) +# define left ( Context.Tokens.Arr.num() - Context.Tokens.Idx ) -#define check_noskip( Type_ ) ( left && currtok_noskip.Type == Type_ ) -#define check( Type_ ) ( left && currtok.Type == Type_ ) +#ifdef check +#define CHECK_WAS_DEFINED +#pragma push_macro("check") +#undef check +#endif -#define push_scope() \ +# define check_noskip( Type_ ) ( left && currtok_noskip.Type == Type_ ) +# define check( Type_ ) ( left && currtok.Type == Type_ ) + +# define push_scope() \ StackNode scope { nullptr, currtok_noskip, NullToken, txt( __func__ ) }; \ - Context.push( &scope ) + Context.push( & scope ) #pragma endregion Helper Macros - // Procedure Forwards ( Entire parser internal parser interface ) +// Procedure Forwards ( Entire parser internal parser interface ) - internal Code parse_array_decl(); - internal CodeAttributes parse_attributes(); - internal CodeComment parse_comment(); - internal Code parse_complicated_definition( TokType which ); - internal CodeBody parse_class_struct_body( TokType which, Token name = NullToken ); - internal Code parse_class_struct( TokType which, bool inplace_def ); - internal CodeDefine parse_define(); - internal Code parse_expression(); - internal Code parse_forward_or_definition( TokType which, bool is_inplace ); - internal CodeFn parse_function_after_name( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type, Token name ); - internal Code parse_function_body(); - internal Code parse_global_nspace(); - internal Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ); - internal Token parse_identifier( bool* possible_member_function = nullptr ); - internal CodeInclude parse_include(); - internal CodeOperator parse_operator_after_ret_type( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type ); - internal Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers ); - internal CodePragma parse_pragma(); - internal CodeParam parse_params( bool use_template_capture = false ); - internal CodePreprocessCond parse_preprocess_cond(); - internal Code parse_simple_preprocess( TokType which ); - internal Code parse_static_assert(); - internal void parse_template_args( Token& token ); - internal CodeVar parse_variable_after_name( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType type, StrC name ); - internal CodeVar parse_variable_declaration_list(); +internal Code parse_array_decl (); +internal CodeAttributes parse_attributes (); +internal CodeComment parse_comment (); +internal Code parse_complicated_definition ( TokType which ); +internal CodeBody parse_class_struct_body ( TokType which, Token name = NullToken ); +internal Code parse_class_struct ( TokType which, bool inplace_def ); +internal CodeDefine parse_define (); +internal Code parse_expression (); +internal Code parse_forward_or_definition ( TokType which, bool is_inplace ); +internal CodeFn parse_function_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type, Token name ); +internal Code parse_function_body (); +internal Code parse_global_nspace (); +internal Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ); +internal Token parse_identifier ( bool* possible_member_function = nullptr ); +internal CodeInclude parse_include (); +internal CodeOperator parse_operator_after_ret_type ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type ); +internal Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers ); +internal CodePragma parse_pragma (); +internal CodeParam parse_params ( bool use_template_capture = false ); +internal CodePreprocessCond parse_preprocess_cond (); +internal Code parse_simple_preprocess ( TokType which ); +internal Code parse_static_assert (); +internal void parse_template_args ( Token& token ); +internal CodeVar parse_variable_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType type, StrC name ); +internal CodeVar parse_variable_declaration_list (); - internal CodeClass parse_class( bool inplace_def = false ); - internal CodeConstructor parse_constructor( CodeSpecifiers specifiers ); - internal CodeDestructor parse_destructor( CodeSpecifiers specifiers = NoCode ); - internal CodeEnum parse_enum( bool inplace_def = false ); - internal CodeBody parse_export_body(); - internal CodeBody parse_extern_link_body(); - internal CodeExtern parse_extern_link(); - internal CodeFriend parse_friend(); - internal CodeFn parse_function(); - internal CodeNS parse_namespace(); - internal CodeOpCast parse_operator_cast( CodeSpecifiers specifiers = NoCode ); - internal CodeStruct parse_struct( bool inplace_def = false ); - internal CodeVar parse_variable(); - internal CodeTemplate parse_template(); - internal CodeType parse_type( bool from_template = false, bool* is_function = nullptr ); - internal CodeTypedef parse_typedef(); - internal CodeUnion parse_union( bool inplace_def = false ); - internal CodeUsing parse_using(); +internal CodeClass parse_class ( bool inplace_def = false ); +internal CodeConstructor parse_constructor ( CodeSpecifiers specifiers ); +internal CodeDestructor parse_destructor ( CodeSpecifiers specifiers = NoCode ); +internal CodeEnum parse_enum ( bool inplace_def = false ); +internal CodeBody parse_export_body (); +internal CodeBody parse_extern_link_body(); +internal CodeExtern parse_extern_link (); +internal CodeFriend parse_friend (); +internal CodeFn parse_function (); +internal CodeNS parse_namespace (); +internal CodeOpCast parse_operator_cast ( CodeSpecifiers specifiers = NoCode ); +internal CodeStruct parse_struct ( bool inplace_def = false ); +internal CodeVar parse_variable (); +internal CodeTemplate parse_template (); +internal CodeType parse_type ( bool from_template = false, bool* is_function = nullptr ); +internal CodeTypedef parse_typedef (); +internal CodeUnion parse_union ( bool inplace_def = false ); +internal CodeUsing parse_using (); - constexpr bool inplace_def = true; +constexpr bool inplace_def = true; - // Internal parsing functions +// Internal parsing functions - constexpr bool strip_formatting_dont_preserve_newlines = false; +constexpr bool strip_formatting_dont_preserve_newlines = false; +/* + This function was an attempt at stripping formatting from any c++ code. + It has edge case failures that prevent it from being used in function bodies. +*/ +internal +String strip_formatting( StrC raw_text, bool preserve_newlines = true ) +{ + String content = String::make_reserve( GlobalAllocator, raw_text.Len ); - /* - This function was an attempt at stripping formatting from any c++ code. - It has edge case failures that prevent it from being used in function bodies. - */ - internal String strip_formatting( StrC raw_text, bool preserve_newlines = true ) - { - String content = String::make_reserve( GlobalAllocator, raw_text.Len ); - - if ( raw_text.Len == 0 ) - return content; + if ( raw_text.Len == 0 ) + return content; #define cut_length ( scanner - raw_text.Ptr - last_cut ) -#define cut_ptr ( raw_text.Ptr + last_cut ) +#define cut_ptr ( raw_text.Ptr + last_cut ) #define pos ( sptr( scanner ) - sptr( raw_text.Ptr ) ) -#define move_fwd() \ - do \ - { \ - scanner++; \ - tokleft--; \ - } while ( 0 ) +#define move_fwd() do { scanner++; tokleft--; } while(0) - s32 tokleft = raw_text.Len; - sptr last_cut = 0; - char const* scanner = raw_text.Ptr; + s32 tokleft = raw_text.Len; + sptr last_cut = 0; + char const* scanner = raw_text.Ptr; - if ( scanner[0] == ' ' ) + if ( scanner[0] == ' ' ) + { + move_fwd(); + last_cut = 1; + } + + bool within_string = false; + bool within_char = false; + bool must_keep_newline = false; + while ( tokleft ) + { + // Skip over the content of string literals + if ( scanner[0] == '"' ) { move_fwd(); - last_cut = 1; + + while ( tokleft && ( scanner[0] != '"' || *( scanner - 1 ) == '\\' ) ) + { + if ( scanner[0] == '\\' && tokleft > 1 ) + { + scanner += 2; + tokleft -= 2; + } + else + { + move_fwd(); + } + } + + // Skip the closing " + if ( tokleft ) + move_fwd(); + + content.append( cut_ptr, cut_length ); + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; } - bool within_string = false; - bool within_char = false; - bool must_keep_newline = false; - while ( tokleft ) + // Skip over the content of character literals + if ( scanner[0] == '\'' ) { - // Skip over the content of string literals - if ( scanner[0] == '"' ) + move_fwd(); + + while ( tokleft + && ( scanner[0] != '\'' + || ( *(scanner -1 ) == '\\' ) + ) ) { move_fwd(); - - while ( tokleft && ( scanner[0] != '"' || *( scanner - 1 ) == '\\' ) ) - { - if ( scanner[0] == '\\' && tokleft > 1 ) - { - scanner += 2; - tokleft -= 2; - } - else - { - move_fwd(); - } - } - - // Skip the closing " - if ( tokleft ) - move_fwd(); - - content.append( cut_ptr, cut_length ); - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; } - // Skip over the content of character literals - if ( scanner[0] == '\'' ) - { + // Skip the closing ' + if ( tokleft ) move_fwd(); - while ( tokleft && ( scanner[0] != '\'' || ( *( scanner - 1 ) == '\\' ) ) ) - { - move_fwd(); - } + content.append( cut_ptr, cut_length ); + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; + } - // Skip the closing ' - if ( tokleft ) - move_fwd(); + // Block comments + if ( tokleft > 1 && scanner[0] == '/' && scanner[1] == '*' ) + { + while ( tokleft > 1 && !(scanner[0] == '*' && scanner[1] == '/') ) + move_fwd(); - content.append( cut_ptr, cut_length ); - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } + scanner += 2; + tokleft -= 2; - // Block comments - if ( tokleft > 1 && scanner[0] == '/' && scanner[1] == '*' ) + content.append( cut_ptr, cut_length ); + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; + } + + // Line comments + if ( tokleft > 1 && scanner[0] == '/' && scanner[1] == '/' ) + { + must_keep_newline = true; + + scanner += 2; + tokleft -= 2; + + while ( tokleft && scanner[ 0 ] != '\n' ) + move_fwd(); + + if (tokleft) + move_fwd(); + + content.append( cut_ptr, cut_length ); + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; + } + + // Tabs + if (scanner[0] == '\t') + { + if (pos > last_cut) + content.append(cut_ptr, cut_length); + + if ( content.back() != ' ' ) + content.append(' '); + + move_fwd(); + last_cut = sptr(scanner) - sptr(raw_text.Ptr); + continue; + } + + if ( tokleft > 1 && scanner[0] == '\r' && scanner[1] == '\n' ) + { + if ( must_keep_newline || preserve_newlines ) { - while ( tokleft > 1 && ! ( scanner[0] == '*' && scanner[1] == '/' ) ) - move_fwd(); + must_keep_newline = false; scanner += 2; tokleft -= 2; @@ -7522,3917 +7538,644 @@ namespace parser continue; } - // Line comments - if ( tokleft > 1 && scanner[0] == '/' && scanner[1] == '/' ) - { - must_keep_newline = true; - - scanner += 2; - tokleft -= 2; - - while ( tokleft && scanner[0] != '\n' ) - move_fwd(); - - if ( tokleft ) - move_fwd(); - + if ( pos > last_cut ) content.append( cut_ptr, cut_length ); - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } - // Tabs - if ( scanner[0] == '\t' ) + // Replace with a space + if ( content.back() != ' ' ) + content.append( ' ' ); + + scanner += 2; + tokleft -= 2; + + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; + } + + if ( scanner[0] == '\n' ) + { + if ( must_keep_newline || preserve_newlines ) { - if ( pos > last_cut ) - content.append( cut_ptr, cut_length ); - - if ( content.back() != ' ' ) - content.append( ' ' ); - - move_fwd(); - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } - - if ( tokleft > 1 && scanner[0] == '\r' && scanner[1] == '\n' ) - { - if ( must_keep_newline || preserve_newlines ) - { - must_keep_newline = false; - - scanner += 2; - tokleft -= 2; - - content.append( cut_ptr, cut_length ); - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } - - if ( pos > last_cut ) - content.append( cut_ptr, cut_length ); - - // Replace with a space - if ( content.back() != ' ' ) - content.append( ' ' ); - - scanner += 2; - tokleft -= 2; - - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } - - if ( scanner[0] == '\n' ) - { - if ( must_keep_newline || preserve_newlines ) - { - must_keep_newline = false; - - move_fwd(); - - content.append( cut_ptr, cut_length ); - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } - - if ( pos > last_cut ) - content.append( cut_ptr, cut_length ); - - // Replace with a space - if ( content.back() != ' ' ) - content.append( ' ' ); + must_keep_newline = false; move_fwd(); + content.append( cut_ptr, cut_length ); last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); continue; } - // Escaped newlines - if ( scanner[0] == '\\' ) - { + if ( pos > last_cut ) content.append( cut_ptr, cut_length ); - s32 amount_to_skip = 1; - if ( tokleft > 1 && scanner[1] == '\n' ) - { - amount_to_skip = 2; - } - else if ( tokleft > 2 && scanner[1] == '\r' && scanner[2] == '\n' ) - { - amount_to_skip = 3; - } - - if ( amount_to_skip > 1 && pos == last_cut ) - { - scanner += amount_to_skip; - tokleft -= amount_to_skip; - } - else - move_fwd(); - - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - continue; - } - - // Consectuive spaces - if ( tokleft > 1 && char_is_space( scanner[0] ) && char_is_space( scanner[1] ) ) - { - content.append( cut_ptr, cut_length ); - do - { - move_fwd(); - } while ( tokleft && char_is_space( scanner[0] ) ); - - last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); - - // Preserve only 1 space of formattting - if ( content.back() != ' ' ) - content.append( ' ' ); - - continue; - } + // Replace with a space + if ( content.back() != ' ' ) + content.append( ' ' ); move_fwd(); + + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; } - if ( last_cut < raw_text.Len ) + // Escaped newlines + if ( scanner[0] == '\\' ) { - content.append( cut_ptr, raw_text.Len - last_cut ); + content.append( cut_ptr, cut_length ); + + s32 amount_to_skip = 1; + if ( tokleft > 1 && scanner[1] == '\n' ) + { + amount_to_skip = 2; + } + else if ( tokleft > 2 && scanner[1] == '\r' && scanner[2] == '\n' ) + { + amount_to_skip = 3; + } + + if ( amount_to_skip > 1 && pos == last_cut ) + { + scanner += amount_to_skip; + tokleft -= amount_to_skip; + } + else + move_fwd(); + + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + continue; } + // Consectuive spaces + if ( tokleft > 1 && char_is_space( scanner[0] ) && char_is_space( scanner[ 1 ] ) ) + { + content.append( cut_ptr, cut_length ); + do + { + move_fwd(); + } + while ( tokleft && char_is_space( scanner[0] ) ); + + last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); + + // Preserve only 1 space of formattting + if ( content.back() != ' ' ) + content.append( ' ' ); + + continue; + } + + move_fwd(); + } + + if ( last_cut < raw_text.Len ) + { + content.append( cut_ptr, raw_text.Len - last_cut ); + } + #undef cut_ptr #undef cut_length #undef pos #undef move_fwd - return content; - } + return content; +} - internal Code parse_array_decl() +internal +Code parse_array_decl() +{ + push_scope(); + + if ( check( TokType::Operator ) && currtok.Text[0] == '[' && currtok.Text[1] == ']' ) { - push_scope(); - - if ( check( TokType::Operator ) && currtok.Text[0] == '[' && currtok.Text[1] == ']' ) - { - Code array_expr = untyped_str( currtok ); - eat( TokType::Operator ); - // [] - - Context.pop(); - return array_expr; - } - - if ( check( TokType::BraceSquare_Open ) ) - { - eat( TokType::BraceSquare_Open ); - // [ - - if ( left == 0 ) - { - log_failure( "Error, unexpected end of array declaration ( '[]' scope started )\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - if ( currtok.Type == TokType::BraceSquare_Close ) - { - log_failure( "Error, empty array expression in definition\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - Token untyped_tok = currtok; - - while ( left && currtok.Type != TokType::BraceSquare_Close ) - { - eat( currtok.Type ); - } - - untyped_tok.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)untyped_tok.Text; - - Code array_expr = untyped_str( untyped_tok ); - // [ - - if ( left == 0 ) - { - log_failure( "Error, unexpected end of array declaration, expected ]\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - if ( currtok.Type != TokType::BraceSquare_Close ) - { - log_failure( "%s: Error, expected ] in array declaration, not %s\n%s", ETokType::to_str( currtok.Type ), Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - eat( TokType::BraceSquare_Close ); - // [ ] - - // Its a multi-dimensional array - if ( check( TokType::BraceSquare_Open ) ) - { - Code adjacent_arr_expr = parse_array_decl(); - // [ ][ ]... - - array_expr->Next = adjacent_arr_expr.ast; - } - - Context.pop(); - return array_expr; - } + Code array_expr = untyped_str( currtok ); + eat( TokType::Operator ); + // [] Context.pop(); - return { nullptr }; + return array_expr; } - internal inline CodeAttributes parse_attributes() + if ( check( TokType::BraceSquare_Open ) ) { - push_scope(); + eat( TokType::BraceSquare_Open ); + // [ - Token start = currtok; - s32 len = 0; - - // There can be more than one attribute. If there is flatten them to a single string. - // TODO(Ed): Support keeping an linked list of attributes similar to parameters - while ( left && currtok.is_attribute() ) + if ( left == 0 ) { - if ( check( TokType::Attribute_Open ) ) - { - eat( TokType::Attribute_Open ); - // [[ - - while ( left && currtok.Type != TokType::Attribute_Close ) - { - eat( currtok.Type ); - } - // [[ - - eat( TokType::Attribute_Close ); - // [[ ]] - - len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text; - } - else if ( check( TokType::Decl_GNU_Attribute ) ) - { - eat( TokType::Decl_GNU_Attribute ); - eat( TokType::Capture_Start ); - eat( TokType::Capture_Start ); - // __attribute__(( - - while ( left && currtok.Type != TokType::Capture_End ) - { - eat( currtok.Type ); - } - // __attribute__(( - - eat( TokType::Capture_End ); - eat( TokType::Capture_End ); - // __attribute__(( )) - - len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text; - } - else if ( check( TokType::Decl_MSVC_Attribute ) ) - { - eat( TokType::Decl_MSVC_Attribute ); - eat( TokType::Capture_Start ); - // __declspec( - - while ( left && currtok.Type != TokType::Capture_End ) - { - eat( currtok.Type ); - } - // __declspec( - - eat( TokType::Capture_End ); - // __declspec( ) - - len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text; - } - else if ( currtok.is_attribute() ) - { - eat( currtok.Type ); - // - - // If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...) - if ( check( TokType::Capture_Start ) ) - { - eat( TokType::Capture_Start ); - - s32 level = 0; - while ( left && currtok.Type != TokType::Capture_End && level == 0 ) - { - if ( currtok.Type == TokType::Capture_Start ) - ++level; - if ( currtok.Type == TokType::Capture_End ) - --level; - eat( currtok.Type ); - } - eat( TokType::Capture_End ); - } - - len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text; - // ( ... ) - } - } - - if ( len > 0 ) - { - StrC attribute_txt = { len, start.Text }; + log_failure( "Error, unexpected end of array declaration ( '[]' scope started )\n%s", Context.to_string() ); Context.pop(); - - String name_stripped = strip_formatting( attribute_txt, strip_formatting_dont_preserve_newlines ); - - Code result = make_code(); - result->Type = ECode::PlatformAttributes; - result->Name = get_cached_string( name_stripped ); - result->Content = result->Name; - // result->Token = - - return (CodeAttributes)result; - } - - Context.pop(); - return { nullptr }; - } - - internal Code parse_class_struct( TokType which, bool inplace_def = false ) - { - if ( which != TokType::Decl_Class && which != TokType::Decl_Struct ) - { - log_failure( "Error, expected class or struct, not %s\n%s", ETokType::to_str( which ), Context.to_string() ); return CodeInvalid; } - Token name { nullptr, 0, TokType::Invalid }; - - AccessSpec access = AccessSpec::Default; - CodeType parent = { nullptr }; - CodeBody body = { nullptr }; - CodeAttributes attributes = { nullptr }; - ModuleFlag mflags = ModuleFlag::None; - - CodeClass result = CodeInvalid; - - if ( check( TokType::Module_Export ) ) + if ( currtok.Type == TokType::BraceSquare_Close ) { - mflags = ModuleFlag::Export; - eat( TokType::Module_Export ); + log_failure( "Error, empty array expression in definition\n%s", Context.to_string() ); + Context.pop(); + return CodeInvalid; } - // - eat( which ); - // + Token untyped_tok = currtok; - attributes = parse_attributes(); - // - - if ( check( TokType::Identifier ) ) + while ( left && currtok.Type != TokType::BraceSquare_Close ) { - name = parse_identifier(); - Context.Scope->Name = name; + eat( currtok.Type ); } - // - local_persist char interface_arr_mem[kilobytes( 4 )] { 0 }; - Array interfaces = Array::init_reserve( Arena::init_from_memory( interface_arr_mem, kilobytes( 4 ) ), 4 ); + untyped_tok.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)untyped_tok.Text; - // TODO(Ed) : Make an AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them. - if ( check( TokType::Assign_Classifer ) ) + Code array_expr = untyped_str( untyped_tok ); + // [ + + if ( left == 0 ) { - eat( TokType::Assign_Classifer ); - // : + log_failure( "Error, unexpected end of array declaration, expected ]\n%s", Context.to_string() ); + Context.pop(); + return CodeInvalid; + } + + if ( currtok.Type != TokType::BraceSquare_Close ) + { + log_failure( "%s: Error, expected ] in array declaration, not %s\n%s", ETokType::to_str( currtok.Type ), Context.to_string() ); + Context.pop(); + return CodeInvalid; + } + + eat( TokType::BraceSquare_Close ); + // [ ] + + // Its a multi-dimensional array + if ( check( TokType::BraceSquare_Open )) + { + Code adjacent_arr_expr = parse_array_decl(); + // [ ][ ]... + + array_expr->Next = adjacent_arr_expr.ast; + } + + Context.pop(); + return array_expr; + } + + Context.pop(); + return { nullptr }; +} + +internal inline +CodeAttributes parse_attributes() +{ + push_scope(); + + Token start = currtok; + s32 len = 0; + + // There can be more than one attribute. If there is flatten them to a single string. + // TODO(Ed): Support keeping an linked list of attributes similar to parameters + while ( left && currtok.is_attribute() ) + { + if ( check( TokType::Attribute_Open ) ) + { + eat( TokType::Attribute_Open ); + // [[ + + while ( left && currtok.Type != TokType::Attribute_Close ) + { + eat( currtok.Type ); + } + // [[ + + eat( TokType::Attribute_Close ); + // [[ ]] + + len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text; + } + else if ( check( TokType::Decl_GNU_Attribute ) ) + { + eat( TokType::Decl_GNU_Attribute ); + eat( TokType::Capture_Start ); + eat( TokType::Capture_Start ); + // __attribute__(( + + while ( left && currtok.Type != TokType::Capture_End ) + { + eat( currtok.Type ); + } + // __attribute__(( + + eat( TokType::Capture_End ); + eat( TokType::Capture_End ); + // __attribute__(( )) + + len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text; + } + else if ( check( TokType::Decl_MSVC_Attribute ) ) + { + eat( TokType::Decl_MSVC_Attribute ); + eat( TokType::Capture_Start ); + // __declspec( + + while ( left && currtok.Type != TokType::Capture_End ) + { + eat( currtok.Type ); + } + // __declspec( + + eat( TokType::Capture_End ); + // __declspec( ) + + len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text; + } + else if ( currtok.is_attribute() ) + { + eat( currtok.Type ); + // + + // If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...) + if ( check( TokType::Capture_Start)) + { + eat( TokType::Capture_Start ); + + s32 level = 0; + while (left && currtok.Type != TokType::Capture_End && level == 0) + { + if (currtok.Type == TokType::Capture_Start) + ++ level; + if (currtok.Type == TokType::Capture_End) + --level; + eat(currtok.Type); + } + eat(TokType::Capture_End); + } + + len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text; + // ( ... ) + } + } + + if ( len > 0 ) + { + StrC attribute_txt = { len, start.Text }; + Context.pop(); + + String name_stripped = strip_formatting( attribute_txt, strip_formatting_dont_preserve_newlines ); + + Code result = make_code(); + result->Type = ECode::PlatformAttributes; + result->Name = get_cached_string( name_stripped ); + result->Content = result->Name; + // result->Token = + + return ( CodeAttributes )result; + } + + Context.pop(); + return { nullptr }; +} + +internal +Code parse_class_struct( TokType which, bool inplace_def = false ) +{ + if ( which != TokType::Decl_Class && which != TokType::Decl_Struct ) + { + log_failure( "Error, expected class or struct, not %s\n%s", ETokType::to_str( which ), Context.to_string() ); + return CodeInvalid; + } + + Token name { nullptr, 0, TokType::Invalid }; + + AccessSpec access = AccessSpec::Default; + CodeType parent = { nullptr }; + CodeBody body = { nullptr }; + CodeAttributes attributes = { nullptr }; + ModuleFlag mflags = ModuleFlag::None; + + CodeClass result = CodeInvalid; + + if ( check(TokType::Module_Export) ) + { + mflags = ModuleFlag::Export; + eat( TokType::Module_Export ); + } + // + + eat( which ); + // + + attributes = parse_attributes(); + // + + if ( check( TokType::Identifier ) ) + { + name = parse_identifier(); + Context.Scope->Name = name; + } + // + + local_persist + char interface_arr_mem[ kilobytes(4) ] {0}; + Array interfaces = Array::init_reserve( Arena::init_from_memory(interface_arr_mem, kilobytes(4) ), 4 ); + + // TODO(Ed) : Make an AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them. + if ( check( TokType::Assign_Classifer ) ) + { + eat( TokType::Assign_Classifer ); + // : + + if ( currtok.is_access_specifier() ) + { + access = currtok.to_access_specifier(); + // : + eat( currtok.Type ); + } + + Token parent_tok = parse_identifier(); + parent = def_type( parent_tok ); + // : + + while ( check(TokType::Comma) ) + { + eat( TokType::Comma ); + // : , if ( currtok.is_access_specifier() ) { - access = currtok.to_access_specifier(); - // : - eat( currtok.Type ); + eat(currtok.Type); } + Token interface_tok = parse_identifier(); - Token parent_tok = parse_identifier(); - parent = def_type( parent_tok ); - // : - - while ( check( TokType::Comma ) ) - { - eat( TokType::Comma ); - // : , - - if ( currtok.is_access_specifier() ) - { - eat( currtok.Type ); - } - Token interface_tok = parse_identifier(); - - interfaces.append( def_type( interface_tok ) ); - // : , ... - } - } - - if ( check( TokType::BraceCurly_Open ) ) - { - body = parse_class_struct_body( which, name ); - } - // : , ... { } - - CodeComment inline_cmt = NoCode; - if ( ! inplace_def ) - { - Token stmt_end = currtok; - eat( TokType::Statement_End ); - // : , ... { }; - - if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line ) - inline_cmt = parse_comment(); - // : , ... { }; - } - - if ( which == TokType::Decl_Class ) - result = def_class( name, body, parent, access, attributes, mflags ); - - else - result = def_struct( name, body, (CodeType)parent, access, attributes, mflags ); - - if ( inline_cmt ) - result->InlineCmt = inline_cmt; - - interfaces.free(); - return result; - } - - internal neverinline CodeBody parse_class_struct_body( TokType which, Token name ) - { - using namespace ECode; - push_scope(); - - eat( TokType::BraceCurly_Open ); - // { - - CodeBody result = (CodeBody)make_code(); - - if ( which == TokType::Decl_Class ) - result->Type = Class_Body; - - else - result->Type = Struct_Body; - - while ( left && currtok_noskip.Type != TokType::BraceCurly_Close ) - { - Code member = Code::Invalid; - CodeAttributes attributes = { nullptr }; - CodeSpecifiers specifiers = { nullptr }; - - bool expects_function = false; - - // Context.Scope->Start = currtok_noskip; - - if ( currtok_noskip.Type == TokType::Preprocess_Hash ) - eat( TokType::Preprocess_Hash ); - - switch ( currtok_noskip.Type ) - { - case TokType::Statement_End : - { - // TODO(Ed): Convert this to a general warning procedure - log_fmt( "Dangling end statement found %S\n", currtok_noskip.to_string() ); - eat( TokType::Statement_End ); - continue; - } - case TokType::NewLine : - member = fmt_newline; - eat( TokType::NewLine ); - break; - - case TokType::Comment : - member = parse_comment(); - break; - - case TokType::Access_Public : - member = access_public; - eat( TokType::Access_Public ); - eat( TokType::Assign_Classifer ); - // public: - break; - - case TokType::Access_Protected : - member = access_protected; - eat( TokType::Access_Protected ); - eat( TokType::Assign_Classifer ); - // protected: - break; - - case TokType::Access_Private : - member = access_private; - eat( TokType::Access_Private ); - eat( TokType::Assign_Classifer ); - // private: - break; - - case TokType::Decl_Class : - member = parse_complicated_definition( TokType::Decl_Class ); - // class - break; - - case TokType::Decl_Enum : - member = parse_complicated_definition( TokType::Decl_Enum ); - // enum - break; - - case TokType::Decl_Friend : - member = parse_friend(); - // friend - break; - - case TokType::Decl_Operator : - member = parse_operator_cast(); - // operator () - break; - - case TokType::Decl_Struct : - member = parse_complicated_definition( TokType::Decl_Struct ); - // struct - break; - - case TokType::Decl_Template : - member = parse_template(); - // template< ... > - break; - - case TokType::Decl_Typedef : - member = parse_typedef(); - // typedef - break; - - case TokType::Decl_Union : - member = parse_complicated_definition( TokType::Decl_Union ); - // union - break; - - case TokType::Decl_Using : - member = parse_using(); - // using - break; - - case TokType::Operator : - if ( currtok.Text[0] != '~' ) - { - log_failure( "Operator token found in global body but not destructor unary negation\n%s", Context.to_string() ); - return CodeInvalid; - } - - member = parse_destructor(); - // ~() - break; - - case TokType::Preprocess_Define : - member = parse_define(); - // #define - break; - - case TokType::Preprocess_Include : - member = parse_include(); - // #include - break; - - case TokType::Preprocess_If : - case TokType::Preprocess_IfDef : - case TokType::Preprocess_IfNotDef : - case TokType::Preprocess_ElIf : - member = parse_preprocess_cond(); - // # - break; - - case TokType::Preprocess_Else : - member = preprocess_else; - eat( TokType::Preprocess_Else ); - // #else - break; - - case TokType::Preprocess_EndIf : - member = preprocess_endif; - eat( TokType::Preprocess_EndIf ); - // #endif - break; - - case TokType::Preprocess_Macro : - member = parse_simple_preprocess( TokType::Preprocess_Macro ); - // - break; - - case TokType::Preprocess_Pragma : - member = parse_pragma(); - // #pragma - break; - - case TokType::Preprocess_Unsupported : - member = parse_simple_preprocess( TokType::Preprocess_Unsupported ); - // # - break; - - case TokType::StaticAssert : - member = parse_static_assert(); - // static_assert - break; - - case TokType::Attribute_Open : - case TokType::Decl_GNU_Attribute : - case TokType::Decl_MSVC_Attribute : -#define Entry( attribute, str ) case TokType::attribute : - GEN_DEFINE_ATTRIBUTE_TOKENS -#undef Entry - { - attributes = parse_attributes(); - // - } - //! Fallthrough intended - case TokType::Spec_Consteval : - case TokType::Spec_Constexpr : - case TokType::Spec_Constinit : - case TokType::Spec_Explicit : - case TokType::Spec_ForceInline : - case TokType::Spec_Inline : - case TokType::Spec_Mutable : - case TokType::Spec_NeverInline : - case TokType::Spec_Static : - case TokType::Spec_Volatile : - case TokType::Spec_Virtual : - { - SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; - s32 NumSpecifiers = 0; - - while ( left && currtok.is_specifier() ) - { - SpecifierT spec = ESpecifier::to_type( currtok ); - - b32 ignore_spec = false; - - switch ( spec ) - { - case ESpecifier::Constexpr : - case ESpecifier::Constinit : - case ESpecifier::Explicit : - case ESpecifier::Inline : - case ESpecifier::ForceInline : - case ESpecifier::Mutable : - case ESpecifier::NeverInline : - case ESpecifier::Static : - case ESpecifier::Volatile : - case ESpecifier::Virtual : - break; - - case ESpecifier::Consteval : - expects_function = true; - break; - - case ESpecifier::Const : - ignore_spec = true; - break; - - default : - log_failure( "Invalid specifier %s for variable\n%s", ESpecifier::to_str( spec ), Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - // Every specifier after would be considered part of the type type signature - if ( ignore_spec ) - break; - - specs_found[NumSpecifiers] = spec; - NumSpecifiers++; - eat( currtok.Type ); - } - - if ( NumSpecifiers ) - { - specifiers = def_specifiers( NumSpecifiers, specs_found ); - } - // - - if ( currtok.is_attribute() ) - { - // Unfortuantely Unreal has code where there is attirbutes before specifiers - CodeAttributes more_attributes = parse_attributes(); - - if ( attributes ) - { - String fused = String::make_reserve( GlobalAllocator, attributes->Content.length() + more_attributes->Content.length() ); - fused.append_fmt( "%S %S", attributes->Content, more_attributes->Content ); - - attributes->Name = get_cached_string( fused ); - attributes->Content = attributes->Name; - // - } - - attributes = more_attributes; - } - - if ( currtok.Type == TokType::Operator && currtok.Text[0] == '~' ) - { - member = parse_destructor( specifiers ); - // ~() - break; - } - - if ( currtok.Type == TokType::Decl_Operator ) - { - member = parse_operator_cast( specifiers ); - // operator () - break; - } - } - //! Fallthrough intentional - case TokType::Identifier : - case TokType::Spec_Const : - case TokType::Type_Unsigned : - case TokType::Type_Signed : - case TokType::Type_Short : - case TokType::Type_Long : - case TokType::Type_bool : - case TokType::Type_char : - case TokType::Type_int : - case TokType::Type_double : - { - if ( nexttok.Type == TokType::Capture_Start && name.Length && currtok.Type == TokType::Identifier ) - { - if ( str_compare( name.Text, currtok.Text, name.Length ) == 0 ) - { - member = parse_constructor( specifiers ); - // () - break; - } - } - - member = parse_operator_function_or_variable( expects_function, attributes, specifiers ); - // operator ... - // or - // ... - } - break; - - default : - Token untyped_tok = currtok; - - while ( left && currtok.Type != TokType::BraceCurly_Close ) - { - untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text; - eat( currtok.Type ); - } - - member = untyped_str( untyped_tok ); - // Something unknown - break; - } - - if ( member == Code::Invalid ) - { - log_failure( "Failed to parse member\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - result.append( member ); - } - - eat( TokType::BraceCurly_Close ); - // { } - Context.pop(); - return result; - } - - internal CodeComment parse_comment() - { - StackNode scope { nullptr, currtok_noskip, NullToken, txt( __func__ ) }; - Context.push( &scope ); - - CodeComment result = (CodeComment)make_code(); - result->Type = ECode::Comment; - result->Content = get_cached_string( currtok_noskip ); - result->Name = result->Content; - // result->Token = currtok_noskip; - eat( TokType::Comment ); - - Context.pop(); - return result; - } - - internal Code parse_complicated_definition( TokType which ) - { - push_scope(); - - bool is_inplace = false; - - TokArray tokens = Context.Tokens; - - s32 idx = tokens.Idx; - s32 level = 0; - for ( ; idx < tokens.Arr.num(); idx++ ) - { - if ( tokens[idx].Type == TokType::BraceCurly_Open ) - level++; - - if ( tokens[idx].Type == TokType::BraceCurly_Close ) - level--; - - if ( level == 0 && tokens[idx].Type == TokType::Statement_End ) - break; - } - - if ( ( idx - 2 ) == tokens.Idx ) - { - // Its a forward declaration only - Code result = parse_forward_or_definition( which, is_inplace ); - // ; - Context.pop(); - return result; - } - - Token tok = tokens[idx - 1]; - if ( tok.is_specifier() && is_trailing( ESpecifier::to_type( tok ) ) ) - { - // (...) ...; - - s32 spec_idx = idx - 1; - Token spec = tokens[spec_idx]; - while ( spec.is_specifier() && is_trailing( ESpecifier::to_type( spec ) ) ) - { - --spec_idx; - spec = tokens[spec_idx]; - } - - if ( tokens[spec_idx].Type == TokType::Capture_End ) - { - // Forward declaration with trailing specifiers for a procedure - tok = tokens[spec_idx]; - - Code result = parse_operator_function_or_variable( false, { nullptr }, { nullptr } ); - // , or Name> ... - Context.pop(); - return result; - } - - log_failure( "Unsupported or bad member definition after %s declaration\n%s", to_str( which ), Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - if ( tok.Type == TokType::Identifier ) - { - tok = tokens[idx - 2]; - bool is_indirection = tok.Type == TokType::Ampersand || tok.Type == TokType::Star; - bool ok_to_parse = false; - - if ( tok.Type == TokType::BraceCurly_Close ) - { - // Its an inplace definition - // { ... } ; - ok_to_parse = true; - is_inplace = true; - } - else if ( tok.Type == TokType::Identifier && tokens[idx - 3].Type == which ) - { - // Its a variable with type ID using namespace. - // ; - ok_to_parse = true; - } - else if ( tok.Type == TokType::Assign_Classifer - && ( ( tokens[idx - 5].Type == which && tokens[idx - 4].Type == TokType::Decl_Class ) || ( tokens[idx - 4].Type == which ) ) ) - { - // Its a forward declaration of an enum - // : ; - // : ; - ok_to_parse = true; - Code result = parse_enum(); - Context.pop(); - return result; - } - else if ( is_indirection ) - { - // Its a indirection type with type ID using struct namespace. - // * ; - ok_to_parse = true; - } - - if ( ! ok_to_parse ) - { - log_failure( "Unsupported or bad member definition after %s declaration\n%s", to_str( which ), Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - Code result = parse_operator_function_or_variable( false, { nullptr }, { nullptr } ); - // , or Name> ... - Context.pop(); - return result; - } - else if ( tok.Type >= TokType::Type_Unsigned && tok.Type <= TokType::Type_MS_W64 ) - { - tok = tokens[idx - 2]; - - if ( tok.Type != TokType::Assign_Classifer - || ( ( tokens[idx - 5].Type != which && tokens[idx - 4].Type != TokType::Decl_Class ) && ( tokens[idx - 4].Type != which ) ) ) - { - log_failure( "Unsupported or bad member definition after %s declaration\n%s", to_str( which ), Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - // Its a forward declaration of an enum class - // : ; - // : ; - Code result = parse_enum(); - Context.pop(); - return result; - } - else if ( tok.Type == TokType::BraceCurly_Close ) - { - // Its a definition - Code result = parse_forward_or_definition( which, is_inplace ); - // { ... }; - Context.pop(); - return result; - } - else if ( tok.Type == TokType::BraceSquare_Close ) - { - // Its an array definition - Code result = parse_operator_function_or_variable( false, { nullptr }, { nullptr } ); - // [ ... ]; - Context.pop(); - return result; - } - else - { - log_failure( "Unsupported or bad member definition after %s declaration\n%S", to_str( which ).Ptr, Context.to_string() ); - Context.pop(); - return CodeInvalid; + interfaces.append( def_type( interface_tok ) ); + // : , ... } } - internal inline CodeDefine parse_define() + if ( check( TokType::BraceCurly_Open ) ) { - push_scope(); - eat( TokType::Preprocess_Define ); - // #define - - CodeDefine define = (CodeDefine)make_code(); - define->Type = ECode::Preprocess_Define; - - if ( ! check( TokType::Identifier ) ) - { - log_failure( "Error, expected identifier after #define\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - Context.Scope->Name = currtok; - define->Name = get_cached_string( currtok ); - eat( TokType::Identifier ); - // #define - - if ( ! check( TokType::Preprocess_Content ) ) - { - log_failure( "Error, expected content after #define %s\n%s", define->Name, Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - if ( currtok.Length == 0 ) - { - define->Content = get_cached_string( currtok ); - eat( TokType::Preprocess_Content ); - // #define - - Context.pop(); - return define; - } - - define->Content = get_cached_string( strip_formatting( currtok, strip_formatting_dont_preserve_newlines ) ); - eat( TokType::Preprocess_Content ); - // #define - - Context.pop(); - return define; + body = parse_class_struct_body( which, name ); } + // : , ... { } - internal inline Code parse_assignment_expression() + CodeComment inline_cmt = NoCode; + if ( ! inplace_def ) { - Code expr = { nullptr }; - - eat( TokType::Operator ); - // = - - Token expr_tok = currtok; - - if ( currtok.Type == TokType::Statement_End && currtok.Type != TokType::Comma ) - { - log_failure( "Expected expression after assignment operator\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - s32 level = 0; - while ( left && currtok.Type != TokType::Statement_End && ( currtok.Type != TokType::Comma || level > 0 ) ) - { - if ( currtok.Type == TokType::BraceCurly_Open ) - level++; - if ( currtok.Type == TokType::BraceCurly_Close ) - level--; - if ( currtok.Type == TokType::Capture_Start ) - level++; - else if ( currtok.Type == TokType::Capture_End ) - level--; - - eat( currtok.Type ); - } - - expr_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)expr_tok.Text - 1; - expr = untyped_str( expr_tok ); - // = - return expr; - } - - internal inline Code parse_forward_or_definition( TokType which, bool is_inplace ) - { - Code result = CodeInvalid; - - switch ( which ) - { - case TokType::Decl_Class : - result = parse_class( is_inplace ); - return result; - - case TokType::Decl_Enum : - result = parse_enum( is_inplace ); - return result; - - case TokType::Decl_Struct : - result = parse_struct( is_inplace ); - return result; - - case TokType::Decl_Union : - result = parse_union( is_inplace ); - return result; - - default : - log_failure( - "Error, wrong token type given to parse_complicated_definition " - "(only supports class, enum, struct, union) \n%s", - Context.to_string() - ); - - return CodeInvalid; - } - } - - // Function parsing is handled in multiple places because its initial signature is shared with variable parsing - internal inline CodeFn parse_function_after_name( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeType ret_type, Token name ) - { - push_scope(); - CodeParam params = parse_params(); - // ( ) - - // TODO(Ed), Review old comment : These have to be kept separate from the return type's specifiers. - while ( left && currtok.is_specifier() ) - { - if ( specifiers.ast == nullptr ) - { - specifiers = def_specifier( ESpecifier::to_type( currtok ) ); - eat( currtok.Type ); - continue; - } - - specifiers.append( ESpecifier::to_type( currtok ) ); - eat( currtok.Type ); - } - // ( ) - - CodeBody body = NoCode; - CodeComment inline_cmt = NoCode; - if ( check( TokType::BraceCurly_Open ) ) - { - body = parse_function_body(); - if ( body == Code::Invalid ) - { - Context.pop(); - return CodeInvalid; - } - // ( ) { } - } - else if ( check( TokType::Operator ) && currtok.Text[0] == '=' ) - { - eat( TokType::Operator ); - specifiers.append( ESpecifier::Pure ); - - eat( TokType::Number ); - Token stmt_end = currtok; - eat( TokType::Statement_End ); - // ( ) = 0; - - if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line ) - inline_cmt = parse_comment(); - // ( ) ; - } - else - { - Token stmt_end = currtok; - eat( TokType::Statement_End ); - // ( ) ; - - if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line ) - inline_cmt = parse_comment(); - // ( ) ; - } - - using namespace ECode; - - String name_stripped = String::make( GlobalAllocator, name ); - name_stripped.strip_space(); - - CodeFn result = (CodeFn)make_code(); - result->Name = get_cached_string( name_stripped ); - result->ModuleFlags = mflags; - - if ( body ) - { - switch ( body->Type ) - { - case Function_Body : - case Untyped : - break; - - default : - { - log_failure( "Body must be either of Function_Body or Untyped type, %s\n%s", body.debug_str(), Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - } - - result->Type = Function; - result->Body = body; - } - else - { - result->Type = Function_Fwd; - } - - if ( attributes ) - result->Attributes = attributes; - - if ( specifiers ) - result->Specs = specifiers; - - result->ReturnType = ret_type; - - if ( params ) - result->Params = params; - - if ( inline_cmt ) - result->InlineCmt = inline_cmt; - - Context.pop(); - return result; - } - - internal Code parse_function_body() - { - using namespace ECode; - push_scope(); - - eat( TokType::BraceCurly_Open ); - - CodeBody result = (CodeBody)make_code(); - result->Type = Function_Body; - - // TODO : Support actual parsing of function body - Token start = currtok_noskip; - - s32 level = 0; - while ( left && ( currtok_noskip.Type != TokType::BraceCurly_Close || level > 0 ) ) - { - if ( currtok_noskip.Type == TokType::BraceCurly_Open ) - level++; - - else if ( currtok_noskip.Type == TokType::BraceCurly_Close && level > 0 ) - level--; - - eat( currtok_noskip.Type ); - } - - Token previous = prevtok; - - s32 len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text; - - if ( len > 0 ) - { - result.append( def_execution( { len, start.Text } ) ); - } - - eat( TokType::BraceCurly_Close ); - - Context.pop(); - return result; - } - - internal neverinline CodeBody parse_global_nspace( CodeT which ) - { - using namespace ECode; - - push_scope(); - - if ( which != Namespace_Body && which != Global_Body && which != Export_Body && which != Extern_Linkage_Body ) - return CodeInvalid; - - if ( which != Global_Body ) - eat( TokType::BraceCurly_Open ); - // { - - CodeBody result = (CodeBody)make_code(); - result->Type = which; - - while ( left && currtok_noskip.Type != TokType::BraceCurly_Close ) - { - Code member = Code::Invalid; - CodeAttributes attributes = { nullptr }; - CodeSpecifiers specifiers = { nullptr }; - - bool expects_function = false; - - // Context.Scope->Start = currtok_noskip; - - if ( currtok_noskip.Type == TokType::Preprocess_Hash ) - eat( TokType::Preprocess_Hash ); - - switch ( currtok_noskip.Type ) - { - case TokType::Statement_End : - { - // TODO(Ed): Convert this to a general warning procedure - log_fmt( "Dangling end statement found %S\n", currtok_noskip.to_string() ); - eat( TokType::Statement_End ); - continue; - } - case TokType::NewLine : - // Empty lines are auto skipped by Tokens.current() - member = fmt_newline; - eat( TokType::NewLine ); - break; - - case TokType::Comment : - member = parse_comment(); - break; - - case TokType::Decl_Class : - member = parse_complicated_definition( TokType::Decl_Class ); - // class - break; - - case TokType::Decl_Enum : - member = parse_complicated_definition( TokType::Decl_Enum ); - // enum - break; - - case TokType::Decl_Extern_Linkage : - if ( which == Extern_Linkage_Body ) - log_failure( "Nested extern linkage\n%s", Context.to_string() ); - - member = parse_extern_link(); - // extern "..." { ... } - break; - - case TokType::Decl_Namespace : - member = parse_namespace(); - // namespace { ... } - break; - - case TokType::Decl_Struct : - member = parse_complicated_definition( TokType::Decl_Struct ); - // struct ... - break; - - case TokType::Decl_Template : - member = parse_template(); - // template<...> ... - break; - - case TokType::Decl_Typedef : - member = parse_typedef(); - // typedef ... - break; - - case TokType::Decl_Union : - member = parse_complicated_definition( TokType::Decl_Union ); - // union ... - break; - - case TokType::Decl_Using : - member = parse_using(); - // using ... - break; - - case TokType::Preprocess_Define : - member = parse_define(); - // #define ... - break; - - case TokType::Preprocess_Include : - member = parse_include(); - // #include ... - break; - - case TokType::Preprocess_If : - case TokType::Preprocess_IfDef : - case TokType::Preprocess_IfNotDef : - case TokType::Preprocess_ElIf : - member = parse_preprocess_cond(); - // # ... - break; - - case TokType::Preprocess_Else : - member = preprocess_else; - eat( TokType::Preprocess_Else ); - // #else - break; - - case TokType::Preprocess_EndIf : - member = preprocess_endif; - eat( TokType::Preprocess_EndIf ); - // #endif - break; - - case TokType::Preprocess_Macro : - member = parse_simple_preprocess( TokType::Preprocess_Macro ); - // - break; - - case TokType::Preprocess_Pragma : - member = parse_pragma(); - // #pragma ... - break; - - case TokType::Preprocess_Unsupported : - member = parse_simple_preprocess( TokType::Preprocess_Unsupported ); - // # ... - break; - - case TokType::StaticAssert : - member = parse_static_assert(); - // static_assert( , ... ); - break; - - case TokType::Module_Export : - if ( which == Export_Body ) - log_failure( "Nested export declaration\n%s", Context.to_string() ); - - member = parse_export_body(); - // export { ... } - break; - - case TokType::Module_Import : - { - not_implemented( context ); - // import ... - } - //! Fallthrough intentional - case TokType::Attribute_Open : - case TokType::Decl_GNU_Attribute : - case TokType::Decl_MSVC_Attribute : -#define Entry( attribute, str ) case TokType::attribute : - GEN_DEFINE_ATTRIBUTE_TOKENS -#undef Entry - { - attributes = parse_attributes(); - // - } - //! Fallthrough intentional - case TokType::Spec_Consteval : - case TokType::Spec_Constexpr : - case TokType::Spec_Constinit : - case TokType::Spec_Extern : - case TokType::Spec_ForceInline : - case TokType::Spec_Global : - case TokType::Spec_Inline : - case TokType::Spec_Internal_Linkage : - case TokType::Spec_NeverInline : - case TokType::Spec_Static : - { - SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; - s32 NumSpecifiers = 0; - - while ( left && currtok.is_specifier() ) - { - SpecifierT spec = ESpecifier::to_type( currtok ); - - bool ignore_spec = false; - - switch ( spec ) - { - case ESpecifier::Constexpr : - case ESpecifier::Constinit : - case ESpecifier::ForceInline : - case ESpecifier::Global : - case ESpecifier::External_Linkage : - case ESpecifier::Internal_Linkage : - case ESpecifier::Inline : - case ESpecifier::Mutable : - case ESpecifier::NeverInline : - case ESpecifier::Static : - case ESpecifier::Volatile : - break; - - case ESpecifier::Consteval : - expects_function = true; - break; - - case ESpecifier::Const : - ignore_spec = true; - break; - - default : - StrC spec_str = ESpecifier::to_str( spec ); - - log_failure( "Invalid specifier %.*s for variable\n%s", spec_str.Len, spec_str, Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - if ( ignore_spec ) - break; - - specs_found[NumSpecifiers] = spec; - NumSpecifiers++; - eat( currtok.Type ); - } - - if ( NumSpecifiers ) - { - specifiers = def_specifiers( NumSpecifiers, specs_found ); - } - // - } - //! Fallthrough intentional - case TokType::Identifier : - case TokType::Spec_Const : - case TokType::Type_Long : - case TokType::Type_Short : - case TokType::Type_Signed : - case TokType::Type_Unsigned : - case TokType::Type_bool : - case TokType::Type_char : - case TokType::Type_double : - case TokType::Type_int : - { - Code constructor_destructor = parse_global_nspace_constructor_destructor( specifiers ); - // Possible constructor implemented at global file scope. - if ( constructor_destructor ) - { - member = constructor_destructor; - break; - } - - bool found_operator_cast_outside_class_implmentation = false; - s32 idx = Context.Tokens.Idx; - - for ( ; idx < Context.Tokens.Arr.num(); idx++ ) - { - Token tok = Context.Tokens[idx]; - - if ( tok.Type == TokType::Identifier ) - { - idx++; - tok = Context.Tokens[idx]; - if ( tok.Type == TokType::Access_StaticSymbol ) - continue; - - break; - } - - if ( tok.Type == TokType::Decl_Operator ) - found_operator_cast_outside_class_implmentation = true; - - break; - } - - if ( found_operator_cast_outside_class_implmentation ) - { - member = parse_operator_cast( specifiers ); - // ::operator () { ... } - break; - } - - member = parse_operator_function_or_variable( expects_function, attributes, specifiers ); - // ... - } - } - - if ( member == Code::Invalid ) - { - log_failure( "Failed to parse member\n%s", Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - // log_fmt("Global Body Member: %s", member->debug_str()); - result.append( member ); - } - - if ( which != Global_Body ) - eat( TokType::BraceCurly_Close ); - // { } - - Context.pop(); - return result; - } - - internal inline Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) - { - Code result = { nullptr }; - - /* - To check if a definition is for a constructor we can go straight to the opening parenthesis for its parameters - From There we work backwards to see if we come across two identifiers with the same name between an member access - :: operator, there can be template parameters on the left of the :: so we ignore those. - Whats important is that its back to back. - - This has multiple possible faults. What we parse using this method may not filter out if something has a "return type" - This is bad since technically you could have a namespace nested into another namespace with the same name. - If this awful pattern is done the only way to distiguish with this coarse parse is to know there is no return type defined. - - TODO(Ed): We could fix this by attempting to parse a type, but we would have to have a way to have it soft fail and rollback. - */ - TokArray tokens = Context.Tokens; - - s32 idx = tokens.Idx; - Token nav = tokens[idx]; - for ( ; idx < tokens.Arr.num(); idx++, nav = tokens[idx] ) - { - if ( nav.Text[0] == '<' ) - { - // Skip templated expressions as they mey have expressions with the () operators - s32 capture_level = 0; - s32 template_level = 0; - for ( ; idx < tokens.Arr.num(); idx++, nav = tokens[idx] ) - { - if ( nav.Text[0] == '<' ) - ++template_level; - - if ( nav.Text[0] == '>' ) - --template_level; - if ( nav.Type == TokType::Operator && nav.Text[1] == '>' ) - --template_level; - - if ( nav.Type == ETokType::Capture_Start ) - { - if ( template_level != 0 ) - ++capture_level; - else - break; - } - - if ( template_level != 0 && nav.Type == ETokType::Capture_End ) - --capture_level; - } - } - - if ( nav.Type == TokType::Capture_Start ) - break; - } - - --idx; - Token tok_right = tokens[idx]; - Token tok_left = NullToken; - - if ( tok_right.Type != TokType::Identifier ) - { - // We're not dealing with a constructor if there is no identifier right before the opening of a parameter's scope. - return result; - } - - --idx; - tok_left = tokens[idx]; - // ... - - bool possible_destructor = false; - if ( tok_left.Type == TokType::Operator && tok_left.Text[0] == '~' ) - { - possible_destructor = true; - --idx; - tok_left = tokens[idx]; - } - - if ( tok_left.Type != TokType::Access_StaticSymbol ) - return result; - - --idx; - tok_left = tokens[idx]; - // ... :: - - // We search toward the left until we find the next valid identifier - s32 capture_level = 0; - s32 template_level = 0; - while ( idx != tokens.Idx ) - { - if ( tok_left.Text[0] == '<' ) - ++template_level; - - if ( tok_left.Text[0] == '>' ) - --template_level; - if ( tok_left.Type == TokType::Operator && tok_left.Text[1] == '>' ) - --template_level; - - if ( template_level != 0 && tok_left.Type == ETokType::Capture_Start ) - ++capture_level; - - if ( template_level != 0 && tok_left.Type == ETokType::Capture_End ) - --capture_level; - - if ( capture_level == 0 && template_level == 0 && tok_left.Type == TokType::Identifier ) - break; - - --idx; - tok_left = tokens[idx]; - } - - bool is_same = str_compare( tok_right.Text, tok_left.Text, tok_right.Length ) == 0; - if ( tok_left.Type == TokType::Identifier && is_same ) - { - // We have found the pattern we desired - if ( possible_destructor ) - { - // :: ~ ( - result = parse_destructor( specifiers ); - } - else - { - // :: ( - result = parse_constructor( specifiers ); - } - } - - return result; - } - - // TODO(Ed): I want to eventually change the identifier to its own AST type. - // This would allow distinction of the qualifier for a symbol :: - // This would also allow - internal Token parse_identifier( bool* possible_member_function ) - { - push_scope(); - - Token name = currtok; - Context.Scope->Name = name; - eat( TokType::Identifier ); - // - - parse_template_args( name ); - //