Base case for extern link parse working.

This commit is contained in:
Edward R. Gonzalez 2023-07-08 23:29:18 -04:00
parent 41f0e49cb0
commit 472189a322
4 changed files with 645 additions and 171 deletions

View File

@ -27,31 +27,31 @@ namespace gen
} }
#pragma region Constants #pragma region Constants
Code type_ns(auto); Code t_auto;
Code type_ns(void); Code t_void;
Code type_ns(int); Code t_int;
Code type_ns(bool); Code t_bool;
Code type_ns(char); Code t_char;
Code type_ns(wchar_t); Code t_wchar_t;
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
Code type_ns(b32); Code t_b32;
Code type_ns(s8); Code t_s8;
Code type_ns(s16); Code t_s16;
Code type_ns(s32); Code t_s32;
Code type_ns(s64); Code t_s64;
Code type_ns(u8); Code t_u8;
Code type_ns(u16); Code t_u16;
Code type_ns(u32); Code t_u32;
Code type_ns(u64); Code t_u64;
Code type_ns(sw); Code t_sw;
Code type_ns(uw); Code t_uw;
Code type_ns(f32); Code t_f32;
Code type_ns(f64); Code t_f64;
#endif #endif
Code access_public; Code access_public;
@ -68,6 +68,7 @@ namespace gen
Code spec_constexpr; Code spec_constexpr;
Code spec_constinit; Code spec_constinit;
Code spec_extern_linkage; Code spec_extern_linkage;
Code spec_global;
Code spec_inline; Code spec_inline;
Code spec_internal_linkage; Code spec_internal_linkage;
Code spec_local_persist; Code spec_local_persist;
@ -79,10 +80,6 @@ namespace gen
Code spec_static_member; Code spec_static_member;
Code spec_thread_local; Code spec_thread_local;
Code spec_volatile; Code spec_volatile;
Code spec_type_signed;
Code spec_type_unsigned;
Code spec_type_short;
Code spec_type_long;
#pragma endregion Constants #pragma endregion Constants
#pragma region AST Body Case Macros #pragma region AST Body Case Macros
@ -1004,8 +1001,8 @@ namespace gen
Code::Invalid.set_global(); Code::Invalid.set_global();
# define def_constant_code_type( Type_ ) \ # define def_constant_code_type( Type_ ) \
type_ns(Type_) = def_type( name(Type_) ); \ t_##Type_ = def_type( name(Type_) ); \
type_ns(Type_).set_global(); t_##Type_.set_global();
def_constant_code_type( auto ); def_constant_code_type( auto );
def_constant_code_type( void ); def_constant_code_type( void );
@ -1015,7 +1012,7 @@ namespace gen
def_constant_code_type( wchar_t ); def_constant_code_type( wchar_t );
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
type_ns(b32) = def_type( name(b32) ); t_b32 = def_type( name(b32) );
def_constant_code_type( s8 ); def_constant_code_type( s8 );
def_constant_code_type( s16 ); def_constant_code_type( s16 );
@ -1068,17 +1065,26 @@ namespace gen
pragma_once->Content = pragma_once->Name; pragma_once->Content = pragma_once->Name;
pragma_once.set_global(); pragma_once.set_global();
# pragma push_macro( "global" )
# pragma push_macro( "internal" )
# pragma push_macro( "local_persist" )
# define global global
# define internal internal
# define local_persist local_persist
# define def_constant_spec( Type_, ... ) \ # define def_constant_spec( Type_, ... ) \
spec_##Type_ = def_specifiers( macro_num_args(__VA_ARGS__), __VA_ARGS__); \ spec_##Type_ = def_specifiers( macro_num_args(__VA_ARGS__), __VA_ARGS__); \
spec_##Type_.set_global(); spec_##Type_.set_global();
def_constant_spec( const, ESpecifier::Const );
def_constant_spec( consteval, ESpecifier::Consteval ); def_constant_spec( consteval, ESpecifier::Consteval );
def_constant_spec( constexpr, ESpecifier::Constexpr ); def_constant_spec( constexpr, ESpecifier::Constexpr );
def_constant_spec( constinit, ESpecifier::Constinit ); def_constant_spec( constinit, ESpecifier::Constinit );
def_constant_spec( extern_linkage, ESpecifier::External_Linkage ); def_constant_spec( extern_linkage, ESpecifier::External_Linkage );
def_constant_spec( const, ESpecifier::Const ); def_constant_spec( global, ESpecifier::Global );
def_constant_spec( inline, ESpecifier::Inline ); def_constant_spec( inline, ESpecifier::Inline );
def_constant_spec( internal_linkage, ESpecifier::Internal_Linkage ); 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( mutable, ESpecifier::Mutable );
def_constant_spec( ptr, ESpecifier::Ptr ); def_constant_spec( ptr, ESpecifier::Ptr );
def_constant_spec( ref, ESpecifier::Ref ); def_constant_spec( ref, ESpecifier::Ref );
@ -1091,6 +1097,10 @@ namespace gen
spec_local_persist = def_specifiers( 1, ESpecifier::Local_Persist ); spec_local_persist = def_specifiers( 1, ESpecifier::Local_Persist );
spec_local_persist.set_global(); spec_local_persist.set_global();
# pragma pop_macro( "global" )
# pragma pop_macro( "internal" )
# pragma pop_macro( "local_persist" )
# undef def_constant_spec # undef def_constant_spec
} }
@ -1415,7 +1425,7 @@ namespace gen
switch ( params_code->param_count() ) switch ( params_code->param_count() )
{ {
case 1: case 1:
if ( params_code->param_type()->is_equal( type_ns(int) ) ) if ( params_code->param_type()->is_equal( t_int ) )
is_member_symbol = true; is_member_symbol = true;
else else
@ -1425,7 +1435,7 @@ namespace gen
case 2: case 2:
check_param_eq_ret(); check_param_eq_ret();
if ( ! params_code->get_param(1)->is_equal( type_ns(int) ) ) if ( ! params_code->get_param(1)->is_equal( t_int ) )
{ {
log_failure("gen::def_operator: " log_failure("gen::def_operator: "
"operator%s requires second parameter of non-member definition to be int for post-decrement", "operator%s requires second parameter of non-member definition to be int for post-decrement",
@ -1545,7 +1555,7 @@ namespace gen
} }
} }
if ( ! ret_type->is_equal( type_ns(bool) )) if ( ! ret_type->is_equal( t_bool ))
{ {
log_failure("gen::def_operator: operator%s return type must be of type bool - %s" log_failure("gen::def_operator: operator%s return type must be of type bool - %s"
, to_str(op) , to_str(op)
@ -2008,7 +2018,7 @@ namespace gen
} }
else else
{ {
result->add_entry( type_ns(void) ); result->add_entry( t_void );
} }
if ( params ) if ( params )
@ -3031,57 +3041,59 @@ namespace gen
// Any angle brackets found will be considered an operator token. // Any angle brackets found will be considered an operator token.
# define Define_TokType \ # define Define_TokType \
Entry( Access_Private, "private" ) \ Entry( Access_Private, "private" ) \
Entry( Access_Protected, "protected" ) \ Entry( Access_Protected, "protected" ) \
Entry( Access_Public, "public" ) \ Entry( Access_Public, "public" ) \
Entry( Access_MemberSymbol, "." ) \ Entry( Access_MemberSymbol, "." ) \
Entry( Access_StaticSymbol, "::") \ Entry( Access_StaticSymbol, "::") \
Entry( Ampersand, "&" ) \ Entry( Ampersand, "&" ) \
Entry( Ampersand_DBL, "&&" ) \ Entry( Ampersand_DBL, "&&" ) \
Entry( Assign_Classifer, ":" ) \ Entry( Assign_Classifer, ":" ) \
Entry( BraceCurly_Open, "{" ) \ Entry( BraceCurly_Open, "{" ) \
Entry( BraceCurly_Close, "}" ) \ Entry( BraceCurly_Close, "}" ) \
Entry( BraceSquare_Open, "[" ) \ Entry( BraceSquare_Open, "[" ) \
Entry( BraceSquare_Close, "]" ) \ Entry( BraceSquare_Close, "]" ) \
Entry( Capture_Start, "(" ) \ Entry( Capture_Start, "(" ) \
Entry( Capture_End, ")" ) \ Entry( Capture_End, ")" ) \
Entry( Comment, "__comment__" ) \ Entry( Comment, "__comment__" ) \
Entry( Char, "__char__" ) \ Entry( Char, "__char__" ) \
Entry( Comma, "," ) \ Entry( Comma, "," ) \
Entry( Decl_Class, "class" ) \ Entry( Decl_Class, "class" ) \
Entry( Decl_Enum, "enum" ) \ Entry( Decl_Enum, "enum" ) \
Entry( Decl_Extern_Linkage, "extern" ) \ Entry( Decl_Extern_Linkage, "extern" ) \
Entry( Decl_Friend, "friend" ) \ Entry( Decl_Friend, "friend" ) \
Entry( Decl_Module, "module" ) \ Entry( Decl_Module, "module" ) \
Entry( Decl_Namespace, "namespace" ) \ Entry( Decl_Namespace, "namespace" ) \
Entry( Decl_Struct, "struct" ) \ Entry( Decl_Struct, "struct" ) \
Entry( Decl_Typedef, "typedef" ) \ Entry( Decl_Typedef, "typedef" ) \
Entry( Decl_Using, "using" ) \ Entry( Decl_Using, "using" ) \
Entry( Decl_Union, "union" ) \ Entry( Decl_Union, "union" ) \
Entry( Identifier, "__SymID__" ) \ Entry( Identifier, "__SymID__" ) \
Entry( Module_Import, "import" ) \ Entry( Module_Import, "import" ) \
Entry( Module_Export, "export" ) \ Entry( Module_Export, "export" ) \
Entry( Number, "number" ) \ Entry( Number, "number" ) \
Entry( Operator, "operator" ) \ Entry( Operator, "operator" ) \
Entry( Spec_Alignas, "alignas" ) \ Entry( Spec_Alignas, "alignas" ) \
Entry( Spec_Const, "const" ) \ Entry( Spec_Const, "const" ) \
Entry( Spec_Consteval, "consteval" ) \ Entry( Spec_Consteval, "consteval" ) \
Entry( Spec_Constexpr, "constexpr" ) \ Entry( Spec_Constexpr, "constexpr" ) \
Entry( Spec_Constinit, "constinit" ) \ Entry( Spec_Constinit, "constinit" ) \
Entry( Spec_Extern, "extern" ) \ Entry( Spec_Extern, "extern" ) \
Entry( Spec_Inline, "inline" ) \ Entry( Spec_Global, "global" ) \
Entry( Spec_LocalPersist, "local_persist" ) \ Entry( Spec_Inline, "inline" ) \
Entry( Spec_Mutable, "mutable" ) \ Entry( Spec_Internal_Linkage, "internal" ) \
Entry( Spec_Static, "static" ) \ Entry( Spec_LocalPersist, "local_persist" ) \
Entry( Spec_ThreadLocal, "thread_local" ) \ Entry( Spec_Mutable, "mutable" ) \
Entry( Spec_Volatile, "volatile") \ Entry( Spec_Static, "static" ) \
Entry( Star, "*" ) \ Entry( Spec_ThreadLocal, "thread_local" ) \
Entry( Statement_End, ";" ) \ Entry( Spec_Volatile, "volatile") \
Entry( String, "__String__" ) \ Entry( Star, "*" ) \
Entry( Type_Unsigned, "unsigned" ) \ Entry( Statement_End, ";" ) \
Entry( Type_Signed, "signed" ) \ Entry( String, "__String__" ) \
Entry( Type_Short, "short" ) \ Entry( Type_Unsigned, "unsigned" ) \
Entry( Type_Long, "long" ) Entry( Type_Signed, "signed" ) \
Entry( Type_Short, "short" ) \
Entry( Type_Long, "long" )
enum class TokType : u32 enum class TokType : u32
{ {
@ -3674,6 +3686,7 @@ namespace gen
Code parse_exten_link ( Parser::TokArray& toks, char const* context ); Code parse_exten_link ( Parser::TokArray& toks, char const* context );
Code parse_friend ( Parser::TokArray& toks, char const* context ); Code parse_friend ( Parser::TokArray& toks, char const* context );
Code parse_function ( Parser::TokArray& toks, char const* context ); Code parse_function ( Parser::TokArray& toks, char const* context );
Code parse_namespace ( Parser::TokArray& toks, char const* context );
Code parse_struct ( Parser::TokArray& toks, char const* context ); Code parse_struct ( Parser::TokArray& toks, char const* context );
Code parse_variable ( Parser::TokArray& toks, char const* context ); Code parse_variable ( Parser::TokArray& toks, char const* context );
Code parse_type ( Parser::TokArray& toks, char const* context ); Code parse_type ( Parser::TokArray& toks, char const* context );
@ -3942,7 +3955,8 @@ namespace gen
while ( left && currtok.Type != TokType::BraceCurly_Close ) while ( left && currtok.Type != TokType::BraceCurly_Close )
{ {
Code member = Code::Invalid; Code member = Code::Invalid;
Code specifiers = Code::Invalid;
switch ( currtok.Type ) switch ( currtok.Type )
{ {
@ -4002,8 +4016,6 @@ namespace gen
case TokType::Spec_ThreadLocal: case TokType::Spec_ThreadLocal:
case TokType::Spec_Volatile: case TokType::Spec_Volatile:
{ {
Code specifiers = Code::Invalid;
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
s32 num_specifiers = 0; s32 num_specifiers = 0;
@ -4045,33 +4057,35 @@ namespace gen
case TokType::Type_Short: case TokType::Type_Short:
case TokType::Type_Long: case TokType::Type_Long:
{ {
Code specifiers = Code::Invalid;
Code type = parse_type( toks, context ); Code type = parse_type( toks, context );
if ( type == Code::Invalid ) if ( type == Code::Invalid )
{
log_failure( "gen::parse_variable: failed to parse type" );
return Code::Invalid; return Code::Invalid;
}
Token name = currtok; Token name = currtok;
eat( TokType::Identifier );
if ( check( TokType::Identifier ) )
{
name = currtok;
}
// Parsing a member function // Parsing a member function
if ( check( TokType::Capture_Start )) if ( check( TokType::Capture_Start ))
{ {
Code params = parse_params( toks, context ); Code params = parse_params( toks, context );
if ( params == Code::Invalid ) if ( params == Code::Invalid )
{
log_failure( "gen::parse_variable: failed to parse function parameters" );
return Code::Invalid; return Code::Invalid;
}
if ( check( TokType::BraceCurly_Open ) ) if ( check( TokType::BraceCurly_Open ) )
{ {
Code body = parse_function_body( toks, context); Code body = parse_function_body( toks, context);
if ( body == Code::Invalid ) if ( body == Code::Invalid )
{
log_failure( "gen::parse_variable: failed to parse function body" );
return Code::Invalid; return Code::Invalid;
}
Code
member = make_code(); member = make_code();
member->Name = get_cached_string( name ); member->Name = get_cached_string( name );
@ -4128,7 +4142,10 @@ namespace gen
} }
if ( member == Code::Invalid ) if ( member == Code::Invalid )
{
log_failure( "gen::parse_variable: failed to parse member" );
return Code::Invalid; return Code::Invalid;
}
result->add_entry( member ); result->add_entry( member );
} }
@ -4176,7 +4193,6 @@ namespace gen
case TokType::Decl_Typedef: case TokType::Decl_Typedef:
member = parse_typedef( toks, context ); member = parse_typedef( toks, context );
break; break;
case TokType::Decl_Union: case TokType::Decl_Union:
@ -4375,22 +4391,248 @@ namespace gen
return Code::Invalid; return Code::Invalid;
} }
Code parse_export_body( StrC def ) Code parse_extern_link_body( Parser::TokArray& toks, char const* context )
{ {
not_implemented(); using namespace Parser;
return Code::Invalid; using namespace ECode;
eat( TokType::BraceCurly_Open );
Code
result = make_code();
result->Type = Extern_Linkage_Body;
while ( left && currtok.Type != TokType::BraceCurly_Close )
{
Code member = Code::Invalid;
Code specifiers = Code::Invalid;
switch ( currtok.Type )
{
case TokType::Comment:
def_comment( currtok );
eat( TokType::Comment );
break;
case TokType::Decl_Enum:
member = parse_enum( toks, context);
break;
case TokType::Decl_Class:
member = parse_class( toks, context );
break;
case TokType::Decl_Extern_Linkage:
log_failure( "gen::parse_extern_link_body: nested extern linkage" );
return Code::Invalid;
case TokType::Decl_Namespace:
member = parse_namespace( toks, context );
break;
case TokType::Decl_Struct:
member = parse_struct( toks, context );
break;
case TokType::Decl_Typedef:
member = parse_typedef( toks, context );
break;
case TokType::Decl_Union:
member = parse_union( toks, context );
break;
case TokType::Decl_Using:
member = parse_using( toks, context );
break;
// TODO: Module support.
// case TokType::Module_Export:
// case TokType::Module_Import:
case TokType::Spec_Extern:
case TokType::Spec_Global:
case TokType::Spec_Inline:
case TokType::Spec_Internal_Linkage:
case TokType::Spec_Static:
{
SpecifierT specs_found[16] { ESpecifier::Invalid };
s32 num_specs = 0;
while ( left && tok_is_specifier( currtok ) )
{
SpecifierT spec = ESpecifier::to_type( currtok );
switch ( spec )
{
case ESpecifier::Const:
case ESpecifier::External_Linkage:
case ESpecifier::Global:
case ESpecifier::Inline:
case ESpecifier::Internal_Linkage:
break;
default:
log_failure( "gen::parse_variable: invalid specifier " txt(spec) " for extern linkage scope" );
return Code::Invalid;
}
specs_found[num_specs] = spec;
num_specs++;
eat( currtok.Type );
}
if ( num_specs )
{
specifiers = def_specifiers( num_specs, specs_found );
}
}
case TokType::Identifier:
case TokType::Spec_Const:
case TokType::Type_Long:
case TokType::Type_Short:
case TokType::Type_Signed:
case TokType::Type_Unsigned:
{
Code type = parse_type( toks, context );
if ( type == Code::Invalid )
{
log_failure( "gen::parse_extern_link_body: failed to parse type" );
return Code::Invalid;
}
Token name = currtok;
eat( TokType::Identifier );
// Parsing a function
if ( check( TokType::Capture_Start ))
{
Code params = parse_params( toks, context );
if ( params == Code::Invalid )
{
log_failure( "gen::parse_extern_link_body: failed to parse function params" );
return Code::Invalid;
}
if ( check( TokType::BraceCurly_Open ))
{
Code body = parse_function_body( toks, context );
if ( body == Code::Invalid )
{
log_failure( "gen::parse_extern_link_body: failed to parse function body" );
return Code::Invalid;
}
member = make_code();
member->Name = get_cached_string( name );
if ( body )
{
switch ( body->Type )
{
case Function_Body:
case Untyped:
break;
default:
{
log_failure( "gen::parse_extern_link_body: invalid function body" );
return Code::Invalid;
}
}
member->Type = Function;
member->add_entry( body );
}
else
{
member->Type = Function_Fwd;
}
member->add_entry( type );
if ( params )
member->add_entry( params );
break;
}
}
// Parsing a variable
Code array_expr = parse_array_decl( toks, context );
Code expr = parse_variable_assignment( toks, context );
member = make_code();
member->Type = Variable;
member->Name = get_cached_string( name );
member->add_entry( type );
if ( array_expr )
type->add_entry( array_expr );
if ( specifiers )
member->add_entry( specifiers );
if ( expr )
member->add_entry( expr );
}
if ( member == Code::Invalid )
{
log_failure( "gen::parse_extern_link_body: failed to parse extern linkage member" );
return Code::Invalid;
}
result->add_entry( member );
}
eat( currtok.Type );
}
eat( TokType::BraceCurly_Close );
return result;
} }
Code parse_extern_link( Parser::TokArray& toks, char const* context ) Code parse_extern_link( Parser::TokArray& toks, char const* context )
{ {
not_implemented(); using namespace Parser;
return Code::Invalid;
eat( TokType::Decl_Extern_Linkage );
Token name = currtok;
eat( TokType::String );
name.Text += 1;
name.Length -= 1;
Code
result = make_code();
result->Type = ECode::Extern_Linkage;
result->Name = get_cached_string( name );
Code entry = parse_extern_link_body( toks, context );
if ( entry == Code::Invalid )
{
log_failure( "gen::parse_extern_link: failed to parse body" );
return result;
}
result->add_entry( entry );
return result;
} }
Code parse_extern_link( StrC def ) Code parse_extern_link( StrC def )
{ {
not_implemented(); check_parse_args( parse_extern_link, def );
return Code::Invalid; using namespace Parser;
TokArray toks = lex( def );
if ( toks.Arr == nullptr )
return Code::Invalid;
return parse_extern_link( toks, txt(parse_extern_link) );
} }
Code parse_friend( Parser::TokArray& toks, char const* context ) Code parse_friend( Parser::TokArray& toks, char const* context )
@ -5056,7 +5298,7 @@ namespace gen
# undef eat # undef eat
# undef left # undef left
// End GEN_FEATURE_PARSING // End GEN_FEATURE_PARSING
# endif #endif
#pragma endregion Parsing Constructors #pragma endregion Parsing Constructors
#pragma region Untyped Constructors #pragma region Untyped Constructors

View File

@ -207,16 +207,17 @@ namespace gen
alignas alignas
*/ */
#define Define_Specifiers \ # define Define_Specifiers \
Entry( Invalid, INVALID ) \ Entry( Invalid, INVALID ) \
Entry( Const, const ) \ Entry( Const, const ) \
Entry( Consteval, consteval ) \ Entry( Consteval, consteval ) \
Entry( Constexpr, constexpr ) \ Entry( Constexpr, constexpr ) \
Entry( Constinit, constinit ) \ Entry( Constinit, constinit ) \
Entry( External_Linkage, extern ) \ Entry( External_Linkage, extern ) \
Entry( Global, global ) \
Entry( Inline, inline ) \ Entry( Inline, inline ) \
Entry( Internal_Linkage, static ) \ Entry( Internal_Linkage, internal ) \
Entry( Local_Persist, static ) \ Entry( Local_Persist, local_persist ) \
Entry( Mutable, mutable ) \ Entry( Mutable, mutable ) \
Entry( Ptr, * ) \ Entry( Ptr, * ) \
Entry( Ref, & ) \ Entry( Ref, & ) \
@ -241,9 +242,20 @@ namespace gen
{ {
local_persist local_persist
StrC lookup[ Num_Specifiers ] = { StrC lookup[ Num_Specifiers ] = {
# pragma push_macro( "global" )
# pragma push_macro( "internal" )
# pragma push_macro( "local_persist" )
# define global global
# define internal internal
# define local_persist local_persist
# define Entry( Spec_, Code_ ) { txt_n_len(Code_) }, # define Entry( Spec_, Code_ ) { txt_n_len(Code_) },
Define_Specifiers Define_Specifiers
# undef Entry # undef Entry
# pragma pop_macro( "global" )
# pragma pop_macro( "internal" )
# pragma pop_macro( "local_persist" )
}; };
return lookup[ specifier ]; return lookup[ specifier ];
@ -274,7 +286,7 @@ namespace gen
return Invalid; return Invalid;
} }
#undef Define_Specifiers # undef Define_Specifiers
} }
using SpecifierT = ESpecifier::Type; using SpecifierT = ESpecifier::Type;
@ -382,7 +394,7 @@ namespace gen
*/ */
struct AST struct AST
{ {
#pragma region Member Functions # pragma region Member Functions
void add_entry( AST* other ); void add_entry( AST* other );
inline inline
@ -524,7 +536,7 @@ namespace gen
} }
String to_string(); String to_string();
#pragma endregion Member Functions # pragma endregion Member Functions
constexpr static constexpr static
uw ArrS_Cap = uw ArrS_Cap =
@ -582,15 +594,15 @@ namespace gen
*/ */
struct Code struct Code
{ {
#pragma region Statics # pragma region Statics
// Used to identify ASTs that should always be duplicated. (Global constant ASTs) // Used to identify ASTs that should always be duplicated. (Global constant ASTs)
static Code Global; static Code Global;
// Used to identify invalid generated code. // Used to identify invalid generated code.
static Code Invalid; static Code Invalid;
#pragma endregion Statics # pragma endregion Statics
#pragma region Member Functions # pragma region Member Functions
inline inline
Code body() Code body()
{ {
@ -676,7 +688,7 @@ namespace gen
return ast; return ast;
} }
#pragma endregion Member Functions # pragma endregion Member Functions
AST* ast; AST* ast;
}; };
@ -814,27 +826,26 @@ namespace gen
Code def_union_body ( s32 num, Code* codes ); Code def_union_body ( s32 num, Code* codes );
# pragma endregion Upfront # pragma endregion Upfront
#pragma region Parsing # pragma region Parsing
#ifdef GEN_FEATURE_PARSING # ifdef GEN_FEATURE_PARSING
Code parse_class ( StrC class_def ); Code parse_class ( StrC class_def );
Code parse_enum ( StrC enum_def ); Code parse_enum ( StrC enum_def );
Code parse_export_body( StrC export_def ); Code parse_extern_link ( StrC exten_link_def);
Code parse_exten_link ( StrC exten_link_def); Code parse_friend ( StrC friend_def );
Code parse_friend ( StrC friend_def ); Code parse_function ( StrC fn_def );
Code parse_function ( StrC fn_def ); Code parse_global_body ( StrC body_def );
Code parse_global_body( StrC body_def ); Code parse_namespace ( StrC namespace_def );
Code parse_namespace ( StrC namespace_def ); Code parse_operator ( StrC operator_def );
Code parse_operator ( StrC operator_def ); Code parse_struct ( StrC struct_def );
Code parse_struct ( StrC struct_def ); Code parse_type ( StrC type_def );
Code parse_type ( StrC type_def ); Code parse_typedef ( StrC typedef_def );
Code parse_typedef ( StrC typedef_def ); Code parse_union ( StrC union_def );
Code parse_union ( StrC union_def ); Code parse_using ( StrC using_def );
Code parse_using ( StrC using_def ); Code parse_variable ( StrC var_def );
Code parse_variable ( StrC var_def ); # endif
#endif # pragma endregion Parsing
#pragma endregion Parsing
#pragma region Untyped text # pragma region Untyped text
sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_list va ); sw token_fmt_va( char* buf, uw buf_size, char const* fmt, s32 num_tokens, va_list va );
inline inline
@ -855,7 +866,7 @@ namespace gen
Code untyped_str ( StrC content); Code untyped_str ( StrC content);
Code untyped_fmt ( char const* fmt, ... ); Code untyped_fmt ( char const* fmt, ... );
Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... ); Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... );
#pragma endregion Untyped text # pragma endregion Untyped text
struct Builder struct Builder
{ {
@ -945,7 +956,7 @@ namespace gen
}; };
#endif #endif
# ifdef GEN_FEATURE_SCANNER #ifdef GEN_FEATURE_SCANNER
struct Scanner struct Scanner
{ {
struct RequestEntry struct RequestEntry
@ -974,7 +985,7 @@ namespace gen
bool process_requests( Array(Receipt) out_receipts ); bool process_requests( Array(Receipt) out_receipts );
}; };
# endif #endif
#pragma endregion Gen Interface #pragma endregion Gen Interface
} }
@ -983,9 +994,6 @@ namespace gen
# define __ NoCode # define __ NoCode
// This represents the naming convention for all typename Codes generated.
# define type_ns( Name_ ) t_##Name_
// Convienence for defining any name used with the gen api. // Convienence for defining any name used with the gen api.
// Lets you provide the length and string literal to the functions without the need for the DSL. // Lets you provide the length and string literal to the functions without the need for the DSL.
# define name( Id_ ) { txt_n_len( Id_ ) } # define name( Id_ ) { txt_n_len( Id_ ) }
@ -1000,23 +1008,23 @@ namespace gen
{ {
// Predefined typename codes. Are set to readonly and are setup during gen::init() // Predefined typename codes. Are set to readonly and are setup during gen::init()
extern Code type_ns( b32 ); extern Code t_b32;
extern Code type_ns( s8 ); extern Code t_s8;
extern Code type_ns( s16 ); extern Code t_s16;
extern Code type_ns( s32 ); extern Code t_s32;
extern Code type_ns( s64 ); extern Code t_s64;
extern Code type_ns( u8 ); extern Code t_u8;
extern Code type_ns( u16 ); extern Code t_u16;
extern Code type_ns( u32 ); extern Code t_u32;
extern Code type_ns( u64 ); extern Code t_u64;
extern Code type_ns( sw ); extern Code t_sw;
extern Code type_ns( uw ); extern Code t_uw;
extern Code type_ns( f32 ); extern Code t_f32;
extern Code type_ns( f64 ); extern Code t_f64;
} }
#endif #endif
@ -1042,12 +1050,12 @@ namespace gen
// Predefined Codes. Are set to readonly and are setup during gen::init() // Predefined Codes. Are set to readonly and are setup during gen::init()
extern Code type_ns( auto ); extern Code t_auto;
extern Code type_ns( void ); extern Code t_void;
extern Code type_ns( int ); extern Code t_int;
extern Code type_ns( bool ); extern Code t_bool;
extern Code type_ns( char ); extern Code t_char;
extern Code type_ns( wchar_t ); extern Code t_wchar_t;
extern Code access_public; extern Code access_public;
extern Code access_protected; extern Code access_protected;
@ -1063,6 +1071,7 @@ namespace gen
extern Code spec_constexpr; extern Code spec_constexpr;
extern Code spec_constinit; extern Code spec_constinit;
extern Code spec_extern_linkage; extern Code spec_extern_linkage;
extern Code spec_global;
extern Code spec_inline; extern Code spec_inline;
extern Code spec_internal_linkage; extern Code spec_internal_linkage;
extern Code spec_local_persist; extern Code spec_local_persist;
@ -1074,10 +1083,6 @@ namespace gen
extern Code spec_static_member; extern Code spec_static_member;
extern Code spec_thread_local; extern Code spec_thread_local;
extern Code spec_volatile; extern Code spec_volatile;
extern Code spec_type_signed;
extern Code spec_type_unsigned;
extern Code spec_type_short;
extern Code spec_type_long;
} }
#pragma endregion Constants #pragma endregion Constants

View File

@ -7,7 +7,7 @@ u32 gen_sanity()
{ {
Builder Builder
gen_sanity_file; gen_sanity_file;
gen_sanity_file.open("./sanity.gen.hpp"); gen_sanity_file.open("./sanity.NonParsed.gen.hpp");
// Comment // Comment
{ {
@ -159,7 +159,6 @@ u32 gen_sanity()
{ {
// Going to make a bit flag set of overloads for this. // Going to make a bit flag set of overloads for this.
Code bitflagtest; Code bitflagtest;
{ {
Code body = def_enum_body( 1, untyped_str( code( Code body = def_enum_body( 1, untyped_str( code(
@ -185,7 +184,6 @@ u32 gen_sanity()
} }
gen_sanity_file.print(bitflagtest); gen_sanity_file.print(bitflagtest);
gen_sanity_file.print_fmt("\n");
gen_sanity_file.print(op_fwd); gen_sanity_file.print(op_fwd);
gen_sanity_file.print(op_or); gen_sanity_file.print(op_or);
} }
@ -207,7 +205,10 @@ u32 gen_sanity()
, def_comment( StrC::from("Empty function body") ) , def_comment( StrC::from("Empty function body") )
); );
Code params = def_params( 2 * 3, t_u8, 1, "a", t_u8, 1, "b" ); Code params = def_params( 2
, def_param( t_u8, name(a) )
, def_param( t_u8, name(b) )
);
def = def_function( name(test_function_wparams), params, __, body ); def = def_function( name(test_function_wparams), params, __, body );
@ -231,10 +232,13 @@ u32 gen_sanity()
{ {
Code fwd_fn = def_function( name(test_function_specifiers), __, __, __, spec_inline ); Code fwd_fn = def_function( name(test_function_specifiers), __, __, __, spec_inline );
// Need an op overload here // TODO: Need an op overload here
Code t_ct_u8 = def_type( name(u8), __, spec_constexpr ); Code u8_ptr = def_type( name(u8), __, spec_ptr );
Code typedef_ConstExprTest = def_typedef( name(ConstExprTest), t_ct_u8 ); Code typedef_u8_ptr = def_typedef( name(ConstExprTest), u8_ptr );
gen_sanity_file.print(fwd_fn);
gen_sanity_file.print(typedef_u8_ptr);
} }
gen_sanity_file.print_fmt("\n"); gen_sanity_file.print_fmt("\n");
@ -244,7 +248,7 @@ u32 gen_sanity()
Code fwd = def_class( name(TestEmptyStruct) ); Code fwd = def_class( name(TestEmptyStruct) );
Code empty_body; Code empty_body;
{ {
Code cmt = def_comment( StrC::from("Empty class body") ); Code cmt = def_comment( StrC::from("Empty struct body") );
Code body = def_class_body( 1, cmt ); Code body = def_class_body( 1, cmt );
empty_body = def_class( name(TestEmptyStruct), body ); empty_body = def_class( name(TestEmptyStruct), body );

View File

@ -4,11 +4,11 @@
using namespace gen; using namespace gen;
void gen_sanity() u32 gen_sanity()
{ {
Builder Builder
gen_sanity_file; gen_sanity_file;
gen_sanity_file.open("./sanity.gen.hpp"); gen_sanity_file.open("./sanity.Parsed.gen.hpp");
gen_sanity_file.print( def_comment( StrC::from( gen_sanity_file.print( def_comment( StrC::from(
"The following will show a series of base cases for the gen parsed api.\n" "The following will show a series of base cases for the gen parsed api.\n"
@ -72,11 +72,234 @@ void gen_sanity()
// External Linkage // External Linkage
{ {
Code empty_comment = def_comment( StrC::from("Empty external linkage") );
Code c_extern = parse_extern_link( code(
extern "C"
{
};
));
c_extern.body()->add_entry( empty_comment );
gen_sanity_file.print(c_extern);
} }
gen_sanity_file.print_fmt("\n"); gen_sanity_file.print_fmt("\n");
// Friend
if (0)
{
Code fwd = parse_class( code(
class TestFriendClass;
));
Code def = parse_class( code(
class TestFriend
{
friend class TestFriendClass;
};
));
gen_sanity_file.print(fwd);
gen_sanity_file.print(def);
}
gen_sanity_file.print_fmt("\n");
// Function
if (0)
{
Code fwd = parse_function( code(
void test_function();
));
Code def = parse_function( code(
void test_function()
{
}
));
def.body()->add_entry( def_comment( StrC::from("Empty function body") ) );
gen_sanity_file.print(fwd);
gen_sanity_file.print(def);
}
gen_sanity_file.print_fmt("\n");
// Namespace
if (0)
{
Code def = parse_namespace( code(
namespace TestNamespace
{
}
));
def.body()->add_entry( def_comment( StrC::from("Empty namespace body") ) );
gen_sanity_file.print(def);
}
gen_sanity_file.print_fmt("\n");
// Operator
if (0)
{
Code bitflagtest = parse_class( code(
enum class EBitFlagTest : u8
{
A = 1 << 0,
B = 1 << 1,
C = 1 << 2
};
));
Code op_fwd = parse_operator( code(
EBitFlagTest operator | ( EBitFlagTest a, EBitFlagTest b );
));
Code op_or = parse_operator( code(
EBitFlagTest operator | ( EBitFlagTest a, EBitFlagTest b )
{
return EBitFlagTest( (u8)a | (u8)b );
}
));
gen_sanity_file.print(bitflagtest);
gen_sanity_file.print(op_fwd);
gen_sanity_file.print(op_or);
}
gen_sanity_file.print_fmt("\n");
// Parameters
if (0)
{
Code fwd = parse_function( code(
void test_function( int a );
));
Code def = parse_function( code(
void test_function( int a, int b )
{
}
));
def.body()->add_entry( def_comment( StrC::from("Empty function body") ) );
gen_sanity_file.print(fwd);
gen_sanity_file.print(def);
}
gen_sanity_file.print_fmt("\n");
// Specifiers
if (0)
{
Code fwd_fn = parse_function( code(
inline
void test_function_specifiers();
));
Code typedef_u8_ptr = parse_typedef( code(
typedef u8* u8_ptr;
));
gen_sanity_file.print(fwd_fn);
gen_sanity_file.print(typedef_u8_ptr);
}
gen_sanity_file.print_fmt("\n");
// Struct
if (0)
{
Code fwd = parse_struct( code(
struct TestEmptyStruct;
));
Code empty_body = parse_struct( code(
struct TestEmptyStruct
{};
));
empty_body.body()->add_entry( def_comment( StrC::from("Empty struct body") ) );
gen_sanity_file.print(fwd);
gen_sanity_file.print(empty_body);
}
gen_sanity_file.print_fmt("\n");
// Union
if (0)
{
Code empty = parse_union( code(
union TestEmptyUnion
{
};
));
empty.body()->add_entry( def_comment( StrC::from("Empty union body") ) );
Code def = parse_union( code(
union TestUnion
{
u8 a;
u16 b;
u32 c;
};
));
gen_sanity_file.print(empty);
gen_sanity_file.print(def);
}
gen_sanity_file.print_fmt("\n");
// Using
if (0)
{
Code reg = parse_using( code(
using TestUsing = u8;
));
Code nspace = parse_using( code(
namespace TestNamespace
{
};
using namespace TestUsing;
));
gen_sanity_file.print(reg);
gen_sanity_file.print(nspace);
}
gen_sanity_file.print_fmt("\n");
// Variable
if (0)
{
Code bss = parse_variable( code(
u8 test_variable;
));
Code data = parse_variable( code(
u8 test_variable = 0x12;
));
}
gen_sanity_file.print_fmt("\n");
gen_sanity_file.print( def_comment( StrC::from(
"End of base case tests\n"
)));
gen_sanity_file.write(); gen_sanity_file.write();
return 0;
} }
#endif #endif