diff --git a/project/components/ast.cpp b/project/components/ast.cpp index 682338a..40eab2e 100644 --- a/project/components/ast.cpp +++ b/project/components/ast.cpp @@ -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 ) { diff --git a/project/components/ast.hpp b/project/components/ast.hpp index b1a7297..6174aac 100644 --- a/project/components/ast.hpp +++ b/project/components/ast.hpp @@ -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; diff --git a/project/components/ast_types.hpp b/project/components/ast_types.hpp index 20fe388..7a01151 100644 --- a/project/components/ast_types.hpp +++ b/project/components/ast_types.hpp @@ -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"); diff --git a/project/components/interface.parsing.cpp b/project/components/interface.parsing.cpp index 6bea715..fd23ee0 100644 --- a/project/components/interface.parsing.cpp +++ b/project/components/interface.parsing.cpp @@ -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; - - // ; - 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. - // ; + // * ; ok_to_parse = true; } @@ -2470,7 +2474,7 @@ Code parse_complicated_definition( Parser::TokType which ) { // Its a definition // { ... }; - 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 { ... } ; + 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. + // ; + ok_to_parse = true; + } + else if ( is_indirection ) + { + // Its a indirection type with type ID using struct namespace. + // * ; + 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 + // { ... }; + type = parse_foward_or_definition( currtok.Type, from_typedef ); + } + else if ( tok.Type == TokType::BraceSquare_Close) + { + // Its an array definition + // [ ... ]; + 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 ) diff --git a/project/components/interface.upfront.cpp b/project/components/interface.upfront.cpp index 1795673..6ee1502 100644 --- a/project/components/interface.upfront.cpp +++ b/project/components/interface.upfront.cpp @@ -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; } diff --git a/project/dependencies/containers.hpp b/project/dependencies/containers.hpp index ac233b9..cae7045 100644 --- a/project/dependencies/containers.hpp +++ b/project/dependencies/containers.hpp @@ -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; } }