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).
This commit is contained in:
Edward R. Gonzalez 2023-07-24 13:44:19 -04:00
parent d4c2cdf30e
commit 39390535ce
11 changed files with 166 additions and 28 deletions

View File

@ -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++":

View File

@ -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.<hpp/cpp>` )
Dependencies are within `gen.dep.<hpp/cpp>`
## 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.

View File

@ -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

View File

@ -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<CodeType>();
if ( interface )
result.append("\n");
while ( interface )
{
result.append_fmt( ", %s", interface.to_string() );
interface = interface->Next->cast<CodeType>();
}
}
else
{
@ -902,6 +913,17 @@ String AST::to_string()
, ParentType->to_string()
, Body->to_string()
);
CodeType interface = Next->cast<CodeType>();
if ( interface )
result.append("\n");
while ( interface )
{
result.append_fmt( ", public %s", interface.to_string() );
interface = interface->Next->cast<CodeType>();
}
}
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<CodeType> interfaces = Array<CodeType>::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"

View File

@ -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,7 +788,6 @@ Define_CodeType( Module );
Define_CodeType( Namespace );
Define_CodeType( Operator );
Define_CodeType( OpCast );
Define_CodeType( Struct );
Define_CodeType( Template );
Define_CodeType( Type );
Define_CodeType( Typedef );
@ -797,6 +795,32 @@ 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"