From af11a85e940545bac0145931dcf71cb9207b8a8e Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Mon, 20 Jan 2020 21:11:07 -0800 Subject: [PATCH] Compressing Type Info Generation --- meta/foldhaus_meta.cpp | 63 ++- meta/foldhaus_meta_type_table.h | 281 +++++++--- meta/gs_meta.cpp | 596 +++++++++++++++++---- meta/gs_meta_code_generator.h | 100 ++++ meta/gs_meta_lexer.h | 3 +- meta/gs_meta_typeinfo_generator.h | 77 ++- src/foldhaus_app.h | 2 +- src/generated/foldhaus_nodes_generated.h | 25 +- src/generated/gs_meta_generated_typeinfo.h | 24 +- src/test_patterns.h | 37 +- src/win32_foldhaus.cpp | 1 + 11 files changed, 927 insertions(+), 282 deletions(-) create mode 100644 meta/gs_meta_code_generator.h diff --git a/meta/foldhaus_meta.cpp b/meta/foldhaus_meta.cpp index bb48e5d..a96ca69 100644 --- a/meta/foldhaus_meta.cpp +++ b/meta/foldhaus_meta.cpp @@ -1,15 +1,9 @@ // -// Usage +// File: foldhaus_meta.cpp +// Author: Peter Slattery +// Creation Date: 2020-01-19 // -// GSMetaTag() to give commands to the meta layer -// -// Tag Values -// -// breakpoint -// will cause the meta layer to break in the debugger when it reaches -// that point in processing the file -// TODO: specify which stage you want it to break at - +#ifndef FOLDHAUS_META_CPP #include "gs_meta.cpp" #include "gs_meta_typeinfo_generator.h" @@ -23,25 +17,64 @@ int main(int ArgCount, char* Args[]) } gs_meta_preprocessor Meta = PreprocessProgram(Args[1]); - s64 Cycles_Preprocess = GetWallClock(); typeinfo_generator TypeGenerator = InitTypeInfoGenerator(Meta.TypeTable); - GenerateFilteredTypeInfo(MakeStringLiteral("node_struct"), Meta.TypeTable, &TypeGenerator); GenerateFilteredTypeInfo(MakeStringLiteral("gen_type_info"), Meta.TypeTable, &TypeGenerator); - FinishGeneratingTypes(&TypeGenerator); + gsm_code_generator NodeTypeGen = BeginEnumGeneration("node_type", "NodeType", false, true); + +#if 0 + // TODO(Peter): Create a FilterTypesByTag function to create a contiguous array + // of type_definition** + printf("\n\n"); + for (u32 i = 0; i < Meta.TypeTable.Types.Used; i++) + { + type_definition* Decl = Meta.TypeTable.Types.GetElementAtIndex(i); + if (HasTag(MakeStringLiteral("node_proc"), Decl->MetaTags) && + Decl->Type == TypeDef_Function) + { + AddEnumElement(&NodeTypeGen, Decl->Identifier); + + type_table_handle ReturnTypeHandle = Decl->Function.ReturnTypeHandle; + type_definition* ReturnType = GetTypeDefinition(ReturnTypeHandle, Meta.TypeTable); + printf("%.*s %.*s(\n", StringExpand(ReturnType->Identifier), StringExpand(Decl->Identifier)); + for (u32 j = 0; j < Decl->Function.Parameters.Used; j++) + { + variable_decl* Param = Decl->Function.Parameters.GetElementAtIndex(j); + type_table_handle ParamTypeHandle = Param->TypeHandle; + type_definition* ParamType = GetTypeDefinition(ParamTypeHandle, Meta.TypeTable); + printf(" %.*s %.*s,\n", StringExpand(ParamType->Identifier), StringExpand(Param->Identifier)); + } + printf(");\n\n"); + } + } + printf("\n\n"); +#endif + + FinishEnumGeneration(&NodeTypeGen); + FILE* TypeInfoH = fopen("C:\\projects\\foldhaus\\src\\generated\\gs_meta_generated_typeinfo.h", "w"); if (TypeInfoH) { - WriteStringBuilderToFile(TypeGenerator.TypeList, TypeInfoH); + WriteStringBuilderToFile(*TypeGenerator.TypeList.Builder, TypeInfoH); WriteStringBuilderToFile(TypeGenerator.StructMembers, TypeInfoH); WriteStringBuilderToFile(TypeGenerator.TypeDefinitions, TypeInfoH); fclose(TypeInfoH); } + FILE* NodeInfoH = fopen("C:\\projects\\foldhaus\\src\\generated\\foldhaus_nodes_generated.h", "w"); + if (NodeInfoH) + { + WriteStringBuilderToFile(*NodeTypeGen.Builder, NodeInfoH); + fclose(NodeInfoH); + } + FinishMetaprogram(&Meta); //__debugbreak(); return 0; -} \ No newline at end of file +} + +#define FOLDHAUS_META_CPP +#endif // FOLDHAUS_META_CPP \ No newline at end of file diff --git a/meta/foldhaus_meta_type_table.h b/meta/foldhaus_meta_type_table.h index efb56db..3b3faad 100644 --- a/meta/foldhaus_meta_type_table.h +++ b/meta/foldhaus_meta_type_table.h @@ -16,10 +16,17 @@ enum type_definition_type TypeDef_Union, TypeDef_BasicType, TypeDef_FunctionPointer, + TypeDef_Function, TypeDef_Count, }; +struct type_table_handle +{ + s32 BucketIndex; + u32 IndexInBucket; +}; + struct meta_tag { string Identifier; @@ -31,7 +38,7 @@ struct variable_decl // at the same time. This means that not all types will be able to be matched // up on the first pass through. A TypeIndex of -1 means we need to fixup that // type at a later time - s32 TypeIndex; + type_table_handle TypeHandle; string Identifier; b32 Pointer; @@ -45,6 +52,7 @@ struct variable_decl struct struct_decl { + b32 IsAnonymous; // TODO(Peter): Lots of tiny arrays everywhere! Pull these into a central allocation // buffer somewhere // :SmallAllocationsAllOver @@ -53,11 +61,18 @@ struct struct_decl struct function_pointer_decl { - s32 ReturnTypeIndex; + type_table_handle ReturnTypeHandle; // :SmallAllocationsAllOver gs_bucket Parameters; }; +struct function_decl +{ + type_table_handle ReturnTypeHandle; + gs_bucket Parameters; + // TODO(Peter): AST? +}; + struct enum_decl { gs_bucket Identifiers; @@ -80,13 +95,22 @@ struct type_definition enum_decl Enum; struct_decl Struct; function_pointer_decl FunctionPtr; + function_decl Function; }; b32 Pointer; }; +#define TYPE_TABLE_BUCKET_MAX 1024 +struct type_table_hash_bucket +{ + u32* Keys; + type_definition* Values; +}; + struct type_table { - gs_bucket Types; + type_table_hash_bucket* Types; + u32 TypeBucketsCount; }; internal b32 @@ -119,63 +143,190 @@ CopyMetaTagsAndClear(gs_bucket* Source, gs_bucket* Dest) Source->Used = 0; } -internal s32 +#define InvalidTypeTableHandle type_table_handle{0, 0} + +// #define TypeHandleIsValid(handle) (!((handle).BucketIndex == 0) && ((handle).IndexInBucket == 0)) +inline b32 TypeHandleIsValid(type_table_handle A) +{ + b32 FirstBucket = (A.BucketIndex == 0); + b32 FirstIndex = (A.IndexInBucket == 0); + b32 Both = FirstBucket && FirstIndex; + return !Both; +} + +#define TypeHandlesEqual(a, b) (((a).BucketIndex == (b).BucketIndex) && ((a).IndexInBucket == (b).IndexInBucket)) + +internal u32 +HashIdentifier(string Identifier) +{ + u32 IdentHash = HashString(Identifier); + if (IdentHash == 0) + { + // NOTE(Peter): We are excluding a has of zero so taht + // the type_table_handle where BucketIndex and IndexInBucket + // are both zero is an invalid handle + IdentHash += 1; + } + return IdentHash; +} + +internal type_table_handle +PushTypeOnHashTable(type_definition TypeDef, type_table* TypeTable) +{ + type_table_handle Result = InvalidTypeTableHandle; + + u32 IdentHash = HashIdentifier(TypeDef.Identifier); + u32 Index = IdentHash % TYPE_TABLE_BUCKET_MAX; + + for (u32 b = 0; b < TypeTable->TypeBucketsCount; b++) + { + type_table_hash_bucket* Bucket = TypeTable->Types + b; + if (Bucket->Keys[Index] == 0) + { + Bucket->Keys[Index] = IdentHash; + Bucket->Values[Index] = TypeDef; + + Result.BucketIndex = b; + Result.IndexInBucket = Index; + } + } + + if (!TypeHandleIsValid(Result)) + { + // Grow Hash Table + u32 NewTypeBucketIndex = TypeTable->TypeBucketsCount++; + u32 NewTypesSize = TypeTable->TypeBucketsCount * sizeof(type_table_hash_bucket); + TypeTable->Types = (type_table_hash_bucket*)realloc(TypeTable->Types, NewTypesSize); + + type_table_hash_bucket* NewBucket = TypeTable->Types + NewTypeBucketIndex; + NewBucket->Keys = (u32*)malloc(sizeof(u32) * TYPE_TABLE_BUCKET_MAX); + NewBucket->Values = (type_definition*)malloc(sizeof(type_definition) * TYPE_TABLE_BUCKET_MAX); + GSZeroMemory((u8*)NewBucket->Keys, sizeof(u32) * TYPE_TABLE_BUCKET_MAX); + GSZeroMemory((u8*)NewBucket->Values, sizeof(type_definition) * TYPE_TABLE_BUCKET_MAX); + + NewBucket->Keys[Index] = IdentHash; + NewBucket->Values[Index] = TypeDef; + + Result.BucketIndex = NewTypeBucketIndex; + Result.IndexInBucket = Index; + } + + return Result; +} + +internal type_table_handle PushUndeclaredType (string Identifier, type_table* TypeTable) { type_definition UndeclaredTypeDef = {}; UndeclaredTypeDef.Identifier = Identifier; UndeclaredTypeDef.Type = TypeDef_Unknown; - s32 TypeIndex = (s32)TypeTable->Types.PushElementOnBucket(UndeclaredTypeDef); - return TypeIndex; + type_table_handle Result = PushTypeOnHashTable(UndeclaredTypeDef, TypeTable); + return Result; } -internal s32 -GetIndexOfType (string Identifier, type_table TypeTable) +internal type_table_handle +GetTypeHandle (string Identifier, type_table TypeTable) { - s32 Result = -1; - for (u32 i = 0; i < TypeTable.Types.Used; i++) + type_table_handle Result = InvalidTypeTableHandle; + + u32 IdentHash = HashIdentifier(Identifier); + u32 Index = IdentHash % TYPE_TABLE_BUCKET_MAX; + + for (u32 b = 0; b < TypeTable.TypeBucketsCount; b++) { - type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); - if (StringsEqual(Identifier, TypeDef->Identifier)) + type_table_hash_bucket Bucket = TypeTable.Types[b]; + if (Bucket.Keys[Index] == IdentHash) { - Result = i; + Result.BucketIndex = b; + Result.IndexInBucket = Index; + break; + } + } + + return Result; +} + +// Guaranteed to return a valid result +internal type_definition* +GetTypeDefinition(type_table_handle Handle, type_table TypeTable) +{ + Assert(TypeHandleIsValid(Handle)); + type_definition* Result = 0; + if (TypeTable.Types[Handle.BucketIndex].Keys != 0) + { + Result = TypeTable.Types[Handle.BucketIndex].Values + Handle.IndexInBucket; + } + return Result; +} + +// May return zero +internal type_definition* +GetTypeDefinitionUnsafe(type_table_handle Handle, type_table TypeTable) +{ + type_definition* Result = 0; + if (TypeTable.Types[Handle.BucketIndex].Keys != 0) + { + Result = TypeTable.Types[Handle.BucketIndex].Values + Handle.IndexInBucket; + } + return Result; +} + +internal type_definition* +GetTypeDefinition(string Identifier, type_table TypeTable) +{ + type_definition* Result = 0; + u32 IdentHash = HashIdentifier(Identifier); + u32 Index = IdentHash % TYPE_TABLE_BUCKET_MAX; + for (u32 b = 0; b < TypeTable.TypeBucketsCount; b++) + { + type_table_hash_bucket Bucket = TypeTable.Types[b]; + if (Bucket.Keys[Index] == IdentHash ) + { + Result = Bucket.Values + Index; break; } } return Result; } -internal s32 +internal type_table_handle PushTypeDefOnTypeTable(type_definition TypeDef, type_table* TypeTable) { - s32 Index = -1; + // NOTE(Peter): We don't accept type definitions with empty identifiers. + // If a struct or union is anonymous, it should be assigned a name of the form + // parent_struct_name_# where # is the member index + // ie. + // struct foo { int a; union { int x }; }; + // the union in foo would have the identifier foo_1 + Assert(TypeDef.Identifier.Length != 0); - s32 ExistingUndeclaredTypeIndex = GetIndexOfType(TypeDef.Identifier, *TypeTable); + type_table_handle Result = InvalidTypeTableHandle; + type_table_handle ExistingUndeclaredTypeHandle = GetTypeHandle(TypeDef.Identifier, *TypeTable); - // NOTE(Peter): If the identifier length is zero, they will all match with the - // first anonymous struct/union member. So every anon struct/union gets its own - // typeef - if (ExistingUndeclaredTypeIndex < 0 || TypeDef.Identifier.Length == 0) + if (!TypeHandleIsValid(ExistingUndeclaredTypeHandle)) { - Index = TypeTable->Types.PushElementOnBucket(TypeDef); + Result = PushTypeOnHashTable(TypeDef, TypeTable); } else { - Index = ExistingUndeclaredTypeIndex; - type_definition* ExistingTypeDef = TypeTable->Types.GetElementAtIndex(ExistingUndeclaredTypeIndex); + Result = ExistingUndeclaredTypeHandle; + type_definition* ExistingTypeDef = GetTypeDefinition(Result, *TypeTable); + Assert(ExistingTypeDef != 0); *ExistingTypeDef = TypeDef; } - return Index; + return Result; } internal s32 -GetSizeOfType (s32 TypeIndex, type_table TypeTable) +GetSizeOfType (type_table_handle TypeHandle, type_table TypeTable) { s32 Result = -1; - Assert(TypeIndex >= 0 && (u32)TypeIndex < TypeTable.Types.Used); - type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(TypeIndex); - Result = TypeDef->Size; + type_definition* TypeDef = GetTypeDefinition(TypeHandle, TypeTable); + if (TypeDef) + { + Result = TypeDef->Size; + } return Result; } @@ -183,14 +334,10 @@ internal s32 GetSizeOfType (string Identifier, type_table TypeTable) { s32 Result = -1; - for (u32 i = 0; i < TypeTable.Types.Used; i++) + type_definition* TypeDef = GetTypeDefinition(Identifier, TypeTable); + if (TypeDef) { - type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); - if (StringsEqual(Identifier, TypeDef->Identifier)) - { - Result = TypeDef->Size; - break; - } + Result = TypeDef->Size; } return Result; } @@ -199,7 +346,7 @@ internal b32 VariableDeclsEqual (variable_decl A, variable_decl B) { b32 Result = false; - if (A.TypeIndex == B.TypeIndex && + if (TypeHandlesEqual(A.TypeHandle, B.TypeHandle) && A.ArrayCount == B.ArrayCount && StringsEqual(A.Identifier, B.Identifier)) { @@ -236,51 +383,35 @@ StructOrUnionsEqual (type_definition A, type_definition B) return Result; } -internal s32 -FindIndexOfMatchingType (type_definition Match, type_table TypeTable) +internal type_table_handle +FindHandleOfMatchingType (type_definition Match, type_table TypeTable) { - s32 Result = -1; - for (u32 i = 0; i < TypeTable.Types.Used; i++) + type_table_handle Result = InvalidTypeTableHandle; + type_table_handle Handle = GetTypeHandle(Match.Identifier, TypeTable); + if (TypeHandleIsValid(Handle)) { - type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); - if (StringsEqual(Match.Identifier, TypeDef->Identifier)) - { - if (Match.Type == TypeDef_Struct || - Match.Type == TypeDef_Union) - { - if (StructOrUnionsEqual(Match, *TypeDef)) - { - Result = (s32)i; - break; - } - } - else - { - Result = (s32)i; - break; - } - } + Result = Handle; } return Result; } -internal void FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors); -internal void FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors); +internal void FixUpStructSize (type_table_handle TypeHandle, type_table TypeTable, errors* Errors); +internal void FixUpUnionSize (type_table_handle TypeHandle, type_table TypeTable, errors* Errors); internal void FixupMemberType (variable_decl* Member, type_table TypeTable) { - if (Member->TypeIndex == -1) + if (!TypeHandleIsValid(Member->TypeHandle)) { - Member->TypeIndex = GetIndexOfType(Member->Identifier, TypeTable); + Member->TypeHandle = GetTypeHandle(Member->Identifier, TypeTable); } - Assert(Member->TypeIndex >= 0); + Assert(TypeHandleIsValid(Member->TypeHandle)); } internal s32 CalculateStructMemberSize (variable_decl Member, type_definition MemberType) { - Assert(Member.TypeIndex >= 0); + Assert(TypeHandleIsValid(Member.TypeHandle)); // NOTE(Peter): At one point we were Asserting on struct sizes of zero, but // that's actually incorrect. It is valid to have an empty struct. @@ -325,11 +456,11 @@ FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_t { if (MemberTypeDef->Type == TypeDef_Struct) { - FixUpStructSize(Member->TypeIndex, TypeTable, Errors); + FixUpStructSize(Member->TypeHandle, TypeTable, Errors); } else if (MemberTypeDef->Type == TypeDef_Union) { - FixUpUnionSize(Member->TypeIndex, TypeTable, Errors); + FixUpUnionSize(Member->TypeHandle, TypeTable, Errors); } else { @@ -353,9 +484,9 @@ FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_t } internal void -FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors) +FixUpStructSize (type_table_handle TypeHandle, type_table TypeTable, errors* Errors) { - type_definition* Struct = TypeTable.Types.GetElementAtIndex(StructIndex); + type_definition* Struct = GetTypeDefinition(TypeHandle, TypeTable); Assert(Struct->Type == TypeDef_Struct); if (HasTag(MakeStringLiteral("breakpoint"), Struct->MetaTags)) @@ -369,12 +500,10 @@ FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors) variable_decl* Member = Struct->Struct.MemberDecls.GetElementAtIndex(j); FixupMemberType(Member, TypeTable); - if (Member->TypeIndex >= 0) + if (TypeHandleIsValid(Member->TypeHandle)) { - type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); - + type_definition* MemberTypeDef = GetTypeDefinition(Member->TypeHandle, TypeTable); FixupStructMember(Member, MemberTypeDef, TypeTable, Errors); - u32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef); SizeAcc += MemberSize; } @@ -400,9 +529,9 @@ FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors) } internal void -FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors) +FixUpUnionSize (type_table_handle TypeHandle, type_table TypeTable, errors* Errors) { - type_definition* Union = TypeTable.Types.GetElementAtIndex(UnionIndex); + type_definition* Union = GetTypeDefinition(TypeHandle, TypeTable); Assert(Union->Type == TypeDef_Union); s32 BiggestMemberSize = 0; @@ -411,9 +540,9 @@ FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors) variable_decl* Member = Union->Struct.MemberDecls.GetElementAtIndex(j); FixupMemberType(Member, TypeTable); - if (Member->TypeIndex >= 0) + if (TypeHandleIsValid(Member->TypeHandle)) { - type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); + type_definition* MemberTypeDef = GetTypeDefinition(Member->TypeHandle, TypeTable); FixupStructMember(Member, MemberTypeDef, TypeTable, Errors); s32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef); BiggestMemberSize = GSMax(BiggestMemberSize, MemberSize); diff --git a/meta/gs_meta.cpp b/meta/gs_meta.cpp index 24d034c..260b082 100644 --- a/meta/gs_meta.cpp +++ b/meta/gs_meta.cpp @@ -1,3 +1,22 @@ +// +// File: gs_meta.cpp +// Author: Peter Slattery +// Creation Date: 2020-01-19 +// +// +// Usage +// +// GSMetaTag() to give commands to the meta layer +// +// Tag Values +// +// breakpoint +// will cause the meta layer to break in the debugger when it reaches +// that point in processing the file +// TODO: specify which stage you want it to break at + +#ifndef GS_META_CPP + #include #include @@ -37,6 +56,31 @@ struct token_iter errors* Errors; }; +struct gsm_profiler_scope +{ + s64 StartTime; + s64 EndTime; + r32 Seconds; + r32 LongestSeconds; + u32 CallCount; + string Category; + string Identifier; +}; + +struct gsm_profiler_category +{ + string Identifier; + r32 TotalTime; + u32 SubscopesCount; + gsm_profiler_scope* LongestSubscope; +}; + +struct gsm_profiler +{ + gs_bucket Scopes; + gs_bucket Categories; +}; + struct gs_meta_preprocessor { errors Errors; @@ -50,7 +94,12 @@ struct gs_meta_preprocessor // Performance s64 PreprocessorStartTime; + s64 TokenizeTime; + s64 PreprocTime; + s64 FixupTime; s64 PreprocessorEndTime; + + gsm_profiler Profiler; }; // ------------------------ @@ -80,13 +129,145 @@ GetPerformanceFrequency () } return (s64)Frequency.QuadPart; } +internal r32 +GetSecondsElapsed(s64 CyclesCount) +{ + s64 Frequency = GetPerformanceFrequency(); + r32 SecondsElapsed = (r32)(CyclesCount) / (r32)(Frequency); + return SecondsElapsed; +} internal r32 GetSecondsElapsed(s64 StartCycles, s64 EndCycles) { - s64 Frequency = GetPerformanceFrequency(); - r32 SecondsElapsed = (r32)(EndCycles - StartCycles) / (r32)(Frequency); - return SecondsElapsed; + return GetSecondsElapsed(EndCycles - StartCycles); +} + +internal gsm_profiler_scope* +FindMatchingScope(gsm_profiler* Profiler, string Category, string Identifier) +{ + gsm_profiler_scope* Result = 0; + for (u32 i = 0; i < Profiler->Scopes.Used; i++) + { + gsm_profiler_scope* Scope = Profiler->Scopes.GetElementAtIndex(i); + if (StringsEqual(Scope->Identifier, Identifier) && + StringsEqual(Scope->Category, Category)) + { + Result = Scope; + break; + } + } + return Result; +} + +internal gsm_profiler_scope* +BeginScope(gsm_profiler* Profiler, string Category, string Identifier) +{ + gsm_profiler_scope* Scope = FindMatchingScope(Profiler, Category, Identifier); + if (!Scope) + { + Scope = Profiler->Scopes.TakeElement(); + *Scope = {}; + } + Scope->Category = Category; + Scope->Identifier = Identifier; + Scope->StartTime = GetWallClock(); + return Scope; +} + +internal gsm_profiler_scope* +BeginScope(gsm_profiler* Profiler, char* Category, char* Identifier) +{ + return BeginScope(Profiler, MakeStringLiteral(Category), MakeStringLiteral(Identifier)); +} + +internal void +EndScope(gsm_profiler_scope* Scope) +{ + Scope->EndTime = GetWallClock(); + r32 Seconds = GetSecondsElapsed(Scope->StartTime, Scope->EndTime); + Scope->Seconds += Seconds; + if (Seconds > Scope->LongestSeconds) + { + Scope->LongestSeconds = Seconds; + } + Scope->CallCount++; +} + +internal gsm_profiler_category* +GetCategory(string Identifier, gsm_profiler* Profiler) +{ + gsm_profiler_category* Result = 0; + + for (u32 i = 0; i < Profiler->Categories.Used; i++) + { + gsm_profiler_category* Category = Profiler->Categories.GetElementAtIndex(i); + if (StringsEqual(Identifier, Category->Identifier)) + { + Result = Category; + break; + } + } + + if (Result == 0) + { + Result = Profiler->Categories.TakeElement(); + *Result = {}; + Result->Identifier = Identifier; + } + + return Result; +} + +internal void +FinishProfiler(gsm_profiler* Profiler) +{ + for (u32 i = 0; i < Profiler->Scopes.Used; i++) + { + gsm_profiler_scope* Scope = Profiler->Scopes.GetElementAtIndex(i); + gsm_profiler_category* Category = GetCategory(Scope->Category, Profiler); + Category->TotalTime += Scope->Seconds; + Category->SubscopesCount++; + + if (!Category->LongestSubscope || + Scope->Seconds > Category->LongestSubscope->Seconds) + { + Category->LongestSubscope = Scope; + } + } +} + +internal void +PrintAllCategories(gsm_profiler* Profiler) +{ + for (u32 i = 0; i < Profiler->Categories.Used; i++) + { + gsm_profiler_category* Category = Profiler->Categories.GetElementAtIndex(i); + printf("Category: %.*s Total Time: %.*f Count: %d\n", + StringExpand(Category->Identifier), + 6, Category->TotalTime, + Category->SubscopesCount); + printf(" Longest Scope: %.*s Total Time: %.*f Longest Time: %.*f Call Count: %d\n", + StringExpand(Category->LongestSubscope->Identifier), + 6, Category->LongestSubscope->Seconds, + 6, Category->LongestSubscope->LongestSeconds, + Category->LongestSubscope->CallCount); + + if (StringsEqual(Category->Identifier, MakeStringLiteral("parse"))) + { + for (u32 j = 0; j < Profiler->Scopes.Used; j++) + { + gsm_profiler_scope* Scope = Profiler->Scopes.GetElementAtIndex(j); + if (StringsEqual(Scope->Category, Category->Identifier)) + { + printf(" Time: %.*f Call Count: %d Scope: %.*s\n", + 6, Scope->Seconds, + Scope->CallCount, + StringExpand(Scope->Identifier)); + } + } + } + } } // ------------------------ @@ -301,8 +482,11 @@ TokenizeFile (source_code_file* File, gs_bucket* Tokens) // ------------------------ internal b32 -ParseMetaTag(token_iter* Iter, gs_bucket* TagList) +ParseMetaTag(token_iter* Iter, gs_meta_preprocessor* Meta) { + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseMetaTag")); b32 Result = false; PushSnapshot(Iter); @@ -312,7 +496,7 @@ ParseMetaTag(token_iter* Iter, gs_bucket* TagList) token MetaIdentifier = {0}; if (TokenAtEquals(Iter, Token_Identifier, &MetaIdentifier)) { - TagList->PushElementOnBucket(MetaIdentifier); + Meta->TagList.PushElementOnBucket(MetaIdentifier); if (StringsEqual(MetaIdentifier.Text, MakeStringLiteral("breakpoint"))) { // NOTE(Peter): This is not a temporary breakpoint. It is @@ -330,6 +514,7 @@ ParseMetaTag(token_iter* Iter, gs_bucket* TagList) } ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); return Result; } @@ -352,7 +537,7 @@ ParseSignedness (token_iter* Iter) } internal b32 -ShortInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +ShortInt (token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -370,13 +555,13 @@ ShortInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) ApplySnapshotIfNotParsedAndPop(Result, Iter); if (Result) { - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("short int"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("short int"), TypeTable); } return Result; } internal b32 -Int (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +Int (token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -390,13 +575,13 @@ Int (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) ApplySnapshotIfNotParsedAndPop(Result, Iter); if (Result) { - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("int"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("int"), TypeTable); } return Result; } internal b32 -LongInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +LongInt (token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -414,13 +599,13 @@ LongInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) ApplySnapshotIfNotParsedAndPop(Result, Iter); if (Result) { - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("long int"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("long int"), TypeTable); } return Result; } internal b32 -LongLongInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +LongLongInt (token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -441,13 +626,13 @@ LongLongInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) ApplySnapshotIfNotParsedAndPop(Result, Iter); if (Result) { - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("long long int"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("long long int"), TypeTable); } return Result; } internal b32 -ParseChar(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +ParseChar(token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -456,12 +641,12 @@ ParseChar(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) if (TokenAtEquals(Iter, "char")) { Result = true; - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("char"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("char"), TypeTable); } else if (TokenAtEquals(Iter, "wchar_t")) { Result = true; - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("wchar_t"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("wchar_t"), TypeTable); } ApplySnapshotIfNotParsedAndPop(Result, Iter); @@ -469,7 +654,7 @@ ParseChar(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) } internal b32 -ParseBool(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +ParseBool(token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -477,7 +662,7 @@ ParseBool(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) if (TokenAtEquals(Iter, "bool")) { Result = true; - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("bool"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("bool"), TypeTable); } ApplySnapshotIfNotParsedAndPop(Result, Iter); @@ -485,7 +670,7 @@ ParseBool(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) } internal b32 -ParseFloat(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +ParseFloat(token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -493,7 +678,7 @@ ParseFloat(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) if (TokenAtEquals(Iter, "float")) { Result = true; - *TypeIndexOut= GetIndexOfType(MakeStringLiteral("float"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("float"), TypeTable); } ApplySnapshotIfNotParsedAndPop(Result, Iter); @@ -501,7 +686,7 @@ ParseFloat(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) } internal b32 -ParseDouble(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) +ParseDouble(token_iter* Iter, type_table_handle* TypeHandleOut, type_table TypeTable) { b32 Result = false; PushSnapshot(Iter); @@ -509,7 +694,7 @@ ParseDouble(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) if (TokenAtEquals(Iter, "double")) { Result = true; - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("double"), TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("double"), TypeTable); } ApplySnapshotIfNotParsedAndPop(Result, Iter); @@ -520,20 +705,23 @@ ParseDouble(token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) // NOTE(Peter): If TypeIndexOut is -1, you need to call NextToken after this // function to advance past the type identifier. internal b32 -ParseType(token_iter* Iter, type_table* TypeTable, s32* TypeIndexOut) +ParseType(token_iter* Iter, gs_meta_preprocessor* Meta, type_table_handle* TypeHandleOut) { + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseType")); b32 Result = false; - *TypeIndexOut = -1; + *TypeHandleOut = InvalidTypeTableHandle; PushSnapshot(Iter); - if (ParseChar(Iter, TypeIndexOut, *TypeTable) || - ParseBool(Iter, TypeIndexOut, *TypeTable) || - LongLongInt(Iter, TypeIndexOut, *TypeTable) || - LongInt(Iter, TypeIndexOut, *TypeTable) || - ShortInt(Iter, TypeIndexOut, *TypeTable) || - Int(Iter, TypeIndexOut, *TypeTable) || - ParseFloat(Iter, TypeIndexOut, *TypeTable) || - ParseDouble(Iter, TypeIndexOut, *TypeTable)) + if (ParseChar(Iter, TypeHandleOut, Meta->TypeTable) || + ParseBool(Iter, TypeHandleOut, Meta->TypeTable) || + LongLongInt(Iter, TypeHandleOut, Meta->TypeTable) || + LongInt(Iter, TypeHandleOut, Meta->TypeTable) || + ShortInt(Iter, TypeHandleOut, Meta->TypeTable) || + Int(Iter, TypeHandleOut, Meta->TypeTable) || + ParseFloat(Iter, TypeHandleOut, Meta->TypeTable) || + ParseDouble(Iter, TypeHandleOut, Meta->TypeTable)) { Result = true; } @@ -541,12 +729,16 @@ ParseType(token_iter* Iter, type_table* TypeTable, s32* TypeIndexOut) { NextToken(Iter); Result = true; - *TypeIndexOut = GetIndexOfType(MakeStringLiteral("void"), *TypeTable); + *TypeHandleOut = GetTypeHandle(MakeStringLiteral("void"), Meta->TypeTable); } else { - *TypeIndexOut = GetIndexOfType(Iter->TokenAt->Text, *TypeTable); - if (*TypeIndexOut >= 0) + gsm_profiler_scope* ProfileInnerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseTypeInner")); + + *TypeHandleOut = GetTypeHandle(Iter->TokenAt->Text, Meta->TypeTable); + if (TypeHandleIsValid(*TypeHandleOut)) { Result = true; NextToken(Iter); @@ -561,11 +753,14 @@ ParseType(token_iter* Iter, type_table* TypeTable, s32* TypeIndexOut) // In the case that we get an as-of-yet undeclared type, we leave it // up to the calling site to determine what to do with that information // :UndeclaredType - *TypeIndexOut = -1; + *TypeHandleOut = InvalidTypeTableHandle; } + + EndScope(ProfileInnerScope); } ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); return Result; } @@ -597,8 +792,11 @@ ParseConstVolatile (token_iter* Iter) } internal b32 -ParseVariableDecl(token_iter* Iter, gs_bucket* TagList, gs_bucket* VariableList, type_table* TypeTable) +ParseVariableDecl(token_iter* Iter, gs_bucket* VariableList, gs_meta_preprocessor* Meta) { + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseVariableDecl")); b32 Result = false; PushSnapshot(Iter); @@ -609,13 +807,13 @@ ParseVariableDecl(token_iter* Iter, gs_bucket* TagList, gs_bucketTokenAt->Text, TypeTable); + TypeHandle = PushUndeclaredType(Iter->TokenAt->Text, &Meta->TypeTable); NextToken(Iter); } @@ -626,7 +824,7 @@ ParseVariableDecl(token_iter* Iter, gs_bucket* TagList, gs_bucket* TagList, gs_bucketTokenAt->Text, MakeStringLiteral("]"))) { - ArrayParseSuccess = true; + NextToken(Iter); } } + + if (TokenAtEquals(Iter, "]")) + { + ArrayParseSuccess = true; + } } if (ArrayParseSuccess) @@ -661,16 +867,54 @@ ParseVariableDecl(token_iter* Iter, gs_bucket* TagList, gs_bucketTakeElement(); *Decl = {}; Decl->Identifier = IdentifierToken.Text; - Decl->TypeIndex = TypeIndex; + Decl->TypeHandle = TypeHandle; Decl->Pointer = IsPointer; Decl->ArrayCount = ArrayCount; - CopyMetaTagsAndClear(TagList, &Decl->MetaTags); + CopyMetaTagsAndClear(&Meta->TagList, &Decl->MetaTags); } } - } while (TokenAtEquals(Iter, ",")); + + if (StringsEqual(Iter->TokenAt->Text, MakeStringLiteral(","))) + { + // NOTE(Peter): There are two ways we enter this case + // 1. We are parsing a declaration list ie. r32 x, y, z; + // 2. We are parsing a function parameter list ie void proc(r32 x, u32 y) + // In this instance, we could still be parsing a declaration list + // ie. this is valid: void proc(r32 x, y, double z) + + // This first snapshot is so we can rewind to before the comma in the event that + // we are parsing a function parameter list + PushSnapshot(Iter); + NextToken(Iter); + + // This second snapshot is so we can rewind to just _after_ the comma + // and continue parsing in the event that we are in a declaration list + PushSnapshot(Iter); + + if (TokenAtEquals(Iter, Token_Identifier) && + (TokenAtEquals(Iter, ",") || TokenAtEquals(Iter, ";"))) + { + // We are in a declaration list (case 1) + ApplySnapshotIfNotParsedAndPop(false, Iter); + PopSnapshot(Iter); // We don't need the first snapshot in this case + } + else + { + // We are in a function parameter list (case 2) + ApplySnapshotIfNotParsedAndPop(false, Iter); + ApplySnapshotIfNotParsedAndPop(false, Iter); + break; + } + } + else + { + break; + } + } } ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); return Result; } @@ -691,11 +935,17 @@ StructOrUnion(token_iter* Iter, type_definition_type* Type) return Result; } +// NOTE(Peter): ContainingStruct will be 0 in all cases except when the struct or union +// is anonymous. In those cases, it MUST be the struct or union +// containing the anonymous struct/union internal b32 -ParseStruct(token_iter* Iter, s32* StructTypeIndexOut, gs_bucket* TagList, type_table* TypeTable) +ParseStruct(token_iter* Iter, type_table_handle* StructTypeHandleOut, gs_meta_preprocessor* Meta, type_definition* ContainingStruct = 0) { + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseStruct")); b32 Result = false; - *StructTypeIndexOut = -1; + *StructTypeHandleOut = InvalidTypeTableHandle; PushSnapshot(Iter); @@ -709,35 +959,58 @@ ParseStruct(token_iter* Iter, s32* StructTypeIndexOut, gs_bucket* TagList if (TokenAtEquals(Iter, "{")) { type_definition StructDecl = {}; - StructDecl.Identifier = IdentifierToken.Text; + if (IdentifierToken.Text.Length > 0) + { + StructDecl.Identifier = IdentifierToken.Text; + StructDecl.Struct.IsAnonymous = false; + } + else + { + Assert(ContainingStruct); + Assert(ContainingStruct->Identifier.Length > 0); + // NOTE(Peter): I'm not sure this is neccessary, but I don't know what + // cases that its not true would be so I'm asserting just to find out + Assert(ContainingStruct->Type == TypeDef_Union || + ContainingStruct->Type == TypeDef_Struct); + + string AnonStructIdentifier = {}; + AnonStructIdentifier.Max = 256; + AnonStructIdentifier.Memory = (char*)malloc(sizeof(char) * AnonStructIdentifier.Max); + + PrintF(&AnonStructIdentifier, "%S_%d", ContainingStruct->Identifier, ContainingStruct->Struct.MemberDecls.Used); + + StructDecl.Identifier = AnonStructIdentifier; + StructDecl.Struct.IsAnonymous = true; + } + StructDecl.Type = DeclType; - CopyMetaTagsAndClear(TagList, &StructDecl.MetaTags); + CopyMetaTagsAndClear(&Meta->TagList, &StructDecl.MetaTags); while (!TokenAtEquals(Iter, "}")) { - s32 MemberStructTypeIndex = {}; + type_table_handle MemberStructTypeHandle = InvalidTypeTableHandle; variable_decl MemberDecl = {}; - if (ParseMetaTag(Iter, TagList)) + if (ParseMetaTag(Iter, Meta)) { } - else if (ParseVariableDecl(Iter, TagList, &StructDecl.Struct.MemberDecls, TypeTable)) + else if (ParseVariableDecl(Iter, &StructDecl.Struct.MemberDecls, Meta)) { if (!TokenAtEquals(Iter, ";")) { PushFError(Iter->Errors, "No semicolon after struct member variable declaration. %S", StructDecl.Identifier); } } - else if (ParseStruct(Iter, &MemberStructTypeIndex, TagList, TypeTable)) + else if (ParseStruct(Iter, &MemberStructTypeHandle, Meta, &StructDecl)) { // NOTE(Peter): Pretty sure, since we just parsed the struct, that - // MemberStructTypeIndex should never be -1 (unknown type). + // MemberStructTypeIndex should never be Invalid (unknown type). // Putting this Assert here for now, but remove if there's a valid // reason that you might not be able to find a struct just parsed at // this point. - Assert(MemberStructTypeIndex >= 0); + Assert(TypeHandleIsValid(MemberStructTypeHandle)); - MemberDecl.TypeIndex = MemberStructTypeIndex; + MemberDecl.TypeHandle = MemberStructTypeHandle; StructDecl.Struct.MemberDecls.PushElementOnBucket(MemberDecl); } else @@ -753,18 +1026,19 @@ ParseStruct(token_iter* Iter, s32* StructTypeIndexOut, gs_bucket* TagList if (TokenAtEquals(Iter, ";")) { Result = true; - *StructTypeIndexOut = PushTypeDefOnTypeTable(StructDecl, TypeTable); + *StructTypeHandleOut = PushTypeDefOnTypeTable(StructDecl, &Meta->TypeTable); } } } ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); return Result; } // ( type *? identifier, ... ) internal b32 -ParseFunctionParameterList (token_iter* Iter, type_definition* FunctionPtrDecl, gs_bucket* TagList, type_table* TypeTable) +ParseFunctionParameterList (token_iter* Iter, type_definition* FunctionPtrDecl, gs_meta_preprocessor* Meta) { b32 Result = false; PushSnapshot(Iter); @@ -775,7 +1049,7 @@ ParseFunctionParameterList (token_iter* Iter, type_definition* FunctionPtrDecl, while(!StringsEqual(Iter->TokenAt->Text, MakeStringLiteral(")"))) { - if (ParseVariableDecl(Iter, TagList, &FunctionPtrDecl->FunctionPtr.Parameters, TypeTable)) + if (ParseVariableDecl(Iter, &FunctionPtrDecl->FunctionPtr.Parameters, Meta)) { if (TokenAtEquals(Iter, Token_Comma)) { @@ -799,17 +1073,17 @@ ParseFunctionParameterList (token_iter* Iter, type_definition* FunctionPtrDecl, } internal b32 -ParseFunctionDeclaration (token_iter* Iter, token* Identifier, gs_bucket* TagList, type_table* TypeTable) +ParseFunctionDeclaration (token_iter* Iter, token* Identifier, gs_meta_preprocessor* Meta) { b32 Result = false; PushSnapshot(Iter); - s32 ReturnTypeIndex = -1; - if (ParseType(Iter, TypeTable, &ReturnTypeIndex)) + type_table_handle ReturnTypeHandle = InvalidTypeTableHandle; + if (ParseType(Iter, Meta, &ReturnTypeHandle)) { - if (ReturnTypeIndex < 0) + if (!TypeHandleIsValid(ReturnTypeHandle)) { - ReturnTypeIndex = PushUndeclaredType(Iter->TokenAt->Text, TypeTable); + ReturnTypeHandle = PushUndeclaredType(Iter->TokenAt->Text, &Meta->TypeTable); NextToken(Iter); } @@ -820,18 +1094,18 @@ ParseFunctionDeclaration (token_iter* Iter, token* Identifier, gs_bucket* type_definition FunctionPtr = {}; FunctionPtr.Identifier = Identifier->Text; FunctionPtr.Size = sizeof(void*); - CopyMetaTagsAndClear(TagList, &FunctionPtr.MetaTags); + CopyMetaTagsAndClear(&Meta->TagList, &FunctionPtr.MetaTags); FunctionPtr.Type = TypeDef_FunctionPointer; FunctionPtr.Pointer = true; FunctionPtr.FunctionPtr = {}; - FunctionPtr.FunctionPtr.ReturnTypeIndex = ReturnTypeIndex; + FunctionPtr.FunctionPtr.ReturnTypeHandle = ReturnTypeHandle; - if (ParseFunctionParameterList(Iter, &FunctionPtr, TagList, TypeTable)) + if (ParseFunctionParameterList(Iter, &FunctionPtr, Meta)) { if (TokenAtEquals(Iter, ";")) { Result = true; - PushTypeDefOnTypeTable(FunctionPtr, TypeTable); + PushTypeDefOnTypeTable(FunctionPtr, &Meta->TypeTable); } } } @@ -846,39 +1120,42 @@ ParseFunctionDeclaration (token_iter* Iter, token* Identifier, gs_bucket* } internal b32 -ParseTypedef(token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) +ParseTypedef(token_iter* Iter, gs_meta_preprocessor* Meta) { + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseTypedef")); b32 Result = false; PushSnapshot(Iter); if (TokenAtEquals(Iter, "typedef")) { token TypeToken = {0}; - s32 TypeIndex = -1; + type_table_handle TypeHandle = InvalidTypeTableHandle; if (TokenAtEquals(Iter, "struct") && - ParseStruct(Iter, &TypeIndex, TagList, TypeTable)) + ParseStruct(Iter, &TypeHandle, Meta)) { Result = true; } - else if (ParseFunctionDeclaration(Iter, &TypeToken, TagList, TypeTable)) + else if (ParseFunctionDeclaration(Iter, &TypeToken, Meta)) { Result = true; } - else if (ParseType(Iter, TypeTable, &TypeIndex)) + else if (ParseType(Iter, Meta, &TypeHandle)) { - if (TypeIndex < 0) + if (!TypeHandleIsValid(TypeHandle)) { - TypeIndex = PushUndeclaredType(Iter->TokenAt->Text, TypeTable); + TypeHandle = PushUndeclaredType(Iter->TokenAt->Text, &Meta->TypeTable); NextToken(Iter); } b32 IsPointer = ParsePointer(Iter); - type_definition* BasisType = TypeTable->Types.GetElementAtIndex(TypeIndex); + type_definition* BasisType = GetTypeDefinition(TypeHandle, Meta->TypeTable); type_definition NewType = {}; NewType.Size = BasisType->Size; - CopyMetaTagsAndClear(TagList, &NewType.MetaTags); + CopyMetaTagsAndClear(&Meta->TagList, &NewType.MetaTags); NewType.Type = BasisType->Type; if (NewType.Type == TypeDef_Struct || NewType.Type == TypeDef_Union) @@ -891,7 +1168,7 @@ ParseTypedef(token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) if (TokenAtEquals(Iter, Token_Identifier, &IdentifierToken)) { NewType.Identifier = IdentifierToken.Text; - PushTypeDefOnTypeTable(NewType, TypeTable); + PushTypeDefOnTypeTable(NewType, &Meta->TypeTable); Result = true; } } @@ -910,12 +1187,16 @@ ParseTypedef(token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); return Result; } internal b32 -ParseEnum (token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) +ParseEnum (token_iter* Iter, gs_meta_preprocessor* Meta) { + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseEnum")); b32 Result = false; PushSnapshot(Iter); @@ -927,7 +1208,7 @@ ParseEnum (token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) type_definition EnumDecl = {}; EnumDecl.Identifier = IdentifierToken.Text; EnumDecl.Size = sizeof(u32); - CopyMetaTagsAndClear(TagList, &EnumDecl.MetaTags); + CopyMetaTagsAndClear(&Meta->TagList, &EnumDecl.MetaTags); EnumDecl.Type = TypeDef_Enum; if (TokenAtEquals(Iter, "{")) @@ -984,7 +1265,7 @@ ParseEnum (token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) if (TokenAtEquals(Iter, "}") && TokenAtEquals(Iter, ";")) { - PushTypeDefOnTypeTable(EnumDecl, TypeTable); + PushTypeDefOnTypeTable(EnumDecl, &Meta->TypeTable); Result = true; } } @@ -992,6 +1273,60 @@ ParseEnum (token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) } ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); + return Result; +} + +internal b32 +ParseFunction (token_iter* Iter, gs_meta_preprocessor* Meta) +{ + gsm_profiler_scope* ProfilerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseFunction")); + b32 Result = false; + PushSnapshot(Iter); + + type_table_handle ReturnTypeHandle = InvalidTypeTableHandle; + if (ParseType(Iter, Meta, &ReturnTypeHandle)) + { + token IdentifierToken = {}; + if (TokenAtEquals(Iter, Token_Identifier, &IdentifierToken) && + TokenAtEquals(Iter, "(")) + { + gsm_profiler_scope* ProfilerInnerScope = BeginScope(&Meta->Profiler, + MakeStringLiteral("parse"), + MakeStringLiteral("ParseFunctionInner")); + type_definition FunctionDecl = {}; + FunctionDecl.Identifier = IdentifierToken.Text; + FunctionDecl.Function.ReturnTypeHandle = ReturnTypeHandle; + CopyMetaTagsAndClear(&Meta->TagList, &FunctionDecl.MetaTags); + FunctionDecl.Type = TypeDef_Function; + FunctionDecl.Function.Parameters = {}; + + while (!StringsEqual(Iter->TokenAt->Text, MakeStringLiteral(")"))) + { + if (ParseVariableDecl(Iter, &FunctionDecl.Function.Parameters, Meta)) + { + + } + + if(!TokenAtEquals(Iter, ",")) + { + break; + } + } + + if (TokenAtEquals(Iter, ")")) + { + Result = true; + PushTypeDefOnTypeTable(FunctionDecl, &Meta->TypeTable); + } + EndScope(ProfilerInnerScope); + } + } + + ApplySnapshotIfNotParsedAndPop(Result, Iter); + EndScope(ProfilerScope); return Result; } @@ -1009,7 +1344,7 @@ internal void PrintStructDecl (type_definition* StructDecl, type_table TypeTable internal void PrintVariableDecl (variable_decl Member, type_table TypeTable, u32 Indent = 0) { - type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member.TypeIndex); + type_definition* MemberTypeDef = GetTypeDefinition(Member.TypeHandle, TypeTable); if ((MemberTypeDef->Type == TypeDef_Struct || MemberTypeDef->Type == TypeDef_Union) && MemberTypeDef->Identifier.Length == 0) { @@ -1018,7 +1353,7 @@ PrintVariableDecl (variable_decl Member, type_table TypeTable, u32 Indent = 0) else { PrintIndent(Indent); - if (Member.TypeIndex == -1) + if (!TypeHandleIsValid(Member.TypeHandle)) { printf("???? "); } @@ -1074,7 +1409,7 @@ PrintStructDecl (type_definition* StructDecl, type_table TypeTable, u32 Indent = internal void PrintFunctionPtrDecl (type_definition* FnPtrDecl, type_table TypeTable) { - type_definition* ReturnType = TypeTable.Types.GetElementAtIndex(FnPtrDecl->FunctionPtr.ReturnTypeIndex); + type_definition* ReturnType = GetTypeDefinition(FnPtrDecl->FunctionPtr.ReturnTypeHandle, TypeTable); printf("%.*s ", StringExpand(ReturnType->Identifier)); if (FnPtrDecl->Identifier.Length > 0) @@ -1098,6 +1433,8 @@ PreprocessProgram (char* SourceFile) { gs_meta_preprocessor Meta = {}; + gsm_profiler_scope* TotalScope = BeginScope(&Meta.Profiler, "total", "total"); + Meta.PreprocessorStartTime = GetWallClock(); PopulateTableWithDefaultCPPTypes(&Meta.TypeTable); @@ -1120,8 +1457,20 @@ PreprocessProgram (char* SourceFile) for (u32 SourceFileIdx = 0; SourceFileIdx < Meta.SourceFiles.Used; SourceFileIdx++) { source_code_file* File = Meta.SourceFiles.GetElementAtIndex(SourceFileIdx); - TokenizeFile(File, &Meta.Tokens); + gsm_profiler_scope* FileScope = BeginScope(&Meta.Profiler, + MakeStringLiteral("file"), + File->Path); + + gsm_profiler_scope* TokenizeScope = BeginScope(&Meta.Profiler, + MakeStringLiteral("tokenize"), + File->Path); + TokenizeFile(File, &Meta.Tokens); + EndScope(TokenizeScope); + + gsm_profiler_scope* PreprocScope = BeginScope(&Meta.Profiler, + MakeStringLiteral("preproc"), + File->Path); token_iter Iter = {}; Iter.Tokens = &Meta.Tokens; Iter.FirstToken = File->FirstTokenIndex; @@ -1134,7 +1483,7 @@ PreprocessProgram (char* SourceFile) { b32 ParseSuccess = false; - s32 TypeIndex = -1; + type_table_handle TypeHandle = InvalidTypeTableHandle; if (TokenAtEquals(&Iter, "#include")) { token* IncludeFile = Iter.TokenAt; @@ -1148,6 +1497,9 @@ PreprocessProgram (char* SourceFile) if (IncludeFile->Type != Token_Operator) { string TempFilePath = IncludeFile->Text; + gsm_profiler_scope* IncludeScope = BeginScope(&Meta.Profiler, + MakeStringLiteral("include"), + TempFilePath); // NOTE(Peter): if the path is NOT absolute ie "C:\etc if (!(IsAlpha(TempFilePath.Memory[0]) && @@ -1164,21 +1516,26 @@ PreprocessProgram (char* SourceFile) { AddFileToSource(TempFilePath, &Meta.SourceFiles, &Meta.Errors); } + EndScope(IncludeScope); } } - else if(ParseMetaTag(&Iter, &Meta.TagList)) + else if(ParseMetaTag(&Iter, &Meta)) { ParseSuccess = true; } - else if (ParseEnum(&Iter, &Meta.TagList, &Meta.TypeTable)) + else if (ParseEnum(&Iter, &Meta)) { ParseSuccess = true; } - else if (ParseStruct(&Iter, &TypeIndex, &Meta.TagList, &Meta.TypeTable)) + else if (ParseStruct(&Iter, &TypeHandle, &Meta)) { ParseSuccess = true; } - else if (ParseTypedef(&Iter, &Meta.TagList, &Meta.TypeTable)) + else if (ParseTypedef(&Iter, &Meta)) + { + ParseSuccess = true; + } + else if (ParseFunction(&Iter, &Meta)) { ParseSuccess = true; } @@ -1188,38 +1545,55 @@ PreprocessProgram (char* SourceFile) NextToken(&Iter); } } + EndScope(PreprocScope); + EndScope(FileScope); } // Type Table Fixup - for (u32 i = 0; i < Meta.TypeTable.Types.Used; i++) + gsm_profiler_scope* FixupScope = BeginScope(&Meta.Profiler, "fixup", "fixup"); + + for (u32 b = 0; b < Meta.TypeTable.TypeBucketsCount; b++) { - type_definition* TypeDef = Meta.TypeTable.Types.GetElementAtIndex(i); - if (TypeDef->Type == TypeDef_Struct) + type_table_hash_bucket Bucket = Meta.TypeTable.Types[b]; + for (u32 i = 0; i < TYPE_TABLE_BUCKET_MAX; i++) { - FixUpStructSize(i, Meta.TypeTable, &Meta.Errors); - } - else if (TypeDef->Type == TypeDef_Union) - { - FixUpUnionSize(i, Meta.TypeTable, &Meta.Errors); + if (Bucket.Keys[i] > 0) + { + type_table_handle Handle = {}; + Handle.BucketIndex = b; + Handle.IndexInBucket = i; + + type_definition* TypeDef = GetTypeDefinitionUnsafe(Handle, Meta.TypeTable); + if (TypeDef) + { + if (TypeDef->Type == TypeDef_Struct) + { + FixUpStructSize(Handle, Meta.TypeTable, &Meta.Errors); + } + else if (TypeDef->Type == TypeDef_Union) + { + FixUpUnionSize(Handle, Meta.TypeTable, &Meta.Errors); + } + } + } } } - Meta.PreprocessorEndTime = GetWallClock(); + EndScope(FixupScope); + EndScope(TotalScope); return Meta; } internal void FinishMetaprogram(gs_meta_preprocessor* Meta) { + FinishProfiler(&Meta->Profiler); + PrintAllErrors(Meta->Errors); - s64 TotalEnd = GetWallClock(); - r32 PreprocTime = GetSecondsElapsed(Meta->PreprocessorStartTime, Meta->PreprocessorEndTime); - r32 TotalTime = GetSecondsElapsed(Meta->PreprocessorStartTime, TotalEnd); - r32 UserTime = TotalTime - PreprocTime; - printf("Metaprogram Performance:\n"); - printf(" Preproc Time: %.*f sec\n", 6, PreprocTime); - printf(" Custom Time: %.*f sec\n", 6, UserTime); - printf(" Total Time: %.*f sec\n", 6, TotalTime); - + printf("\nMetaprogram Performance:\n"); + PrintAllCategories(&Meta->Profiler); } + +#define GS_META_CPP +#endif // GS_META_CPP \ No newline at end of file diff --git a/meta/gs_meta_code_generator.h b/meta/gs_meta_code_generator.h new file mode 100644 index 0000000..b8e5ed0 --- /dev/null +++ b/meta/gs_meta_code_generator.h @@ -0,0 +1,100 @@ +// +// File: gs_meta_code_generator.h +// Author: Peter Slattery +// Creation Date: 2020-01-20 +// +#ifndef GS_META_CODE_GENERATOR_H + +#include +#include + +enum gsm_code_gen_type +{ + gsm_CodeGen_Enum, + gsm_CodeGen_Count, +}; + +struct gsm_enum_generator +{ + string Identifier; + string Prefix; + b32 EndsWithCount; +}; + +struct gsm_code_generator +{ + gsm_code_gen_type Type; + string_builder* Builder; + + union + { + gsm_enum_generator Enum; + }; +}; + +// --------------- +// Enum +// --------------- + +internal gsm_code_generator +BeginEnumGeneration(string EnumIdentifier, string ValuePrefix, b32 StartsWithInvalid, b32 EndsWithCount) +{ + gsm_code_generator Gen = {}; + + // TODO(Peter): TEMP!! + Gen.Builder = (string_builder*)malloc(sizeof(string_builder)); + *Gen.Builder = {}; + + Gen.Type = gsm_CodeGen_Enum; + Gen.Enum.Identifier = EnumIdentifier; + Gen.Enum.Prefix = ValuePrefix; + Gen.Enum.EndsWithCount = EndsWithCount; + + WriteF(Gen.Builder, "enum %S\n{\n", EnumIdentifier); + if (StartsWithInvalid) + { + WriteF(Gen.Builder, " %S_Invalid,\n", ValuePrefix); + } + + return Gen; +} + +internal gsm_code_generator +BeginEnumGeneration(char* EnumIdentifier, char* ValuePrefix, b32 StartsWithInvalid, b32 EndsWithCount) +{ + return BeginEnumGeneration(MakeStringLiteral(EnumIdentifier), + MakeStringLiteral(ValuePrefix), + StartsWithInvalid, + EndsWithCount); +} + +internal void +AddEnumElement(gsm_code_generator* Gen, string ElementIdentifier) +{ + // TODO(Peter): Support const expr defining enum values + Assert(Gen->Type == gsm_CodeGen_Enum); + WriteF(Gen->Builder, " %S_%S,\n", Gen->Enum.Prefix, ElementIdentifier); +} + +internal void +AddEnumElement(gsm_code_generator* Gen, char* ElementIdentifier) +{ + AddEnumElement(Gen, MakeStringLiteral(ElementIdentifier)); +} + +internal void +FinishEnumGeneration(gsm_code_generator* Gen) +{ + Assert(Gen->Type == gsm_CodeGen_Enum); + + if (Gen->Enum.EndsWithCount) + { + WriteF(Gen->Builder, " %S_Count,\n", Gen->Enum.Prefix); + } + + WriteF(Gen->Builder, "};\n\n"); +} + + +#define GS_META_CODE_GENERATOR_H +#endif // GS_META_CODE_GENERATOR_H \ No newline at end of file diff --git a/meta/gs_meta_lexer.h b/meta/gs_meta_lexer.h index 0923360..557f245 100644 --- a/meta/gs_meta_lexer.h +++ b/meta/gs_meta_lexer.h @@ -121,8 +121,7 @@ GetNextToken (tokenizer* Tokenizer) Tokenizer->At += 2; break; } - EatToNewLine(Tokenizer); - EatWhitespace(Tokenizer); + Tokenizer->At++; } EatWhitespace(Tokenizer); } diff --git a/meta/gs_meta_typeinfo_generator.h b/meta/gs_meta_typeinfo_generator.h index dc4cca5..49015df 100644 --- a/meta/gs_meta_typeinfo_generator.h +++ b/meta/gs_meta_typeinfo_generator.h @@ -3,15 +3,21 @@ // Author: Peter Slattery // Creation Date: 2020-01-19 // +// Usage +// TODO +// +// #ifndef GS_META_TYPEINFO_GENERATOR_H #include #include #include +#include "gs_meta_code_generator.h" struct typeinfo_generator { - string_builder TypeList; + string_builder TypeListString; + gsm_code_generator TypeList; string_builder StructMembers; string_builder TypeDefinitions; @@ -20,16 +26,17 @@ struct typeinfo_generator b8* TypesGeneratedMask; }; +#define TypeHandleToIndex(handle) ((handle.BucketIndex * TYPE_TABLE_BUCKET_MAX) + handle.IndexInBucket) internal typeinfo_generator InitTypeInfoGenerator(type_table TypeTable) { typeinfo_generator Result = {}; - Result.TypesMax = TypeTable.Types.Used; + Result.TypesMax = TypeTable.TypeBucketsCount * TYPE_TABLE_BUCKET_MAX; Result.TypesGeneratedMask = (b8*)malloc(sizeof(b8) * Result.TypesMax); GSZeroMemory((u8*)Result.TypesGeneratedMask, Result.TypesMax); - WriteF(&Result.TypeList, "enum gsm_struct_type\n{\n"); + Result.TypeList = BeginEnumGeneration("gsm_struct_type", "gsm_StructType", false, true); WriteF(&Result.TypeDefinitions, "static gsm_struct_type_info StructTypes[] = {\n"); return Result; @@ -38,12 +45,12 @@ InitTypeInfoGenerator(type_table TypeTable) internal void FinishGeneratingTypes(typeinfo_generator* Generator) { - WriteF(&Generator->TypeList, "gsm_StructTypeCount,\n};\n\n"); + FinishEnumGeneration(&Generator->TypeList); WriteF(&Generator->StructMembers, "\n"); WriteF(&Generator->TypeDefinitions, "};\n"); - WriteF(&Generator->TypeDefinitions, "gsm_u32 StructTypesCount = %d;\n", Generator->GeneratedInfoTypesCount); + WriteF(&Generator->TypeDefinitions, "static gsm_u32 StructTypesCount = %d;\n", Generator->GeneratedInfoTypesCount); } internal void @@ -71,9 +78,12 @@ GenerateStructMemberInfo (variable_decl* Member, string StructIdentifier, type_t } internal void -GenerateTypeInfo (type_definition* Type, u32 TypeIndex, type_table TypeTable, typeinfo_generator* Generator) +GenerateTypeInfo (type_definition* Type, type_table_handle TypeHandle, type_table TypeTable, typeinfo_generator* Generator) { - Generator->TypesGeneratedMask[TypeIndex] = true; + // TODO(Peter): + // 1. allocate the full range of the types hash table + // 2. use bucketindex * bucket_max + indexinbucket to get the consecutive index + Generator->TypesGeneratedMask[TypeHandleToIndex(TypeHandle)] = true; Generator->GeneratedInfoTypesCount++; { @@ -81,8 +91,7 @@ GenerateTypeInfo (type_definition* Type, u32 TypeIndex, type_table TypeTable, ty // type info for any member types. If it doesn't, it will screw // up array ordering - // Lookup Enum - WriteF(&Generator->TypeList, "gsm_StructType_%S,\n", Type->Identifier); + AddEnumElement(&Generator->TypeList, Type->Identifier); // Type Info WriteF(&Generator->TypeDefinitions, "{ gsm_StructType_%S, \"%S\", %d, %d, 0, 0, ", @@ -110,12 +119,18 @@ GenerateTypeInfo (type_definition* Type, u32 TypeIndex, type_table TypeTable, ty for (u32 m = 0; m < Type->Struct.MemberDecls.Used; m++) { variable_decl* Member = Type->Struct.MemberDecls.GetElementAtIndex(m); - type_definition* MemberType = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); + type_definition* MemberType = GetTypeDefinition(Member->TypeHandle, TypeTable); - if (MemberType->Identifier.Length == 0) { continue; } // Don't gen info for anonymous struct and union members - if (Generator->TypesGeneratedMask[Member->TypeIndex]) { continue; } + if ((MemberType->Type == TypeDef_Struct || + MemberType->Type == TypeDef_Union) && + MemberType->Struct.IsAnonymous) + { + continue; // Don't gen info for anonymous struct and union members + } - GenerateTypeInfo(MemberType, Member->TypeIndex, TypeTable, Generator); + if (Generator->TypesGeneratedMask[TypeHandleToIndex(Member->TypeHandle)]) { continue; } + + GenerateTypeInfo(MemberType, Member->TypeHandle, TypeTable, Generator); } // @@ -123,14 +138,14 @@ GenerateTypeInfo (type_definition* Type, u32 TypeIndex, type_table TypeTable, ty for (u32 m = 0; m < Type->Struct.MemberDecls.Used; m++) { variable_decl* Member = Type->Struct.MemberDecls.GetElementAtIndex(m); - type_definition* MemberType = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); + type_definition* MemberType = GetTypeDefinition(Member->TypeHandle, TypeTable); - if (MemberType->Identifier.Length > 0) + if ((MemberType->Type != TypeDef_Struct && MemberType->Type != TypeDef_Union) || + !MemberType->Struct.IsAnonymous) { GenerateStructMemberInfo(Member, Type->Identifier, TypeTable, Generator); } - else if (MemberType->Type == TypeDef_Struct || - MemberType->Type == TypeDef_Union) + else if (MemberType->Struct.IsAnonymous) { // Anonymous Members for (u32 a = 0; a < MemberType->Struct.MemberDecls.Used; a++) @@ -147,17 +162,29 @@ GenerateTypeInfo (type_definition* Type, u32 TypeIndex, type_table TypeTable, ty internal void GenerateFilteredTypeInfo (string MetaTagFilter, type_table TypeTable, typeinfo_generator* Generator) { - for (u32 i = 0; i < TypeTable.Types.Used; i++) + for (u32 b = 0; b < TypeTable.TypeBucketsCount; b++) { - if (Generator->TypesGeneratedMask[i]) - { - continue; - } + type_table_hash_bucket Bucket = TypeTable.Types[b]; - type_definition* Type = TypeTable.Types.GetElementAtIndex(i); - if (HasTag(MetaTagFilter, Type->MetaTags)) + for (u32 i = 0; i < TYPE_TABLE_BUCKET_MAX; i++) { - GenerateTypeInfo(Type, i, TypeTable, Generator); + type_table_handle TypeHandle = {}; + TypeHandle.BucketIndex = b; + TypeHandle.IndexInBucket = i; + + if (Generator->TypesGeneratedMask[TypeHandleToIndex(TypeHandle)]) + { + continue; + } + + type_definition* Type = GetTypeDefinitionUnsafe(TypeHandle, TypeTable); + if (Type) + { + if (HasTag(MetaTagFilter, Type->MetaTags)) + { + GenerateTypeInfo(Type, TypeHandle, TypeTable, Generator); + } + } } } } diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index bd9cdf6..31cb0ab 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -26,7 +26,7 @@ node_specification* NodeSpecifications = 0; #include "assembly_parser.cpp" -//#include "test_patterns.h" +#include "test_patterns.h" // TODO(Peter): something we can do later is to remove all reliance on app_state and context // from foldhaus_pane.h. It should just emit lists of things that the app can iterate over and diff --git a/src/generated/foldhaus_nodes_generated.h b/src/generated/foldhaus_nodes_generated.h index fb892e7..6d6566b 100644 --- a/src/generated/foldhaus_nodes_generated.h +++ b/src/generated/foldhaus_nodes_generated.h @@ -1,22 +1,5 @@ -#define GENERATED_NODE_TYPES \ -NodeType_MultiplyNodeProc, \ -NodeType_AddNodeProc, \ -NodeType_FloatValueProc, \ -NodeType_SolidColorProc, \ -NodeType_VerticalColorFadeProc - -#define GENERATED_NODE_SPECS \ -{ NodeType_MultiplyNodeProc, "MultiplyNodeProc", 16, MemberList_multiply_data, 12, 3, 2, 1, false}, \ -{ NodeType_AddNodeProc, "AddNodeProc", 11, MemberList_add_data, 48, 3, 2, 1, false}, \ -{ NodeType_FloatValueProc, "FloatValueProc", 14, MemberList_float_value_data, 8, 2, 1, 1, false}, \ -{ NodeType_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 16, 1, 1, 0, true}, \ -{ NodeType_VerticalColorFadeProc, "VerticalColorFadeProc", 21, MemberList_vertical_color_fade_data, 24, 3, 3, 0, true} -#define GENERATED_NODE_SPECS_COUNT 5 - -#define EVALUATE_GENERATED_NODES \ -case NodeType_MultiplyNodeProc: { MultiplyNodeProc((multiply_data*)NodeData); } break; \ -case NodeType_AddNodeProc: { AddNodeProc((add_data*)NodeData); } break; \ -case NodeType_FloatValueProc: { FloatValueProc((float_value_data*)NodeData); } break; \ -case NodeType_SolidColorProc: { SolidColorProc((solid_color_data*)NodeData, LEDs, Colors, LEDCount); } break; \ -case NodeType_VerticalColorFadeProc: { VerticalColorFadeProc((vertical_color_fade_data*)NodeData, LEDs, Colors, LEDCount); } break; \ +enum node_type +{ + NodeType_Count, +}; diff --git a/src/generated/gs_meta_generated_typeinfo.h b/src/generated/gs_meta_generated_typeinfo.h index 8fbbe1b..7fcc15b 100644 --- a/src/generated/gs_meta_generated_typeinfo.h +++ b/src/generated/gs_meta_generated_typeinfo.h @@ -1,16 +1,16 @@ enum gsm_struct_type { -gsm_StructType_sin_wave_data, -gsm_StructType_r32, -gsm_StructType_multiply_patterns_data, -gsm_StructType_color_buffer, -gsm_StructType_led, -gsm_StructType_s32, -gsm_StructType_v4, -gsm_StructType_float, -gsm_StructType_pixel, -gsm_StructType_u8, -gsm_StructTypeCount, + gsm_StructType_sin_wave_data, + gsm_StructType_r32, + gsm_StructType_multiply_patterns_data, + gsm_StructType_color_buffer, + gsm_StructType_led, + gsm_StructType_s32, + gsm_StructType_v4, + gsm_StructType_float, + gsm_StructType_pixel, + gsm_StructType_u8, + gsm_StructType_Count, }; static gsm_struct_member_type_info StructMembers_sin_wave_data[] = { @@ -64,4 +64,4 @@ static gsm_struct_type_info StructTypes[] = { { gsm_StructType_pixel, "pixel", 5, 3, 0, 0, StructMembers_pixel, 2 }, { gsm_StructType_u8, "u8", 2, 1, 0, 0, 0, 0 }, }; -gsm_u32 StructTypesCount = 10; +static gsm_u32 StructTypesCount = 10; diff --git a/src/test_patterns.h b/src/test_patterns.h index bd6f409..d385ece 100644 --- a/src/test_patterns.h +++ b/src/test_patterns.h @@ -5,7 +5,6 @@ // #ifndef TEST_PATTERNS_H - GSMetaTag(node_struct) struct solid_color_data { @@ -17,20 +16,20 @@ struct solid_color_data }; GSMetaTag(node_proc); // :TagParamsForNodeParamStructs -void SolidColorProc, solid_color_data* Data) +void SolidColorProc(solid_color_data* Data) { u8 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f); u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f); u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f); - led* LED = Data->ResultLEDs; - for (s32 l = 0; l < Data->ResultLEDCount; l++) + led* LED = Data->Result.LEDs; + for (s32 l = 0; l < Data->Result.LEDCount; l++) { - Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount); + Assert(LED->Index >= 0 && LED->Index < Data->Result.LEDCount); - Data->ResultColors[LED->Index].R = R; - Data->ResultColors[LED->Index].G = G; - Data->ResultColors[LED->Index].B = B; + Data->Result.Colors[LED->Index].R = R; + Data->Result.Colors[LED->Index].G = G; + Data->Result.Colors[LED->Index].B = B; LED++; } } @@ -52,7 +51,7 @@ struct vertical_color_fade_data }; GSMetaTag(node_proc); // :TagParamsForNodeParamStructs -void VerticalColorFadeProc, vertical_color_fade_data* Data) +void VerticalColorFadeProc(vertical_color_fade_data* Data) { r32 R = (Data->Color.r * 255); r32 G = (Data->Color.g * 255); @@ -60,17 +59,17 @@ void VerticalColorFadeProc, vertical_color_fade_data* Data) r32 Range = Data->Max - Data->Min; - led* LED = Data->ResultLEDs; - for (s32 l = 0; l < Data->ResultLEDCount; l++) + led* LED = Data->Result.LEDs; + for (s32 l = 0; l < Data->Result.LEDCount; l++) { - Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount); + Assert(LED->Index >= 0 && LED->Index < Data->Result.LEDCount); r32 Amount = (LED->Position.y - Data->Min) / Range; Amount = GSClamp01(1.0f - Amount); - Data->ResultColors[LED->Index].R = (u8)(R * Amount); - Data->ResultColors[LED->Index].G = (u8)(G * Amount); - Data->ResultColors[LED->Index].B = (u8)(B * Amount); + Data->Result.Colors[LED->Index].R = (u8)(R * Amount); + Data->Result.Colors[LED->Index].G = (u8)(G * Amount); + Data->Result.Colors[LED->Index].B = (u8)(B * Amount); LED++; } } @@ -105,7 +104,7 @@ struct revolving_discs_data }; GSMetaTag(node_proc); // :TagParamsForNodeParamStructs -void RevolvingDiscs, revolving_discs_data* Data) +void RevolvingDiscs(revolving_discs_data* Data) { DEBUG_TRACK_FUNCTION; @@ -125,8 +124,8 @@ void RevolvingDiscs, revolving_discs_data* Data) r32 OuterRadiusSquared = Data->OuterRadius * Data->OuterRadius; r32 InnerRadiusSquared = Data->InnerRadius * Data->InnerRadius; - led* LED = Data->ResultLEDs; - for (s32 l = 0; l < Data->ResultLEDCount; l++) + led* LED = Data->Result.LEDs; + for (s32 l = 0; l < Data->Result.LEDCount; l++) { v4 Position = LED->Position; @@ -144,7 +143,7 @@ void RevolvingDiscs, revolving_discs_data* Data) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) { - Data->ResultColors[LED->Index] = Color; + Data->Result.Colors[LED->Index] = Color; } } LED++; diff --git a/src/win32_foldhaus.cpp b/src/win32_foldhaus.cpp index a8c45d8..d6a0096 100644 --- a/src/win32_foldhaus.cpp +++ b/src/win32_foldhaus.cpp @@ -11,6 +11,7 @@ #include #include +#include "../meta/foldhaus_meta_include.h" #include "foldhaus_platform.h" #include "gs_win32.cpp"