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:
Edward R. Gonzalez 2023-08-07 20:16:04 -04:00
parent c4d5637a64
commit ed3246c6b0
6 changed files with 201 additions and 67 deletions

View File

@ -722,7 +722,10 @@ String AST::to_string()
result.append( "typedef "); 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 ) if ( UnderlyingType->Type == Typename && UnderlyingType->ArrExpr )
{ {

View File

@ -256,6 +256,7 @@ struct AST
CodeT Type; CodeT Type;
ModuleFlag ModuleFlags; ModuleFlag ModuleFlags;
union { union {
b32 IsFunction; // Used by typedef to not serialize the name field.
OperatorT Op; OperatorT Op;
AccessSpec ParentAccess; AccessSpec ParentAccess;
s32 NumEntries; s32 NumEntries;
@ -304,6 +305,7 @@ struct AST_POD
CodeT Type; CodeT Type;
ModuleFlag ModuleFlags; ModuleFlag ModuleFlags;
union { union {
b32 IsFunction; // Used by typedef to not serialize the name field.
OperatorT Op; OperatorT Op;
AccessSpec ParentAccess; AccessSpec ParentAccess;
s32 NumEntries; s32 NumEntries;

View File

@ -469,7 +469,7 @@ struct AST_Typedef
StringCached Name; StringCached Name;
CodeT Type; CodeT Type;
ModuleFlag ModuleFlags; 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"); static_assert( sizeof(AST_Typedef) == sizeof(AST), "ERROR: AST_Typedef is not the same size as AST");

View File

@ -1143,7 +1143,7 @@ internal CodeOpCast parse_operator_cast ();
internal CodeStruct parse_struct ( bool inplace_def = false ); internal CodeStruct parse_struct ( bool inplace_def = false );
internal CodeVar parse_variable (); internal CodeVar parse_variable ();
internal CodeTemplate parse_template (); internal CodeTemplate parse_template ();
internal CodeType parse_type (); internal CodeType parse_type ( bool* is_function = nullptr );
internal CodeTypedef parse_typedef (); internal CodeTypedef parse_typedef ();
internal CodeUnion parse_union ( bool inplace_def = false ); internal CodeUnion parse_union ( bool inplace_def = false );
internal CodeUsing parse_using (); internal CodeUsing parse_using ();
@ -2358,6 +2358,47 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
return result; 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 internal inline
Code parse_complicated_definition( Parser::TokType which ) Code parse_complicated_definition( Parser::TokType which )
{ {
@ -2366,43 +2407,6 @@ Code parse_complicated_definition( Parser::TokType which )
bool is_inplace = false; 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; TokArray tokens = Context.Tokens;
s32 idx = tokens.Idx; s32 idx = tokens.Idx;
@ -2422,7 +2426,7 @@ Code parse_complicated_definition( Parser::TokType which )
if ( (idx - 2 ) == tokens.Idx ) if ( (idx - 2 ) == tokens.Idx )
{ {
// Its a forward declaration only // Its a forward declaration only
goto PARSE_FORWARD_OR_DEFINITION; return parse_foward_or_definition( which, is_inplace );
} }
Token tok = tokens[ idx - 1 ]; Token tok = tokens[ idx - 1 ];
@ -2451,7 +2455,7 @@ Code parse_complicated_definition( Parser::TokType which )
else if ( is_indirection ) else if ( is_indirection )
{ {
// Its a indirection type with type ID using struct namespace. // Its a indirection type with type ID using struct namespace.
// <which> <type_identifier> <identifier>; // <which> <type_identifier>* <identifier>;
ok_to_parse = true; ok_to_parse = true;
} }
@ -2470,7 +2474,7 @@ Code parse_complicated_definition( Parser::TokType which )
{ {
// Its a definition // Its a definition
// <which> { ... }; // <which> { ... };
goto PARSE_FORWARD_OR_DEFINITION; return parse_foward_or_definition( which, is_inplace );
} }
else if ( tok.Type == TokType::BraceSquare_Close) else if ( tok.Type == TokType::BraceSquare_Close)
{ {
@ -4142,7 +4146,7 @@ CodeTemplate parse_template( StrC def )
} }
internal internal
CodeType parse_type() CodeType parse_type( bool* is_function )
{ {
using namespace Parser; using namespace Parser;
push_scope(); push_scope();
@ -4258,13 +4262,24 @@ CodeType parse_type()
eat( currtok.Type ); eat( currtok.Type );
} }
BruteforceCaptureAgain: bool is_first_capture = true;
if ( check( TokType::Capture_Start ) && context_tok.Type != TokType::Decl_Operator ) while ( check( TokType::Capture_Start ) && context_tok.Type != TokType::Decl_Operator )
{ {
// Brute force capture the entire thing. // Brute force capture the entire thing.
// Function typedefs are complicated and there are not worth dealing with for validation at this point... // Function typedefs are complicated and there are not worth dealing with for validation at this point...
eat( TokType::Capture_Start ); 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; s32 level = 0;
while ( left && ( currtok.Type != TokType::Capture_End || level > 0 )) while ( left && ( currtok.Type != TokType::Capture_End || level > 0 ))
{ {
@ -4276,11 +4291,10 @@ BruteforceCaptureAgain:
eat( currtok.Type ); eat( currtok.Type );
} }
eat( TokType::Capture_End ); eat( TokType::Capture_End );
goto BruteforceCaptureAgain;
brute_sig.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)brute_sig.Text; brute_sig.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)brute_sig.Text;
is_first_capture = false;
} }
using namespace ECode; using namespace ECode;
@ -4331,9 +4345,10 @@ CodeTypedef parse_typedef()
using namespace Parser; using namespace Parser;
push_scope(); push_scope();
Token name = { nullptr, 0, TokType::Invalid }; bool is_function = false;
Code array_expr = { nullptr }; Token name = { nullptr, 0, TokType::Invalid };
Code type = { nullptr }; Code array_expr = { nullptr };
Code type = { nullptr };
ModuleFlag mflags = ModuleFlag::None; ModuleFlag mflags = ModuleFlag::None;
@ -4356,27 +4371,109 @@ CodeTypedef parse_typedef()
} }
else else
{ {
if ( check( TokType::Decl_Enum ) ) bool is_complicated =
type = parse_enum( from_typedef ); 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 ) ) if ( is_complicated )
type = parse_class( from_typedef ); {
TokArray tokens = Context.Tokens;
else if ( check(TokType::Decl_Struct ) ) s32 idx = tokens.Idx;
type = parse_struct( from_typedef ); s32 level = 0;
for ( ; idx < tokens.Arr.num(); idx ++ )
{
if ( tokens[idx].Type == TokType::BraceCurly_Open )
level++;
else if ( check(TokType::Decl_Union) ) if ( tokens[idx].Type == TokType::BraceCurly_Close )
type = parse_union( from_typedef ); 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 else
type = parse_type(); type = parse_type( & is_function );
if ( check( TokType::Identifier ) ) if ( check( TokType::Identifier ) )
{ {
name = currtok; name = currtok;
eat( TokType::Identifier ); eat( TokType::Identifier );
} }
else else if ( ! is_function )
{ {
log_failure( "Error, expected identifier for typedef\n%s", Context.to_string() ); log_failure( "Error, expected identifier for typedef\n%s", Context.to_string() );
Context.pop(); Context.pop();
@ -4393,9 +4490,19 @@ CodeTypedef parse_typedef()
CodeTypedef CodeTypedef
result = (CodeTypedef) make_code(); result = (CodeTypedef) make_code();
result->Type = Typedef; result->Type = Typedef;
result->Name = get_cached_string( name );
result->ModuleFlags = mflags; 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; result->UnderlyingType = type;
if ( type->Type == Typename && array_expr && array_expr->Type != Invalid ) if ( type->Type == Typename && array_expr && array_expr->Type != Invalid )

View File

@ -1221,7 +1221,6 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module
{ {
using namespace ECode; using namespace ECode;
name_check( def_typedef, name );
null_check( def_typedef, type ); null_check( def_typedef, type );
switch ( type->Type ) switch ( type->Type )
@ -1260,12 +1259,28 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module
CodeTypedef CodeTypedef
result = (CodeTypedef) make_code(); result = (CodeTypedef) make_code();
result->Name = get_cached_string( name );
result->Type = ECode::Typedef; result->Type = ECode::Typedef;
result->ModuleFlags = mflags; result->ModuleFlags = mflags;
result->UnderlyingType = type; 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; return result;
} }

View File

@ -424,9 +424,16 @@ struct HashTable
for ( idx = 0; idx < Entries.num(); idx++ ) for ( idx = 0; idx < Entries.num(); idx++ )
{ {
Entry* entry; Entry* entry;
FindResult find_result; 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;
} }
} }