mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 07:44:45 -08:00
Fixes for typedef serialization of functions..
Also fix for HashTable<>::rehash_fast not having finished implemenation... The typedef fix is a sort of hack (like how parsing the rest of the language feels like tbh...). I might make a def_typedef_fn to make it clearer how to define function typedefs using the upfront interface.
This commit is contained in:
parent
c4d5637a64
commit
ed3246c6b0
@ -722,7 +722,10 @@ String AST::to_string()
|
||||
|
||||
result.append( "typedef ");
|
||||
|
||||
result.append_fmt( "%s %s", UnderlyingType->to_string(), Name );
|
||||
if ( IsFunction )
|
||||
result.append( UnderlyingType->to_string() );
|
||||
else
|
||||
result.append_fmt( "%s %s", UnderlyingType->to_string(), Name );
|
||||
|
||||
if ( UnderlyingType->Type == Typename && UnderlyingType->ArrExpr )
|
||||
{
|
||||
|
@ -256,6 +256,7 @@ struct AST
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
union {
|
||||
b32 IsFunction; // Used by typedef to not serialize the name field.
|
||||
OperatorT Op;
|
||||
AccessSpec ParentAccess;
|
||||
s32 NumEntries;
|
||||
@ -304,6 +305,7 @@ struct AST_POD
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
union {
|
||||
b32 IsFunction; // Used by typedef to not serialize the name field.
|
||||
OperatorT Op;
|
||||
AccessSpec ParentAccess;
|
||||
s32 NumEntries;
|
||||
|
@ -469,7 +469,7 @@ struct AST_Typedef
|
||||
StringCached Name;
|
||||
CodeT Type;
|
||||
ModuleFlag ModuleFlags;
|
||||
char _PAD_UNUSED_[ sizeof(u32) ];
|
||||
b32 IsFunction;
|
||||
};
|
||||
static_assert( sizeof(AST_Typedef) == sizeof(AST), "ERROR: AST_Typedef is not the same size as AST");
|
||||
|
||||
|
@ -1143,7 +1143,7 @@ internal CodeOpCast parse_operator_cast ();
|
||||
internal CodeStruct parse_struct ( bool inplace_def = false );
|
||||
internal CodeVar parse_variable ();
|
||||
internal CodeTemplate parse_template ();
|
||||
internal CodeType parse_type ();
|
||||
internal CodeType parse_type ( bool* is_function = nullptr );
|
||||
internal CodeTypedef parse_typedef ();
|
||||
internal CodeUnion parse_union ( bool inplace_def = false );
|
||||
internal CodeUsing parse_using ();
|
||||
@ -2358,6 +2358,47 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
|
||||
return result;
|
||||
}
|
||||
|
||||
internal inline
|
||||
Code parse_foward_or_definition( Parser::TokType which, bool is_inplace )
|
||||
{
|
||||
using namespace Parser;
|
||||
|
||||
Code result = CodeInvalid;
|
||||
|
||||
switch ( which )
|
||||
{
|
||||
case TokType::Decl_Class:
|
||||
result = parse_class( is_inplace );
|
||||
Context.pop();
|
||||
return result;
|
||||
|
||||
case TokType::Decl_Enum:
|
||||
result = parse_enum( is_inplace );
|
||||
Context.pop();
|
||||
return result;
|
||||
|
||||
case TokType::Decl_Struct:
|
||||
result = parse_struct( is_inplace );
|
||||
Context.pop();
|
||||
return result;
|
||||
|
||||
case TokType::Decl_Union:
|
||||
result = parse_union( is_inplace );
|
||||
Context.pop();
|
||||
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() );
|
||||
|
||||
Context.pop();
|
||||
return CodeInvalid;
|
||||
}
|
||||
|
||||
return CodeInvalid;
|
||||
}
|
||||
|
||||
internal inline
|
||||
Code parse_complicated_definition( Parser::TokType which )
|
||||
{
|
||||
@ -2366,43 +2407,6 @@ Code parse_complicated_definition( Parser::TokType which )
|
||||
|
||||
bool is_inplace = false;
|
||||
|
||||
labeled_scope_start
|
||||
PARSE_FORWARD_OR_DEFINITION:
|
||||
Code result = CodeInvalid;
|
||||
|
||||
// <which> <type_identifier>;
|
||||
switch ( which )
|
||||
{
|
||||
case TokType::Decl_Class:
|
||||
result = parse_class( is_inplace );
|
||||
Context.pop();
|
||||
return result;
|
||||
|
||||
case TokType::Decl_Enum:
|
||||
result = parse_enum( is_inplace );
|
||||
Context.pop();
|
||||
return result;
|
||||
|
||||
case TokType::Decl_Struct:
|
||||
result = parse_struct( is_inplace );
|
||||
Context.pop();
|
||||
return result;
|
||||
|
||||
case TokType::Decl_Union:
|
||||
result = parse_union( is_inplace );
|
||||
Context.pop();
|
||||
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() );
|
||||
|
||||
Context.pop();
|
||||
return CodeInvalid;
|
||||
}
|
||||
labeled_scope_end
|
||||
|
||||
TokArray tokens = Context.Tokens;
|
||||
|
||||
s32 idx = tokens.Idx;
|
||||
@ -2422,7 +2426,7 @@ Code parse_complicated_definition( Parser::TokType which )
|
||||
if ( (idx - 2 ) == tokens.Idx )
|
||||
{
|
||||
// Its a forward declaration only
|
||||
goto PARSE_FORWARD_OR_DEFINITION;
|
||||
return parse_foward_or_definition( which, is_inplace );
|
||||
}
|
||||
|
||||
Token tok = tokens[ idx - 1 ];
|
||||
@ -2451,7 +2455,7 @@ Code parse_complicated_definition( Parser::TokType which )
|
||||
else if ( is_indirection )
|
||||
{
|
||||
// Its a indirection type with type ID using struct namespace.
|
||||
// <which> <type_identifier> <identifier>;
|
||||
// <which> <type_identifier>* <identifier>;
|
||||
ok_to_parse = true;
|
||||
}
|
||||
|
||||
@ -2470,7 +2474,7 @@ Code parse_complicated_definition( Parser::TokType which )
|
||||
{
|
||||
// Its a definition
|
||||
// <which> { ... };
|
||||
goto PARSE_FORWARD_OR_DEFINITION;
|
||||
return parse_foward_or_definition( which, is_inplace );
|
||||
}
|
||||
else if ( tok.Type == TokType::BraceSquare_Close)
|
||||
{
|
||||
@ -4142,7 +4146,7 @@ CodeTemplate parse_template( StrC def )
|
||||
}
|
||||
|
||||
internal
|
||||
CodeType parse_type()
|
||||
CodeType parse_type( bool* is_function )
|
||||
{
|
||||
using namespace Parser;
|
||||
push_scope();
|
||||
@ -4258,13 +4262,24 @@ CodeType parse_type()
|
||||
eat( currtok.Type );
|
||||
}
|
||||
|
||||
BruteforceCaptureAgain:
|
||||
if ( check( TokType::Capture_Start ) && context_tok.Type != TokType::Decl_Operator )
|
||||
bool is_first_capture = true;
|
||||
while ( check( TokType::Capture_Start ) && context_tok.Type != TokType::Decl_Operator )
|
||||
{
|
||||
// Brute force capture the entire thing.
|
||||
// Function typedefs are complicated and there are not worth dealing with for validation at this point...
|
||||
eat( TokType::Capture_Start );
|
||||
|
||||
if ( is_function && is_first_capture )
|
||||
{
|
||||
while ( check( TokType::Star ))
|
||||
{
|
||||
eat( TokType::Star );
|
||||
}
|
||||
|
||||
* is_function = true;
|
||||
eat( TokType::Identifier );
|
||||
}
|
||||
|
||||
s32 level = 0;
|
||||
while ( left && ( currtok.Type != TokType::Capture_End || level > 0 ))
|
||||
{
|
||||
@ -4276,11 +4291,10 @@ BruteforceCaptureAgain:
|
||||
|
||||
eat( currtok.Type );
|
||||
}
|
||||
|
||||
eat( TokType::Capture_End );
|
||||
|
||||
goto BruteforceCaptureAgain;
|
||||
|
||||
brute_sig.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)brute_sig.Text;
|
||||
is_first_capture = false;
|
||||
}
|
||||
|
||||
using namespace ECode;
|
||||
@ -4331,9 +4345,10 @@ CodeTypedef parse_typedef()
|
||||
using namespace Parser;
|
||||
push_scope();
|
||||
|
||||
Token name = { nullptr, 0, TokType::Invalid };
|
||||
Code array_expr = { nullptr };
|
||||
Code type = { nullptr };
|
||||
bool is_function = false;
|
||||
Token name = { nullptr, 0, TokType::Invalid };
|
||||
Code array_expr = { nullptr };
|
||||
Code type = { nullptr };
|
||||
|
||||
ModuleFlag mflags = ModuleFlag::None;
|
||||
|
||||
@ -4356,27 +4371,109 @@ CodeTypedef parse_typedef()
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( check( TokType::Decl_Enum ) )
|
||||
type = parse_enum( from_typedef );
|
||||
bool is_complicated =
|
||||
currtok.Type == TokType::Decl_Enum
|
||||
|| currtok.Type == TokType::Decl_Class
|
||||
|| currtok.Type == TokType::Decl_Struct
|
||||
|| currtok.Type == TokType::Decl_Union;
|
||||
|
||||
else if ( check(TokType::Decl_Class ) )
|
||||
type = parse_class( from_typedef );
|
||||
if ( is_complicated )
|
||||
{
|
||||
TokArray tokens = Context.Tokens;
|
||||
|
||||
else if ( check(TokType::Decl_Struct ) )
|
||||
type = parse_struct( from_typedef );
|
||||
s32 idx = tokens.Idx;
|
||||
s32 level = 0;
|
||||
for ( ; idx < tokens.Arr.num(); idx ++ )
|
||||
{
|
||||
if ( tokens[idx].Type == TokType::BraceCurly_Open )
|
||||
level++;
|
||||
|
||||
else if ( check(TokType::Decl_Union) )
|
||||
type = parse_union( from_typedef );
|
||||
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
|
||||
type = parse_foward_or_definition( currtok.Type, from_typedef );
|
||||
}
|
||||
|
||||
Token tok = tokens[ idx - 1 ];
|
||||
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 )
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
}* Something;
|
||||
|
||||
|
||||
// Its an inplace definition
|
||||
// typdef <which> <type_identifier> { ... } <identifier>;
|
||||
ok_to_parse = true;
|
||||
}
|
||||
else if ( tok.Type == TokType::Identifier && tokens[ idx - 3 ].Type == TokType::Decl_Struct )
|
||||
{
|
||||
// Its a variable with type ID using struct namespace.
|
||||
// <which> <type_identifier> <identifier>;
|
||||
ok_to_parse = true;
|
||||
}
|
||||
else if ( is_indirection )
|
||||
{
|
||||
// Its a indirection type with type ID using struct namespace.
|
||||
// <which> <type_identifier>* <identifier>;
|
||||
ok_to_parse = true;
|
||||
}
|
||||
|
||||
if ( ! ok_to_parse )
|
||||
{
|
||||
log_failure( "Unsupported or bad member definition after struct declaration\n%s", Context.to_string() );
|
||||
Context.pop();
|
||||
return CodeInvalid;
|
||||
}
|
||||
|
||||
type = parse_type();
|
||||
}
|
||||
else if ( tok.Type == TokType::BraceCurly_Close )
|
||||
{
|
||||
// Its a definition
|
||||
// <which> { ... };
|
||||
type = parse_foward_or_definition( currtok.Type, from_typedef );
|
||||
}
|
||||
else if ( tok.Type == TokType::BraceSquare_Close)
|
||||
{
|
||||
// Its an array definition
|
||||
// <which> <type_identifier> <identifier> [ ... ];
|
||||
type = parse_type();
|
||||
}
|
||||
else
|
||||
{
|
||||
log_failure( "Unsupported or bad member definition after struct declaration\n%s", Context.to_string() );
|
||||
Context.pop();
|
||||
return CodeInvalid;
|
||||
}
|
||||
}
|
||||
else
|
||||
type = parse_type();
|
||||
type = parse_type( & is_function );
|
||||
|
||||
if ( check( TokType::Identifier ) )
|
||||
{
|
||||
name = currtok;
|
||||
eat( TokType::Identifier );
|
||||
}
|
||||
else
|
||||
else if ( ! is_function )
|
||||
{
|
||||
log_failure( "Error, expected identifier for typedef\n%s", Context.to_string() );
|
||||
Context.pop();
|
||||
@ -4393,9 +4490,19 @@ CodeTypedef parse_typedef()
|
||||
CodeTypedef
|
||||
result = (CodeTypedef) make_code();
|
||||
result->Type = Typedef;
|
||||
result->Name = get_cached_string( name );
|
||||
result->ModuleFlags = mflags;
|
||||
|
||||
if ( is_function )
|
||||
{
|
||||
result->Name = type->Name;
|
||||
result->IsFunction = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result->Name = get_cached_string( name );
|
||||
result->IsFunction = false;
|
||||
}
|
||||
|
||||
result->UnderlyingType = type;
|
||||
|
||||
if ( type->Type == Typename && array_expr && array_expr->Type != Invalid )
|
||||
|
@ -1221,7 +1221,6 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module
|
||||
{
|
||||
using namespace ECode;
|
||||
|
||||
name_check( def_typedef, name );
|
||||
null_check( def_typedef, type );
|
||||
|
||||
switch ( type->Type )
|
||||
@ -1260,12 +1259,28 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module
|
||||
|
||||
CodeTypedef
|
||||
result = (CodeTypedef) make_code();
|
||||
result->Name = get_cached_string( name );
|
||||
result->Type = ECode::Typedef;
|
||||
result->ModuleFlags = mflags;
|
||||
|
||||
result->UnderlyingType = type;
|
||||
|
||||
if ( name.Len <= 0 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
result->Name = get_cached_string( type->Name );
|
||||
result->IsFunction = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result->Name = get_cached_string( name );
|
||||
result->IsFunction = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -424,9 +424,16 @@ struct HashTable
|
||||
|
||||
for ( idx = 0; idx < Entries.num(); idx++ )
|
||||
{
|
||||
Entry* entry;
|
||||
|
||||
Entry* entry;
|
||||
FindResult find_result;
|
||||
|
||||
entry = & Entries[ idx ];
|
||||
find_result = find( entry->Key );
|
||||
|
||||
if ( find_result.PrevIndex < 0 )
|
||||
Hashes[ find_result.HashIndex ] = idx;
|
||||
else
|
||||
Entries[ find_result.PrevIndex ].Next = idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user