From 39390535ce603fe4285ab16972cfeaea4e3e8ea7 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Mon, 24 Jul 2023 13:44:19 -0400 Subject: [PATCH] Support for interfaces in class/struct. Interfaces are assumed to have the public access specifier for their content (if its a class definition) Started to prepare to segement library code into more files (Less scrolling, need for bootstrapping a tailored version + single header support anyway). --- Readme.md | 2 +- project/Readme.md | 4 + project/{ => dependencies}/gen.dep.cpp | 0 project/{ => dependencies}/gen.dep.hpp | 2 +- project/{ => filesystem}/gen.editor.hpp | 0 project/{ => filesystem}/gen.scanner.hpp | 0 project/gen.cpp | 83 +++++++++++--- project/gen.hpp | 103 +++++++++++++++--- .../{ => helpers}/gen.pop_ignores.inline.hpp | 0 .../{ => helpers}/gen.push_ignores.inline.hpp | 0 project/{ => helpers}/gen.undef.macros.hpp | 0 11 files changed, 166 insertions(+), 28 deletions(-) rename project/{ => dependencies}/gen.dep.cpp (100%) rename project/{ => dependencies}/gen.dep.hpp (99%) rename project/{ => filesystem}/gen.editor.hpp (100%) rename project/{ => filesystem}/gen.scanner.hpp (100%) rename project/{ => helpers}/gen.pop_ignores.inline.hpp (100%) rename project/{ => helpers}/gen.push_ignores.inline.hpp (100%) rename project/{ => helpers}/gen.undef.macros.hpp (100%) diff --git a/Readme.md b/Readme.md index e186864..6e46cc8 100644 --- a/Readme.md +++ b/Readme.md @@ -172,7 +172,7 @@ This method is setup where all the metaprogram's code are the within the same fi * Lambdas (This naturally means its unsupported) * RAII : This needs support for constructors/destructor parsing * I haven't gotten around to yet, only useful (to me) for third-party scanning -* Multiple Inheritance +* Multiple Inheritance : Working on it.. Keywords kept from "Modern C++": diff --git a/project/Readme.md b/project/Readme.md index 7491323..b7b2170 100644 --- a/project/Readme.md +++ b/project/Readme.md @@ -3,16 +3,20 @@ The core library is contained within `gen.hpp` and `gen.cpp`. Things related to the editor and scanner are in their own respective files. (Ex: `gen.scanner.` ) +Dependencies are within `gen.dep.` ## gen.hpp Feature Macros: +* `GEN_DONT_USE_NAMESPACE` : By default, the library is wrapped in a `gen` namespace, this will disable that expose it to the global scope. * `GEN_DONT_ENFORCE_GEN_TIME_GUARD` : By default, the library ( gen.hpp/ gen.cpp ) expects the macro `GEN_TIME` to be defined, this disables that. * `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves. * `GEN_DEFINE_LIBRARY_CORE_CONSTANTS` : Optional typename codes as they are non-standard to C/C++ and not necessary to library usage * `GEN_ENFORCE_STRONG_CODE_TYPES` : Enforces casts to filtered code types. +* `GEN_EXPOSE_BACKEND` : Will expose symbols meant for internal use only. +* `GEN_Define_Attribute_Tokens` : Allows user to define their own attribute macros for use in parsing. `GEN_USE_RECURSIVE_AST_DUPLICATION` is available but its not well tested and should not need to be used. If constructing ASTs properly. There should be no modification of ASTs, and thus this would never become an issue. diff --git a/project/gen.dep.cpp b/project/dependencies/gen.dep.cpp similarity index 100% rename from project/gen.dep.cpp rename to project/dependencies/gen.dep.cpp diff --git a/project/gen.dep.hpp b/project/dependencies/gen.dep.hpp similarity index 99% rename from project/gen.dep.hpp rename to project/dependencies/gen.dep.hpp index cd5e6b3..ac68f2d 100644 --- a/project/gen.dep.hpp +++ b/project/dependencies/gen.dep.hpp @@ -1,4 +1,4 @@ -// This file is intended to be included within gen.hpp (There is pragma diagnostic ignores) +// This file is intended to be included within gen.hpp (There is no pragma diagnostic ignores) #pragma once #pragma region Platform Detection diff --git a/project/gen.editor.hpp b/project/filesystem/gen.editor.hpp similarity index 100% rename from project/gen.editor.hpp rename to project/filesystem/gen.editor.hpp diff --git a/project/gen.scanner.hpp b/project/filesystem/gen.scanner.hpp similarity index 100% rename from project/gen.scanner.hpp rename to project/filesystem/gen.scanner.hpp diff --git a/project/gen.cpp b/project/gen.cpp index add00a0..aa312e6 100644 --- a/project/gen.cpp +++ b/project/gen.cpp @@ -4,12 +4,12 @@ #error Gen.hpp : GEN_TIME not defined #endif -#include "gen.push_ignores.inline.hpp" +#include "helpers/gen.push_ignores.inline.hpp" //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. //! Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl #ifndef GEN_ROLL_OWN_DEPENDENCIES -# include "gen.dep.cpp" +# include "dependencies/gen.dep.cpp" #endif #include "gen.hpp" @@ -478,6 +478,17 @@ String AST::to_string() , ParentType->to_string() , Body->to_string() ); + + CodeType interface = Next->cast(); + if ( interface ) + result.append("\n"); + + while ( interface ) + { + result.append_fmt( ", %s", interface.to_string() ); + + interface = interface->Next->cast(); + } } else { @@ -902,6 +913,17 @@ String AST::to_string() , ParentType->to_string() , Body->to_string() ); + + CodeType interface = Next->cast(); + if ( interface ) + result.append("\n"); + + while ( interface ) + { + result.append_fmt( ", public %s", interface.to_string() ); + + interface = interface->Next->cast(); + } } else { @@ -1182,7 +1204,8 @@ bool AST::validate_body() #pragma endregion AST #pragma region Gen Interface -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, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) { Arena* last = & Global_AllocatorBuckets.back(); @@ -1244,7 +1267,8 @@ 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_StrC("Global Code") ); @@ -2032,7 +2056,8 @@ CodeClass def_class( StrC name , Code body , CodeType parent, AccessSpec parent_access , CodeAttributes attributes - , ModuleFlag mflags ) + , ModuleFlag mflags + , CodeType* interfaces, s32 num_interfaces ) { using namespace ECode; @@ -2085,6 +2110,14 @@ CodeClass def_class( StrC name result->ParentType = parent; } + if ( interfaces ) + { + for (s32 idx = 0; idx < num_interfaces; idx++ ) + { + result.add_interface( interfaces[idx] ); + } + } + return result; } @@ -2523,7 +2556,8 @@ CodeStruct def_struct( StrC name , Code body , CodeType parent, AccessSpec parent_access , CodeAttributes attributes - , ModuleFlag mflags ) + , ModuleFlag mflags + , CodeType* interfaces, s32 num_interfaces ) { using namespace ECode; @@ -2571,6 +2605,14 @@ CodeStruct def_struct( StrC name result->ParentType = parent; } + if ( interfaces ) + { + for (s32 idx = 0; idx < num_interfaces; idx++ ) + { + result.add_interface( interfaces[idx] ); + } + } + return result; } @@ -5162,6 +5204,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con Token name { nullptr, 0, TokType::Invalid }; + AccessSpec access = AccessSpec::Default; CodeType parent = { nullptr }; CodeBody body = { nullptr }; CodeAttributes attributes = { nullptr }; @@ -5182,8 +5225,9 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con if ( check( TokType::Identifier ) ) name = parse_identifier( toks, context ); - AccessSpec access = AccessSpec::Default; - Token parent_tok = { nullptr, 0, TokType::Invalid }; + local_persist + char interface_arr_mem[ kilobytes(4) ] {0}; + Array interfaces = Array::init_reserve( Arena::init_from_memory(interface_arr_mem, kilobytes(4) ), 4 ); if ( check( TokType::Assign_Classifer ) ) { @@ -5194,7 +5238,22 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con access = tok_to_access_specifier( currtok ); } - parent_tok = parse_identifier( toks, context ); + Token parent_tok = parse_identifier( toks, context ); + parent = def_type( parent_tok ); + + while ( check(TokType::Comma) ) + { + eat(TokType::Access_Public); + + if ( tok_is_access_specifier( currtok ) ) + { + eat(currtok.Type); + } + + Token interface_tok = parse_identifier( toks, context ); + + interfaces.append( def_type( interface_tok ) ); + } } if ( check( TokType::BraceCurly_Open ) ) @@ -5204,9 +5263,6 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con eat( TokType::Statement_End ); - if ( parent_tok ) - parent = def_type( parent_tok ); - if ( which == TokType::Decl_Class ) result = def_class( name, body, parent, access , attributes @@ -5219,6 +5275,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con , mflags ); + interfaces.free(); return result; } @@ -6812,4 +6869,4 @@ void Builder::write() GEN_NS_END -#include "gen.pop_ignores.inline.hpp" +#include "helpers/gen.pop_ignores.inline.hpp" diff --git a/project/gen.hpp b/project/gen.hpp index 4e58c0c..fcfb072 100644 --- a/project/gen.hpp +++ b/project/gen.hpp @@ -12,12 +12,12 @@ #error Gen.hpp : GEN_TIME not defined #endif -#include "gen.push_ignores.inline.hpp" +#include "helpers/gen.push_ignores.inline.hpp" //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl #ifndef GEN_ROLL_OWN_DEPENDENCIES -# include "gen.dep.hpp" +# include "dependencies/gen.dep.hpp" #endif #if defined(GEN_DONT_USE_NAMESPACE) && ! defined(GEN_NS_BEGIN) @@ -778,7 +778,6 @@ struct CodeBody Define_CodeType( Attributes ); Define_CodeType( Comment ); -Define_CodeType( Class ); Define_CodeType( Enum ); Define_CodeType( Exec ); Define_CodeType( Extern ); @@ -789,14 +788,39 @@ Define_CodeType( Module ); Define_CodeType( Namespace ); Define_CodeType( Operator ); Define_CodeType( OpCast ); -Define_CodeType( Struct ); Define_CodeType( Template ); Define_CodeType( Type ); -Define_CodeType(Typedef); +Define_CodeType( Typedef ); Define_CodeType( Union ); Define_CodeType( Using ); Define_CodeType( Var ); +struct CodeClass +{ + Using_Code( CodeClass ); + + void add_interface( CodeType interface ); + + AST* raw() + { + return rcast( AST*, ast ); + } + operator Code() + { + return * rcast( Code*, this ); + } + AST_Class* operator->() + { + if ( ast == nullptr ) + { + log_failure("Attempt to dereference a nullptr"); + return nullptr; + } + return ast; + } + AST_Class* ast; +}; + struct CodeParam { Using_Code( CodeParam ); @@ -904,6 +928,32 @@ struct CodeSpecifiers AST_Specifiers* ast; }; +struct CodeStruct +{ + Using_Code( CodeStruct ); + + void add_interface( CodeType interface ); + + AST* raw() + { + return rcast( AST*, ast ); + } + operator Code() + { + return * rcast( Code*, this ); + } + AST_Struct* operator->() + { + if ( ast == nullptr ) + { + log_failure("Attempt to dereference a nullptr"); + return nullptr; + } + return ast; + } + AST_Struct* ast; +}; + #undef Define_CodeType #undef Using_Code #pragma endregion Code Types @@ -971,8 +1021,8 @@ struct AST_Class CodeBody Body; }; }; - Code Prev; - Code Next; + CodeType Last; + CodeType Next; Code Parent; StringCached Name; CodeT Type; @@ -1223,8 +1273,8 @@ struct AST_Struct CodeBody Body; }; }; - Code Prev; - Code Next; + CodeType Last; + CodeType Next; Code Parent; StringCached Name; CodeT Type; @@ -1407,7 +1457,8 @@ CodeClass def_class( StrC name , Code body = NoCode , CodeType parent = NoCode, AccessSpec access = AccessSpec::Default , CodeAttributes attributes = NoCode - , ModuleFlag mflags = ModuleFlag::None ); + , ModuleFlag mflags = ModuleFlag::None + , CodeType* interfaces = nullptr, s32 num_interfaces = 0 ); CodeEnum def_enum( StrC name , Code body = NoCode, CodeType type = NoCode @@ -1441,7 +1492,8 @@ CodeStruct def_struct( StrC name , Code body = NoCode , CodeType parent = NoCode, AccessSpec access = AccessSpec::Default , CodeAttributes attributes = NoCode - , ModuleFlag mflags = ModuleFlag::None ); + , ModuleFlag mflags = ModuleFlag::None + , CodeType* interfaces = nullptr, s32 num_interfaces = 0 ); CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag::None ); @@ -1737,8 +1789,8 @@ Define_AST_Cast( Namespace ); Define_AST_Cast( Operator ); Define_AST_Cast( OpCast ); Define_AST_Cast( Param ); -Define_AST_Cast( Specifiers ); Define_AST_Cast( Struct ); +Define_AST_Cast( Specifiers ); Define_AST_Cast( Template ); Define_AST_Cast( Type ); Define_AST_Cast( Typedef ); @@ -1779,6 +1831,19 @@ Define_CodeCast( Body); #undef Define_CodeCast #pragma endregion AST & Code Gen Common +void CodeClass::add_interface( CodeType type ) +{ + if ( ! ast->Next ) + { + ast->Next = type; + ast->Last = ast->Next; + return; + } + + ast->Next->Next = type; + ast->Last = ast->Next->Next; +} + void CodeParam::append( CodeParam other ) { AST* self = (AST*) ast; @@ -1828,6 +1893,18 @@ CodeParam& CodeParam::operator ++() return * this; } +void CodeStruct::add_interface( CodeType type ) +{ + if ( ! ast->Next ) + { + ast->Next = type; + ast->Last = ast->Next; + } + + ast->Next->Next = type; + ast->Last = ast->Next->Next; +} + CodeBody def_body( CodeT type ) { switch ( type ) @@ -2030,4 +2107,4 @@ StrC token_fmt_impl( sw num, ... ) GEN_NS_END -#include "gen.pop_ignores.inline.hpp" +#include "helpers/gen.pop_ignores.inline.hpp" diff --git a/project/gen.pop_ignores.inline.hpp b/project/helpers/gen.pop_ignores.inline.hpp similarity index 100% rename from project/gen.pop_ignores.inline.hpp rename to project/helpers/gen.pop_ignores.inline.hpp diff --git a/project/gen.push_ignores.inline.hpp b/project/helpers/gen.push_ignores.inline.hpp similarity index 100% rename from project/gen.push_ignores.inline.hpp rename to project/helpers/gen.push_ignores.inline.hpp diff --git a/project/gen.undef.macros.hpp b/project/helpers/gen.undef.macros.hpp similarity index 100% rename from project/gen.undef.macros.hpp rename to project/helpers/gen.undef.macros.hpp