Compressing Type Info Generation

This commit is contained in:
Peter Slattery 2020-01-20 21:11:07 -08:00
parent d1353e52fa
commit af11a85e94
11 changed files with 927 additions and 282 deletions

View File

@ -1,15 +1,9 @@
// //
// Usage // File: foldhaus_meta.cpp
// Author: Peter Slattery
// Creation Date: 2020-01-19
// //
// GSMetaTag(<tag name>) to give commands to the meta layer #ifndef FOLDHAUS_META_CPP
//
// 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
#include "gs_meta.cpp" #include "gs_meta.cpp"
#include "gs_meta_typeinfo_generator.h" #include "gs_meta_typeinfo_generator.h"
@ -23,25 +17,64 @@ int main(int ArgCount, char* Args[])
} }
gs_meta_preprocessor Meta = PreprocessProgram(Args[1]); gs_meta_preprocessor Meta = PreprocessProgram(Args[1]);
s64 Cycles_Preprocess = GetWallClock();
typeinfo_generator TypeGenerator = InitTypeInfoGenerator(Meta.TypeTable); typeinfo_generator TypeGenerator = InitTypeInfoGenerator(Meta.TypeTable);
GenerateFilteredTypeInfo(MakeStringLiteral("node_struct"), Meta.TypeTable, &TypeGenerator); GenerateFilteredTypeInfo(MakeStringLiteral("node_struct"), Meta.TypeTable, &TypeGenerator);
GenerateFilteredTypeInfo(MakeStringLiteral("gen_type_info"), Meta.TypeTable, &TypeGenerator); GenerateFilteredTypeInfo(MakeStringLiteral("gen_type_info"), Meta.TypeTable, &TypeGenerator);
FinishGeneratingTypes(&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"); FILE* TypeInfoH = fopen("C:\\projects\\foldhaus\\src\\generated\\gs_meta_generated_typeinfo.h", "w");
if (TypeInfoH) if (TypeInfoH)
{ {
WriteStringBuilderToFile(TypeGenerator.TypeList, TypeInfoH); WriteStringBuilderToFile(*TypeGenerator.TypeList.Builder, TypeInfoH);
WriteStringBuilderToFile(TypeGenerator.StructMembers, TypeInfoH); WriteStringBuilderToFile(TypeGenerator.StructMembers, TypeInfoH);
WriteStringBuilderToFile(TypeGenerator.TypeDefinitions, TypeInfoH); WriteStringBuilderToFile(TypeGenerator.TypeDefinitions, TypeInfoH);
fclose(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); FinishMetaprogram(&Meta);
//__debugbreak(); //__debugbreak();
return 0; return 0;
} }
#define FOLDHAUS_META_CPP
#endif // FOLDHAUS_META_CPP

View File

@ -16,10 +16,17 @@ enum type_definition_type
TypeDef_Union, TypeDef_Union,
TypeDef_BasicType, TypeDef_BasicType,
TypeDef_FunctionPointer, TypeDef_FunctionPointer,
TypeDef_Function,
TypeDef_Count, TypeDef_Count,
}; };
struct type_table_handle
{
s32 BucketIndex;
u32 IndexInBucket;
};
struct meta_tag struct meta_tag
{ {
string Identifier; 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 // 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 // up on the first pass through. A TypeIndex of -1 means we need to fixup that
// type at a later time // type at a later time
s32 TypeIndex; type_table_handle TypeHandle;
string Identifier; string Identifier;
b32 Pointer; b32 Pointer;
@ -45,6 +52,7 @@ struct variable_decl
struct struct_decl struct struct_decl
{ {
b32 IsAnonymous;
// TODO(Peter): Lots of tiny arrays everywhere! Pull these into a central allocation // TODO(Peter): Lots of tiny arrays everywhere! Pull these into a central allocation
// buffer somewhere // buffer somewhere
// :SmallAllocationsAllOver // :SmallAllocationsAllOver
@ -53,11 +61,18 @@ struct struct_decl
struct function_pointer_decl struct function_pointer_decl
{ {
s32 ReturnTypeIndex; type_table_handle ReturnTypeHandle;
// :SmallAllocationsAllOver // :SmallAllocationsAllOver
gs_bucket<variable_decl> Parameters; gs_bucket<variable_decl> Parameters;
}; };
struct function_decl
{
type_table_handle ReturnTypeHandle;
gs_bucket<variable_decl> Parameters;
// TODO(Peter): AST?
};
struct enum_decl struct enum_decl
{ {
gs_bucket<string> Identifiers; gs_bucket<string> Identifiers;
@ -80,13 +95,22 @@ struct type_definition
enum_decl Enum; enum_decl Enum;
struct_decl Struct; struct_decl Struct;
function_pointer_decl FunctionPtr; function_pointer_decl FunctionPtr;
function_decl Function;
}; };
b32 Pointer; b32 Pointer;
}; };
#define TYPE_TABLE_BUCKET_MAX 1024
struct type_table_hash_bucket
{
u32* Keys;
type_definition* Values;
};
struct type_table struct type_table
{ {
gs_bucket<type_definition> Types; type_table_hash_bucket* Types;
u32 TypeBucketsCount;
}; };
internal b32 internal b32
@ -119,63 +143,190 @@ CopyMetaTagsAndClear(gs_bucket<token>* Source, gs_bucket<meta_tag>* Dest)
Source->Used = 0; 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) PushUndeclaredType (string Identifier, type_table* TypeTable)
{ {
type_definition UndeclaredTypeDef = {}; type_definition UndeclaredTypeDef = {};
UndeclaredTypeDef.Identifier = Identifier; UndeclaredTypeDef.Identifier = Identifier;
UndeclaredTypeDef.Type = TypeDef_Unknown; UndeclaredTypeDef.Type = TypeDef_Unknown;
s32 TypeIndex = (s32)TypeTable->Types.PushElementOnBucket(UndeclaredTypeDef); type_table_handle Result = PushTypeOnHashTable(UndeclaredTypeDef, TypeTable);
return TypeIndex; return Result;
} }
internal s32 internal type_table_handle
GetIndexOfType (string Identifier, type_table TypeTable) GetTypeHandle (string Identifier, type_table TypeTable)
{ {
s32 Result = -1; type_table_handle Result = InvalidTypeTableHandle;
for (u32 i = 0; i < TypeTable.Types.Used; i++)
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); type_table_hash_bucket Bucket = TypeTable.Types[b];
if (StringsEqual(Identifier, TypeDef->Identifier)) 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; break;
} }
} }
return Result; return Result;
} }
internal s32 internal type_table_handle
PushTypeDefOnTypeTable(type_definition TypeDef, type_table* TypeTable) 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 if (!TypeHandleIsValid(ExistingUndeclaredTypeHandle))
// first anonymous struct/union member. So every anon struct/union gets its own
// typeef
if (ExistingUndeclaredTypeIndex < 0 || TypeDef.Identifier.Length == 0)
{ {
Index = TypeTable->Types.PushElementOnBucket(TypeDef); Result = PushTypeOnHashTable(TypeDef, TypeTable);
} }
else else
{ {
Index = ExistingUndeclaredTypeIndex; Result = ExistingUndeclaredTypeHandle;
type_definition* ExistingTypeDef = TypeTable->Types.GetElementAtIndex(ExistingUndeclaredTypeIndex); type_definition* ExistingTypeDef = GetTypeDefinition(Result, *TypeTable);
Assert(ExistingTypeDef != 0);
*ExistingTypeDef = TypeDef; *ExistingTypeDef = TypeDef;
} }
return Index; return Result;
} }
internal s32 internal s32
GetSizeOfType (s32 TypeIndex, type_table TypeTable) GetSizeOfType (type_table_handle TypeHandle, type_table TypeTable)
{ {
s32 Result = -1; s32 Result = -1;
Assert(TypeIndex >= 0 && (u32)TypeIndex < TypeTable.Types.Used); type_definition* TypeDef = GetTypeDefinition(TypeHandle, TypeTable);
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(TypeIndex); if (TypeDef)
Result = TypeDef->Size; {
Result = TypeDef->Size;
}
return Result; return Result;
} }
@ -183,14 +334,10 @@ internal s32
GetSizeOfType (string Identifier, type_table TypeTable) GetSizeOfType (string Identifier, type_table TypeTable)
{ {
s32 Result = -1; 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); Result = TypeDef->Size;
if (StringsEqual(Identifier, TypeDef->Identifier))
{
Result = TypeDef->Size;
break;
}
} }
return Result; return Result;
} }
@ -199,7 +346,7 @@ internal b32
VariableDeclsEqual (variable_decl A, variable_decl B) VariableDeclsEqual (variable_decl A, variable_decl B)
{ {
b32 Result = false; b32 Result = false;
if (A.TypeIndex == B.TypeIndex && if (TypeHandlesEqual(A.TypeHandle, B.TypeHandle) &&
A.ArrayCount == B.ArrayCount && A.ArrayCount == B.ArrayCount &&
StringsEqual(A.Identifier, B.Identifier)) StringsEqual(A.Identifier, B.Identifier))
{ {
@ -236,51 +383,35 @@ StructOrUnionsEqual (type_definition A, type_definition B)
return Result; return Result;
} }
internal s32 internal type_table_handle
FindIndexOfMatchingType (type_definition Match, type_table TypeTable) FindHandleOfMatchingType (type_definition Match, type_table TypeTable)
{ {
s32 Result = -1; type_table_handle Result = InvalidTypeTableHandle;
for (u32 i = 0; i < TypeTable.Types.Used; i++) type_table_handle Handle = GetTypeHandle(Match.Identifier, TypeTable);
if (TypeHandleIsValid(Handle))
{ {
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); Result = Handle;
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;
}
}
} }
return Result; return Result;
} }
internal void FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors); internal void FixUpStructSize (type_table_handle TypeHandle, type_table TypeTable, errors* Errors);
internal void FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors); internal void FixUpUnionSize (type_table_handle TypeHandle, type_table TypeTable, errors* Errors);
internal void internal void
FixupMemberType (variable_decl* Member, type_table TypeTable) 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 internal s32
CalculateStructMemberSize (variable_decl Member, type_definition MemberType) 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 // 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. // 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) if (MemberTypeDef->Type == TypeDef_Struct)
{ {
FixUpStructSize(Member->TypeIndex, TypeTable, Errors); FixUpStructSize(Member->TypeHandle, TypeTable, Errors);
} }
else if (MemberTypeDef->Type == TypeDef_Union) else if (MemberTypeDef->Type == TypeDef_Union)
{ {
FixUpUnionSize(Member->TypeIndex, TypeTable, Errors); FixUpUnionSize(Member->TypeHandle, TypeTable, Errors);
} }
else else
{ {
@ -353,9 +484,9 @@ FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_t
} }
internal void 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); Assert(Struct->Type == TypeDef_Struct);
if (HasTag(MakeStringLiteral("breakpoint"), Struct->MetaTags)) 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); variable_decl* Member = Struct->Struct.MemberDecls.GetElementAtIndex(j);
FixupMemberType(Member, TypeTable); 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); FixupStructMember(Member, MemberTypeDef, TypeTable, Errors);
u32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef); u32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef);
SizeAcc += MemberSize; SizeAcc += MemberSize;
} }
@ -400,9 +529,9 @@ FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors)
} }
internal void 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); Assert(Union->Type == TypeDef_Union);
s32 BiggestMemberSize = 0; s32 BiggestMemberSize = 0;
@ -411,9 +540,9 @@ FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors)
variable_decl* Member = Union->Struct.MemberDecls.GetElementAtIndex(j); variable_decl* Member = Union->Struct.MemberDecls.GetElementAtIndex(j);
FixupMemberType(Member, TypeTable); 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); FixupStructMember(Member, MemberTypeDef, TypeTable, Errors);
s32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef); s32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef);
BiggestMemberSize = GSMax(BiggestMemberSize, MemberSize); BiggestMemberSize = GSMax(BiggestMemberSize, MemberSize);

File diff suppressed because it is too large Load Diff

View File

@ -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 <gs_string.h>
#include <gs_string_builder.h>
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

View File

@ -121,8 +121,7 @@ GetNextToken (tokenizer* Tokenizer)
Tokenizer->At += 2; Tokenizer->At += 2;
break; break;
} }
EatToNewLine(Tokenizer); Tokenizer->At++;
EatWhitespace(Tokenizer);
} }
EatWhitespace(Tokenizer); EatWhitespace(Tokenizer);
} }

View File

@ -3,15 +3,21 @@
// Author: Peter Slattery // Author: Peter Slattery
// Creation Date: 2020-01-19 // Creation Date: 2020-01-19
// //
// Usage
// TODO
//
//
#ifndef GS_META_TYPEINFO_GENERATOR_H #ifndef GS_META_TYPEINFO_GENERATOR_H
#include <gs_language.h> #include <gs_language.h>
#include <gs_string.h> #include <gs_string.h>
#include <gs_string_builder.h> #include <gs_string_builder.h>
#include "gs_meta_code_generator.h"
struct typeinfo_generator struct typeinfo_generator
{ {
string_builder TypeList; string_builder TypeListString;
gsm_code_generator TypeList;
string_builder StructMembers; string_builder StructMembers;
string_builder TypeDefinitions; string_builder TypeDefinitions;
@ -20,16 +26,17 @@ struct typeinfo_generator
b8* TypesGeneratedMask; b8* TypesGeneratedMask;
}; };
#define TypeHandleToIndex(handle) ((handle.BucketIndex * TYPE_TABLE_BUCKET_MAX) + handle.IndexInBucket)
internal typeinfo_generator internal typeinfo_generator
InitTypeInfoGenerator(type_table TypeTable) InitTypeInfoGenerator(type_table TypeTable)
{ {
typeinfo_generator Result = {}; typeinfo_generator Result = {};
Result.TypesMax = TypeTable.Types.Used; Result.TypesMax = TypeTable.TypeBucketsCount * TYPE_TABLE_BUCKET_MAX;
Result.TypesGeneratedMask = (b8*)malloc(sizeof(b8) * Result.TypesMax); Result.TypesGeneratedMask = (b8*)malloc(sizeof(b8) * Result.TypesMax);
GSZeroMemory((u8*)Result.TypesGeneratedMask, 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"); WriteF(&Result.TypeDefinitions, "static gsm_struct_type_info StructTypes[] = {\n");
return Result; return Result;
@ -38,12 +45,12 @@ InitTypeInfoGenerator(type_table TypeTable)
internal void internal void
FinishGeneratingTypes(typeinfo_generator* Generator) FinishGeneratingTypes(typeinfo_generator* Generator)
{ {
WriteF(&Generator->TypeList, "gsm_StructTypeCount,\n};\n\n"); FinishEnumGeneration(&Generator->TypeList);
WriteF(&Generator->StructMembers, "\n"); WriteF(&Generator->StructMembers, "\n");
WriteF(&Generator->TypeDefinitions, "};\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 internal void
@ -71,9 +78,12 @@ GenerateStructMemberInfo (variable_decl* Member, string StructIdentifier, type_t
} }
internal void 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++; 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 // type info for any member types. If it doesn't, it will screw
// up array ordering // up array ordering
// Lookup Enum AddEnumElement(&Generator->TypeList, Type->Identifier);
WriteF(&Generator->TypeList, "gsm_StructType_%S,\n", Type->Identifier);
// Type Info // Type Info
WriteF(&Generator->TypeDefinitions, "{ gsm_StructType_%S, \"%S\", %d, %d, 0, 0, ", 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++) for (u32 m = 0; m < Type->Struct.MemberDecls.Used; m++)
{ {
variable_decl* Member = Type->Struct.MemberDecls.GetElementAtIndex(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 ((MemberType->Type == TypeDef_Struct ||
if (Generator->TypesGeneratedMask[Member->TypeIndex]) { continue; } 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++) for (u32 m = 0; m < Type->Struct.MemberDecls.Used; m++)
{ {
variable_decl* Member = Type->Struct.MemberDecls.GetElementAtIndex(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); GenerateStructMemberInfo(Member, Type->Identifier, TypeTable, Generator);
} }
else if (MemberType->Type == TypeDef_Struct || else if (MemberType->Struct.IsAnonymous)
MemberType->Type == TypeDef_Union)
{ {
// Anonymous Members // Anonymous Members
for (u32 a = 0; a < MemberType->Struct.MemberDecls.Used; a++) 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 internal void
GenerateFilteredTypeInfo (string MetaTagFilter, type_table TypeTable, typeinfo_generator* Generator) 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]) type_table_hash_bucket Bucket = TypeTable.Types[b];
{
continue;
}
type_definition* Type = TypeTable.Types.GetElementAtIndex(i); for (u32 i = 0; i < TYPE_TABLE_BUCKET_MAX; i++)
if (HasTag(MetaTagFilter, Type->MetaTags))
{ {
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);
}
}
} }
} }
} }

View File

@ -26,7 +26,7 @@ node_specification* NodeSpecifications = 0;
#include "assembly_parser.cpp" #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 // 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 // from foldhaus_pane.h. It should just emit lists of things that the app can iterate over and

View File

@ -1,22 +1,5 @@
#define GENERATED_NODE_TYPES \ enum node_type
NodeType_MultiplyNodeProc, \ {
NodeType_AddNodeProc, \ NodeType_Count,
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; \

View File

@ -1,16 +1,16 @@
enum gsm_struct_type enum gsm_struct_type
{ {
gsm_StructType_sin_wave_data, gsm_StructType_sin_wave_data,
gsm_StructType_r32, gsm_StructType_r32,
gsm_StructType_multiply_patterns_data, gsm_StructType_multiply_patterns_data,
gsm_StructType_color_buffer, gsm_StructType_color_buffer,
gsm_StructType_led, gsm_StructType_led,
gsm_StructType_s32, gsm_StructType_s32,
gsm_StructType_v4, gsm_StructType_v4,
gsm_StructType_float, gsm_StructType_float,
gsm_StructType_pixel, gsm_StructType_pixel,
gsm_StructType_u8, gsm_StructType_u8,
gsm_StructTypeCount, gsm_StructType_Count,
}; };
static gsm_struct_member_type_info StructMembers_sin_wave_data[] = { 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_pixel, "pixel", 5, 3, 0, 0, StructMembers_pixel, 2 },
{ gsm_StructType_u8, "u8", 2, 1, 0, 0, 0, 0 }, { gsm_StructType_u8, "u8", 2, 1, 0, 0, 0, 0 },
}; };
gsm_u32 StructTypesCount = 10; static gsm_u32 StructTypesCount = 10;

View File

@ -5,7 +5,6 @@
// //
#ifndef TEST_PATTERNS_H #ifndef TEST_PATTERNS_H
GSMetaTag(node_struct) GSMetaTag(node_struct)
struct solid_color_data struct solid_color_data
{ {
@ -17,20 +16,20 @@ struct solid_color_data
}; };
GSMetaTag(node_proc); // :TagParamsForNodeParamStructs 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 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f);
u8 G = (u8)GSClamp(0.f, (Data->Color.g * 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); u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f);
led* LED = Data->ResultLEDs; led* LED = Data->Result.LEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++) 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->Result.Colors[LED->Index].R = R;
Data->ResultColors[LED->Index].G = G; Data->Result.Colors[LED->Index].G = G;
Data->ResultColors[LED->Index].B = B; Data->Result.Colors[LED->Index].B = B;
LED++; LED++;
} }
} }
@ -52,7 +51,7 @@ struct vertical_color_fade_data
}; };
GSMetaTag(node_proc); // :TagParamsForNodeParamStructs 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 R = (Data->Color.r * 255);
r32 G = (Data->Color.g * 255); r32 G = (Data->Color.g * 255);
@ -60,17 +59,17 @@ void VerticalColorFadeProc, vertical_color_fade_data* Data)
r32 Range = Data->Max - Data->Min; r32 Range = Data->Max - Data->Min;
led* LED = Data->ResultLEDs; led* LED = Data->Result.LEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++) 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; r32 Amount = (LED->Position.y - Data->Min) / Range;
Amount = GSClamp01(1.0f - Amount); Amount = GSClamp01(1.0f - Amount);
Data->ResultColors[LED->Index].R = (u8)(R * Amount); Data->Result.Colors[LED->Index].R = (u8)(R * Amount);
Data->ResultColors[LED->Index].G = (u8)(G * Amount); Data->Result.Colors[LED->Index].G = (u8)(G * Amount);
Data->ResultColors[LED->Index].B = (u8)(B * Amount); Data->Result.Colors[LED->Index].B = (u8)(B * Amount);
LED++; LED++;
} }
} }
@ -105,7 +104,7 @@ struct revolving_discs_data
}; };
GSMetaTag(node_proc); // :TagParamsForNodeParamStructs GSMetaTag(node_proc); // :TagParamsForNodeParamStructs
void RevolvingDiscs, revolving_discs_data* Data) void RevolvingDiscs(revolving_discs_data* Data)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
@ -125,8 +124,8 @@ void RevolvingDiscs, revolving_discs_data* Data)
r32 OuterRadiusSquared = Data->OuterRadius * Data->OuterRadius; r32 OuterRadiusSquared = Data->OuterRadius * Data->OuterRadius;
r32 InnerRadiusSquared = Data->InnerRadius * Data->InnerRadius; r32 InnerRadiusSquared = Data->InnerRadius * Data->InnerRadius;
led* LED = Data->ResultLEDs; led* LED = Data->Result.LEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++) for (s32 l = 0; l < Data->Result.LEDCount; l++)
{ {
v4 Position = LED->Position; v4 Position = LED->Position;
@ -144,7 +143,7 @@ void RevolvingDiscs, revolving_discs_data* Data)
{ {
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
{ {
Data->ResultColors[LED->Index] = Color; Data->Result.Colors[LED->Index] = Color;
} }
} }
LED++; LED++;

View File

@ -11,6 +11,7 @@
#include <windowsx.h> #include <windowsx.h>
#include <gl/gl.h> #include <gl/gl.h>
#include "../meta/foldhaus_meta_include.h"
#include "foldhaus_platform.h" #include "foldhaus_platform.h"
#include "gs_win32.cpp" #include "gs_win32.cpp"