diff --git a/meta/foldhaus_meta.cpp b/meta/foldhaus_meta.cpp index 1ac6013..c4da21c 100644 --- a/meta/foldhaus_meta.cpp +++ b/meta/foldhaus_meta.cpp @@ -27,6 +27,74 @@ #include "gs_meta_error.h" #include "gs_meta_lexer.h" +struct error_buffer +{ + char* Backbuffer; + string* Contents; +}; + +#define ERROR_MAX_LENGTH 256 +#define ERROR_BUFFER_SIZE 256 +struct errors +{ + error_buffer* Buffers; + u32 BuffersCount; + u32 Used; +}; + +internal void +PushFError (errors* Errors, char* Format, ...) +{ + if (Errors->Used >= (Errors->BuffersCount * ERROR_BUFFER_SIZE)) + { + Errors->BuffersCount += 1; + Errors->Buffers = (error_buffer*)realloc(Errors->Buffers, sizeof(error_buffer*) * Errors->BuffersCount); + + error_buffer* NewBuffer = Errors->Buffers + (Errors->BuffersCount - 1); + NewBuffer->Backbuffer = (char*)malloc(sizeof(char) * ERROR_MAX_LENGTH * ERROR_BUFFER_SIZE); + NewBuffer->Contents = (string*)malloc(sizeof(string) * ERROR_BUFFER_SIZE); + + for (u32 i = 0; i < ERROR_BUFFER_SIZE; i++) + { + NewBuffer->Contents[i].Memory = NewBuffer->Backbuffer + (i * ERROR_MAX_LENGTH); + NewBuffer->Contents[i].Max = ERROR_MAX_LENGTH; + NewBuffer->Contents[i].Length = 0; + } + } + + u32 NewErrorIndex = Errors->Used++; + u32 BufferIndex = NewErrorIndex / ERROR_BUFFER_SIZE; + u32 IndexInBuffer = NewErrorIndex % ERROR_BUFFER_SIZE; + string* NewError = Errors->Buffers[BufferIndex].Contents + IndexInBuffer; + + va_list Args; + va_start(Args, Format); + NewError->Length = PrintFArgsList(NewError->Memory, NewError->Max, Format, Args); + va_end(Args); +} + +internal string* +TakeError (errors* Errors) +{ + u32 NewErrorIndex = Errors->Used++; + u32 BufferIndex = NewErrorIndex / ERROR_BUFFER_SIZE; + u32 IndexInBuffer = NewErrorIndex % ERROR_BUFFER_SIZE; + string* NewError = Errors->Buffers[BufferIndex].Contents + IndexInBuffer; + return NewError; +} + +internal void +PrintAllErrors (errors Errors) +{ + for (u32 i = 0; i < Errors.Used; i++) + { + u32 BufferIndex = i / ERROR_BUFFER_SIZE; + u32 IndexInBuffer = i % ERROR_BUFFER_SIZE; + string Error = Errors.Buffers[BufferIndex].Contents[IndexInBuffer]; + printf("%.*s\n", StringExpand(Error)); + } +} + #include "foldhaus_meta_type_table.h" error_list GlobalErrorList = {}; @@ -57,6 +125,8 @@ struct token_iter #define TOKEN_ITER_SNAPSHOTS_MAX 64 u32 SnapshotsUsed; u32 Snapshots[TOKEN_ITER_SNAPSHOTS_MAX]; + + errors* Errors; }; internal token* @@ -308,7 +378,7 @@ GetSecondsElapsed(s64 StartCycles, s64 EndCycles) } internal void -AddFileToSource(string RelativePath, gs_bucket* SourceFiles) +AddFileToSource(string RelativePath, gs_bucket* SourceFiles, errors* Errors) { source_code_file File = {0}; @@ -328,7 +398,7 @@ AddFileToSource(string RelativePath, gs_bucket* SourceFiles) } else { - printf("Error: Could not load file %.*s\n", StringExpand(RelativePath)); + PushFError(Errors, "Error: Could not load file %S\n", RelativePath); } } @@ -448,7 +518,6 @@ LongInt (token_iter* Iter, s32* TypeIndexOut, type_table TypeTable) if (TokenAtEquals(Iter, "unsigned") || TokenAtEquals(Iter, "signed")) { - Result = true; } if (TokenAtEquals(Iter, "long")) @@ -598,12 +667,8 @@ ParseType(token_iter* Iter, type_table* TypeTable, s32* TypeIndexOut) { NextToken(Iter); Result = true; - } - else if (ShortInt(Iter, TypeIndexOut, *TypeTable)) - { - Result = true; } - else if (Int(Iter, TypeIndexOut, *TypeTable)) + else if (LongLongInt(Iter, TypeIndexOut, *TypeTable)) { Result = true; } @@ -611,7 +676,11 @@ ParseType(token_iter* Iter, type_table* TypeTable, s32* TypeIndexOut) { Result = true; } - else if (LongLongInt(Iter, TypeIndexOut, *TypeTable)) + else if (ShortInt(Iter, TypeIndexOut, *TypeTable)) + { + Result = true; + } + else if (Int(Iter, TypeIndexOut, *TypeTable)) { Result = true; } @@ -883,6 +952,7 @@ ParseFunctionDeclaration (token_iter* Iter, token* Identifier, gs_bucket CopyMetaTagsAndClear(TagList, &FunctionPtr.MetaTags); FunctionPtr.Type = TypeDef_FunctionPointer; FunctionPtr.Pointer = true; + FunctionPtr.FunctionPtr = {}; FunctionPtr.FunctionPtr.ReturnTypeIndex = ReturnTypeIndex; *Identifier = *Iter->TokenAt; @@ -959,13 +1029,14 @@ ParseTypedef(token_iter* Iter, gs_bucket* TagList, type_table* TypeTable } else { - printf("unhandled typedef "); + string* Error = TakeError(Iter->Errors); + PrintF(Error, "unhandled typedef "); while (!TokenAtEquals(Iter, ";")) { - printf("%.*s ", StringExpand(Iter->TokenAt->Text)); + PrintF(Error, "%S ", Iter->TokenAt->Text); NextToken(Iter); } - printf("\n"); + PrintF(Error, "\n"); } } @@ -974,6 +1045,91 @@ ParseTypedef(token_iter* Iter, gs_bucket* TagList, type_table* TypeTable return Result; } +internal b32 +ParseEnum (token_iter* Iter, gs_bucket* TagList, type_table* TypeTable) +{ + b32 Result = false; + PushSnapshot(Iter); + + if (TokenAtEquals(Iter, "enum")) + { + if (Iter->TokenAt->Type == Token_Identifier) + { + type_definition EnumDecl = {}; + EnumDecl.Identifier = Iter->TokenAt->Text; + EnumDecl.Size = sizeof(u32); + CopyMetaTagsAndClear(TagList, &EnumDecl.MetaTags); + EnumDecl.Type = TypeDef_Enum; + + NextToken(Iter); + + if (TokenAtEquals(Iter, "{")) + { + u32 EnumeratorAcc = 0; + + while (!StringsEqual(Iter->TokenAt->Text, MakeStringLiteral("}"))) + { + if (Iter->TokenAt->Type == Token_Identifier) + { + string EnumeratorIdentifier = Iter->TokenAt->Text; + NextToken(Iter); + + if (TokenAtEquals(Iter, "=")) + { + // TODO(Peter): TempValue is just here until we handle all + // const expr that could define an enum value. Its there so + // that if the first token of an expression is a number, + // we can avoid using anything from the expression. + u32 TempValue = EnumeratorAcc; + if (Iter->TokenAt->Type == Token_Number) + { + parse_result ParsedExpr = ParseSignedInt(StringExpand(Iter->TokenAt->Text)); + TempValue = ParsedExpr.SignedIntValue; + NextToken(Iter); + } + + // TODO(Peter): Handle setting enums equal to other kinds + // of const exprs. + // We're skipping a whole bunch of stuff now + while (!(StringsEqual(Iter->TokenAt->Text, MakeStringLiteral(",")) || + StringsEqual(Iter->TokenAt->Text, MakeStringLiteral("}")))) + { + TempValue = EnumeratorAcc; + NextToken(Iter); + } + + EnumeratorAcc = TempValue; + } + + s32 EnumeratorValue = EnumeratorAcc++; + if (TokenAtEquals(Iter, ",") || + StringsEqual(Iter->TokenAt->Text, MakeStringLiteral("}"))) + { + EnumDecl.Enum.Identifiers.PushElementOnBucket(EnumeratorIdentifier); + EnumDecl.Enum.Values.PushElementOnBucket(EnumeratorValue); + } + else if (!StringsEqual(Iter->TokenAt->Text, MakeStringLiteral("}"))) + { + Result = false; + break; + } + } + } + + if (TokenAtEquals(Iter, "}") && + TokenAtEquals(Iter, ";")) + { + PushTypeDefOnTypeTable(EnumDecl, TypeTable); + Result = true; + } + } + } + } + + ApplySnapshotIfNotParsedAndPop(Result, Iter); + return Result; +} + internal void PrintIndent (u32 Indent) { @@ -1072,6 +1228,159 @@ PrintFunctionPtrDecl (type_definition* FnPtrDecl, type_table TypeTable) printf(");"); } +struct typeinfo_generator +{ + string_builder TypeList; + string_builder StructMembers; + string_builder TypeDefinitions; + + u32 GeneratedInfoTypesCount; + u32 TypesMax; + b8* TypesGeneratedMask; +}; + +internal typeinfo_generator +InitTypeInfoGenerator(type_table TypeTable) +{ + typeinfo_generator Result = {}; + + Result.TypesMax = TypeTable.Types.Used; + Result.TypesGeneratedMask = (b8*)malloc(sizeof(b8) * Result.TypesMax); + GSZeroMemory((u8*)Result.TypesGeneratedMask, Result.TypesMax); + + WriteF(&Result.TypeList, "enum gsm_struct_type\n{\n"); + + WriteF(&Result.TypeDefinitions, "static gsm_struct_type_info StructTypes[] = {\n"); + return Result; +} + +internal void +FinishGeneratingTypes(typeinfo_generator* Generator) +{ + WriteF(&Generator->TypeList, "gsm_StructTypeCount,\n};\n\n"); + + WriteF(&Generator->StructMembers, "\n"); + + WriteF(&Generator->TypeDefinitions, "};\n"); + WriteF(&Generator->TypeDefinitions, "gsm_u32 StructTypesCount = %d;\n", Generator->GeneratedInfoTypesCount); +} + +internal void +GenerateMetaTagInfo (gs_bucket Tags, string_builder* Builder) +{ + WriteF(Builder, "{"); + for (u32 t = 0; t < Tags.Used; t++) + { + meta_tag* Tag = Tags.GetElementAtIndex(t); + WriteF(Builder, "{ \"%S\", %d }", Tag->Identifier, Tag->Identifier.Length); + if ((t + 1) < Tags.Used) + { + WriteF(Builder, ", "); + } + } + WriteF(Builder, "}, %d", Tags.Used); +} + +internal void +GenerateStructMemberInfo (variable_decl* Member, string StructIdentifier, type_table TypeTable, typeinfo_generator* Gen) +{ + WriteF(&Gen->StructMembers, "{ \"%S\", %d, ", Member->Identifier, Member->Identifier.Length); + WriteF(&Gen->StructMembers, "(u64)&((%S*)0)->%S ", StructIdentifier, Member->Identifier); + WriteF(&Gen->StructMembers, "},\n"); +} + +internal void +GenerateTypeInfo (type_definition* Type, u32 TypeIndex, type_table TypeTable, typeinfo_generator* Generator) +{ + Generator->TypesGeneratedMask[TypeIndex] = true; + Generator->GeneratedInfoTypesCount++; + + { + // NOTE(Peter): This block MUST come before generating + // 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); + + // Type Info + WriteF(&Generator->TypeDefinitions, "{ gsm_StructType_%S, \"%S\", %d, %d, 0, 0, ", + Type->Identifier, + Type->Identifier, Type->Identifier.Length, + Type->Size + // TODO(Peter): include Meta Tags somehow + ); + if ((Type->Type == TypeDef_Struct || Type->Type == TypeDef_Union) && + Type->Struct.MemberDecls.Used > 0) + { + WriteF(&Generator->TypeDefinitions, "StructMembers_%S, %d },\n", + Type->Identifier, + Type->Struct.MemberDecls.Used); + } + else + { + WriteF(&Generator->TypeDefinitions, "0, 0 },\n"); + } + } + + if (Type->Type == TypeDef_Struct || + Type->Type == TypeDef_Union) + { + 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); + + if (MemberType->Identifier.Length == 0) { continue; } // Don't gen info for anonymous struct and union members + if (Generator->TypesGeneratedMask[Member->TypeIndex]) { continue; } + + GenerateTypeInfo(MemberType, Member->TypeIndex, TypeTable, Generator); + } + + // + WriteF(&Generator->StructMembers, "static gsm_struct_member_type_info StructMembers_%S[] = {\n", Type->Identifier); + 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); + + if (MemberType->Identifier.Length > 0) + { + GenerateStructMemberInfo(Member, Type->Identifier, TypeTable, Generator); + } + else if (MemberType->Type == TypeDef_Struct || + MemberType->Type == TypeDef_Union) + { + // Anonymous Members + for (u32 a = 0; a < MemberType->Struct.MemberDecls.Used; a++) + { + variable_decl* AnonMember = MemberType->Struct.MemberDecls.GetElementAtIndex(a); + GenerateStructMemberInfo(AnonMember, Type->Identifier, TypeTable, Generator); + } + } + } + WriteF(&Generator->StructMembers, "};\n", Type->Struct.MemberDecls.Used); + } +} + +internal void +GenerateFilteredTypeInfo (string MetaTagFilter, type_table TypeTable, typeinfo_generator* Generator) +{ + for (u32 i = 0; i < TypeTable.Types.Used; i++) + { + if (Generator->TypesGeneratedMask[i]) + { + continue; + } + + type_definition* Type = TypeTable.Types.GetElementAtIndex(i); + if (HasTag(MetaTagFilter, Type->MetaTags)) + { + GenerateTypeInfo(Type, i, TypeTable, Generator); + } + } +} + // Step 1: Get All Tokens, for every file // Step 2: Identify all preprocessor directives // Step 3: Apply Preprocessor Directives && Generate Code @@ -1087,29 +1396,31 @@ int main(int ArgCount, char** ArgV) return 0; } + errors Errors = {0}; + memory_arena SourceFileArena = {}; gs_bucket SourceFiles; gs_bucket Tokens; string_builder NodeTypeBlock = {}; - Write(MakeStringLiteral("enum node_type\n{\n"), &NodeTypeBlock); + WriteF(&NodeTypeBlock, "enum node_type\n{\n"); string_builder NodeMembersBlock = {}; string_builder NodeSpecificationsBlock = {}; - Write(MakeStringLiteral("node_specification NodeSpecifications[] = {\n"), &NodeSpecificationsBlock); + WriteF(&NodeSpecificationsBlock, "node_specification NodeSpecifications[] = {\n"); string_builder CallNodeProcBlock = {}; - Write(MakeStringLiteral("internal void CallNodeProc(u32 SpecificationIndex, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)\n{\n"), &CallNodeProcBlock); - Write(MakeStringLiteral("node_specification Spec = NodeSpecifications[SpecificationIndex];\n"), &CallNodeProcBlock); - Write(MakeStringLiteral("switch (Spec.Type)\n{\n"), &CallNodeProcBlock); + WriteF(&CallNodeProcBlock, "internal void CallNodeProc(u32 SpecificationIndex, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)\n{\n"); + WriteF(&CallNodeProcBlock, "node_specification Spec = NodeSpecifications[SpecificationIndex];\n"); + WriteF(&CallNodeProcBlock, "switch (Spec.Type)\n{\n"); string CurrentWorkingDirectory = MakeString((char*)malloc(1024), 0, 1024); if (ArgCount > 1) { string RootFile = MakeString(ArgV[1]); - AddFileToSource(RootFile, &SourceFiles); + AddFileToSource(RootFile, &SourceFiles, &Errors); s32 LastSlash = ReverseSearchForCharInSet(RootFile, "\\/"); Assert(LastSlash > 0); @@ -1137,6 +1448,7 @@ int main(int ArgCount, char** ArgV) Iter.LastToken = File->LastTokenIndex; Iter.TokenAtIndex = Iter.FirstToken; Iter.TokenAt = Tokens.GetElementAtIndex(Iter.TokenAtIndex); + Iter.Errors = &Errors; while (Iter.TokenAtIndex < Iter.LastToken) { @@ -1170,7 +1482,7 @@ int main(int ArgCount, char** ArgV) ParseSuccess = true; if (!FileAlreadyInSource(TempFilePath, SourceFiles)) { - AddFileToSource(TempFilePath, &SourceFiles); + AddFileToSource(TempFilePath, &SourceFiles, &Errors); } } } @@ -1178,6 +1490,10 @@ int main(int ArgCount, char** ArgV) { ParseSuccess = true; } + else if (ParseEnum(&Iter, &TagList, &TypeTable)) + { + ParseSuccess = true; + } else if (ParseStruct(&Iter, &TypeIndex, &TagList, &TypeTable)) { ParseSuccess = true; @@ -1200,48 +1516,29 @@ int main(int ArgCount, char** ArgV) type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); if (TypeDef->Type == TypeDef_Struct) { - FixUpStructSize(i, TypeTable); + FixUpStructSize(i, TypeTable, &Errors); } else if (TypeDef->Type == TypeDef_Union) { - FixUpUnionSize(i, TypeTable); + FixUpUnionSize(i, TypeTable, &Errors); } } - // Print All Structs - for (u32 i = 0; i < TypeTable.Types.Used; i++) - { - type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); -#if 0 - if ((TypeDef->Type == TypeDef_Struct || TypeDef->Type == TypeDef_Union) && TypeDef->Identifier.Length > 0) - { - PrintStructDecl(TypeDef, TypeTable); - printf("\n\n"); - } -#endif - - if (TypeDef->Type == TypeDef_FunctionPointer) - { - PrintFunctionPtrDecl(TypeDef, TypeTable); - printf("\n\n"); - } - } - - s64 Cycles_Preprocess = GetWallClock(); + PrintAllErrors(Errors); + MakeStringBuffer(Buffer, 256); // Close Types Block - overwrite the last comma and '\' newline character with newlines. - Write(MakeStringLiteral("NodeType_Count,\n};\n\n"), &NodeTypeBlock); + WriteF(&NodeTypeBlock, "NodeType_Count,\n};\n\n"); // Close Specifications Block - Write(MakeStringLiteral("};\n"), &NodeSpecificationsBlock); - PrintF(&Buffer, "s32 NodeSpecificationsCount = %d;\n\n", NodeProcCount); - Write(Buffer, &NodeSpecificationsBlock); + WriteF(&NodeSpecificationsBlock, "};\n"); + WriteF(&NodeSpecificationsBlock, "s32 NodeSpecificationsCount = %d;\n\n", NodeProcCount); // Close Call Node Proc Block - Write(MakeStringLiteral("}\n}\n"), &CallNodeProcBlock); + WriteF(&CallNodeProcBlock, "}\n}\n"); FILE* NodeGeneratedCPP = fopen("C:\\projects\\foldhaus\\src\\generated\\foldhaus_nodes_generated.cpp", "w"); if (NodeGeneratedCPP) @@ -1253,47 +1550,24 @@ int main(int ArgCount, char** ArgV) fclose(NodeGeneratedCPP); } + typeinfo_generator TypeGenerator = InitTypeInfoGenerator(TypeTable); + GenerateFilteredTypeInfo(MakeStringLiteral("node_struct"), TypeTable, &TypeGenerator); + FinishGeneratingTypes(&TypeGenerator); + FILE* TypeInfoH = fopen("C:\\projects\\foldhaus\\src\\generated\\gs_meta_generated_typeinfo.h", "w"); + if (TypeInfoH) + { + WriteStringBuilderToFile(TypeGenerator.TypeList, TypeInfoH); + WriteStringBuilderToFile(TypeGenerator.StructMembers, TypeInfoH); + WriteStringBuilderToFile(TypeGenerator.TypeDefinitions, TypeInfoH); + fclose(NodeGeneratedCPP); + } + PrintErrorList(GlobalErrorList); s64 TotalEnd = GetWallClock(); - r32 TotalTime = GetSecondsElapsed(TotalStart, TotalEnd); - printf("Metaprogram Preproc Time: %.*f sec\n", 6, TotalTime); -#if 0 - for (u32 i = 0; i < Structs.Used; i++) - { - seen_node_struct* Struct = Structs.GetElementAtIndex(i); - -#ifdef PRINT_ALL_INFO - printf("\n"); - for (u32 j = 0; j < Struct->MetaTags.Used; j++) - { - token* MetaTag = Struct->MetaTags.GetElementAtIndex(j); - printf("GSMetaTag(%.*s)\n", StringExpand(MetaTag->Text)); - } -#endif - - printf("struct %.*s\n", StringExpand(Struct->Name)); - -#ifdef PRINT_ALL_INFO - for (u32 j = 0; j < Struct->MemberDecls.Used; j++) - { - struct_member_decl* Member = Struct->MemberDecls.GetElementAtIndex(j); - - for (u32 k = 0; k < Member->MetaTags.Used; k++) - { - token* MetaTag = Member->MetaTags.GetElementAtIndex(k); - printf(" GSMetaTag(%.*s)\n", StringExpand(MetaTag->Text)); - } - - printf(" %.*s %.*s\n", StringExpand(Member->Type), StringExpand(Member->Identifier)); - } -#endif - } -#endif - - __debugbreak(); + //__debugbreak(); return 0; } \ No newline at end of file diff --git a/meta/foldhaus_meta_include.h b/meta/foldhaus_meta_include.h new file mode 100644 index 0000000..8e3b0fa --- /dev/null +++ b/meta/foldhaus_meta_include.h @@ -0,0 +1,50 @@ +// +// File: foldhaus_meta_include.h +// Author: Peter Slattery +// Creation Date: 2020-01-19 +// +#ifndef FOLDHAUS_META_INCLUDE_H + +// +// NOTE +// Include this file FIRST in any application utilizing the Foldhaus Meta system +// Include the generated files you wish to take advantage of at convenient locations +// in your application +// + +typedef unsigned int gsm_u32; +typedef unsigned long long int gsm_u64; + +#define GSMetaTag(ident, ...) + +struct gsm_meta_tag +{ + char* Tag; + gsm_u32 TagLength; +}; + +struct gsm_struct_member_type_info +{ + char* Identifier; + gsm_u32 IdentifierLength; + gsm_u64 Offset; +}; + +struct gsm_struct_type_info +{ + gsm_u32 Type; + char* Identifier; + gsm_u32 IdentifierLength; + + gsm_u32 Size; + + gsm_meta_tag* Tags; + gsm_u32 TagsCount; + + gsm_struct_member_type_info* Members; + gsm_u32 MembersCount; +}; + + +#define FOLDHAUS_META_INCLUDE_H +#endif // FOLDHAUS_META_INCLUDE_H \ No newline at end of file diff --git a/meta/foldhaus_meta_type_table.h b/meta/foldhaus_meta_type_table.h index 8c273a0..f11dd59 100644 --- a/meta/foldhaus_meta_type_table.h +++ b/meta/foldhaus_meta_type_table.h @@ -11,6 +11,7 @@ enum type_definition_type // NOTE(Peter): tokens with this type require fixup later TypeDef_Unknown, + TypeDef_Enum, TypeDef_Struct, TypeDef_Union, TypeDef_BasicType, @@ -57,6 +58,15 @@ struct function_pointer_decl gs_bucket Parameters; }; +struct enum_decl +{ + gs_bucket Identifiers; + + // TODO(Peter): I suppose there are ways to make an enum a 64 bit number + // for values. Probably need to handle that at some point + gs_bucket Values; +}; + struct type_definition { string Identifier; @@ -67,6 +77,7 @@ struct type_definition type_definition_type Type; union { + enum_decl Enum; struct_decl Struct; function_pointer_decl FunctionPtr; }; @@ -78,17 +89,19 @@ struct type_table gs_bucket Types; }; -internal void -MetaTagBreakpoint(gs_bucket Tags) +internal b32 +HasTag(string Needle, gs_bucket Tags) { + b32 Result = false; for (u32 i = 0; i < Tags.Used; i++) { meta_tag* Tag = Tags.GetElementAtIndex(i); - if (StringsEqual(Tag->Identifier, MakeStringLiteral("breakpoint"))) + if (StringsEqual(Tag->Identifier, Needle)) { - __debugbreak(); + Result = true; } } + return Result; } internal void @@ -136,7 +149,11 @@ PushTypeDefOnTypeTable(type_definition TypeDef, type_table* TypeTable) s32 Index = -1; s32 ExistingUndeclaredTypeIndex = GetIndexOfType(TypeDef.Identifier, *TypeTable); - if (ExistingUndeclaredTypeIndex < 0) + + // 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) { Index = TypeTable->Types.PushElementOnBucket(TypeDef); } @@ -245,8 +262,8 @@ FindIndexOfMatchingType (type_definition Match, type_table TypeTable) return Result; } -internal void FixUpStructSize (s32 StructIndex, type_table TypeTable); -internal void FixUpUnionSize (s32 UnionIndex, type_table TypeTable); +internal void FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors); +internal void FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors); internal void FixupMemberType (variable_decl* Member, type_table TypeTable) @@ -279,12 +296,69 @@ CalculateStructMemberSize (variable_decl Member, type_definition MemberType) } internal void -FixUpStructSize (s32 StructIndex, type_table TypeTable) +FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_table TypeTable, errors* Errors) +{ + // NOTE(Peter): There are a lot of cases where struct members which are pointers + // to other structs cause interesting behavior here. + // For example: + // struct foo { foo* Next; } + // could cause infinite loops if we try and fixup all structs with a size of 0 + // which would happen in this case, because we wouldn't have parsed foo's size + // yet, but would begin fixing up foo because of the type of Next + // Another example: + // typedef struct bar bar; + // struct foo { bar* Bar; } + // struct bar { foo* Foo; } + // causes the exact same problem, but we cant detect it by just excluding + // fixing up StructIndex recursively. + // + // TL;DR + // The solution I've chosen to go with is just exclude all pointer members from + // causing recursive fixups. Those types should be fixed up at some point in the + // process, and we already know how big a pointer is in memory, no matter the type + if (!Member->Pointer) + { + if (MemberTypeDef->Size == 0) + { + if (MemberTypeDef->Type == TypeDef_Struct) + { + FixUpStructSize(Member->TypeIndex, TypeTable, Errors); + } + else if (MemberTypeDef->Type == TypeDef_Union) + { + FixUpUnionSize(Member->TypeIndex, TypeTable, Errors); + } + else + { + if (MemberTypeDef->Type == TypeDef_Unknown) + { + PushFError(Errors, "Union Error: TypeDef Unknown: %S\n", MemberTypeDef->Identifier); + } + else + { + // TODO(Peter): We don't parse all types yet, so for now, this is just an alert, + // not an assert; +#if 0 + InvalidCodePath; +#else + PushFError(Errors, "Struct Error: TypeDef Size = 0. %S\n", MemberTypeDef->Identifier); +#endif + } + } + } + } +} + +internal void +FixUpStructSize (s32 StructIndex, type_table TypeTable, errors* Errors) { type_definition* Struct = TypeTable.Types.GetElementAtIndex(StructIndex); Assert(Struct->Type == TypeDef_Struct); - MetaTagBreakpoint(Struct->MetaTags); + if (HasTag(MakeStringLiteral("breakpoint"), Struct->MetaTags)) + { + __debugbreak(); + } s32 SizeAcc = 0; for (u32 j = 0; j < Struct->Struct.MemberDecls.Used; j++) @@ -292,52 +366,12 @@ FixUpStructSize (s32 StructIndex, type_table TypeTable) variable_decl* Member = Struct->Struct.MemberDecls.GetElementAtIndex(j); FixupMemberType(Member, TypeTable); + // TODO(Peter): if (Member->TypeIndex >= 0) { type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); - // NOTE(Peter): There are a lot of cases where struct members which are pointers - // to other structs cause interesting behavior here. - // For example: - // struct foo { foo* Next; } - // could cause infinite loops if we try and fixup all structs with a size of 0 - // which would happen in this case, because we wouldn't have parsed foo's size - // yet, but would begin fixing up foo because of the type of Next - // Another example: - // typedef struct bar bar; - // struct foo { bar* Bar; } - // struct bar { foo* Foo; } - // causes the exact same problem, but we cant detect it by just excluding - // fixing up StructIndex recursively. - // - // TL;DR - // The solution I've chosen to go with is just exclude all pointer members from - // causing recursive fixups. Those types should be fixed up at some point in the - // process, and we already know how big a pointer is in memory, no matter the type - if (!Member->Pointer) - { - if (MemberTypeDef->Size == 0) - { - if (MemberTypeDef->Type == TypeDef_Struct) - { - FixUpStructSize(Member->TypeIndex, TypeTable); - } - else if (MemberTypeDef->Type == TypeDef_Union) - { - FixUpUnionSize(Member->TypeIndex, TypeTable); - } - else - { - // TODO(Peter): We don't parse all types yet, so for now, this is just an alert, - // not an assert; -#if 0 - InvalidCodePath; -#else - printf("Struct Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier)); -#endif - } - } - } + FixupStructMember(Member, MemberTypeDef, TypeTable, Errors); u32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef); SizeAcc += MemberSize; @@ -346,23 +380,25 @@ FixUpStructSize (s32 StructIndex, type_table TypeTable) Struct->Size = SizeAcc; - // NOTE(Peter): Because its recursive (it makes sure all type sizes become known - // if it needs them) we should never get to the end of this function and not have - // the ability to tell how big something is. - // TODO(Peter): We don't parse all types yet however, so for now, this is just an alert, - // not an assert; -#if 0 - Assert(Struct->Size != 0); -#else - if (Struct->Size == 0) + // NOTE(Peter): It is valid to have an empty struct, which would have a size of + // zero, hence the check here. + if (Struct->Size == 0 && Struct->Struct.MemberDecls.Used > 0) { - printf("Struct Error: Struct Size = 0. %.*s\n", StringExpand(Struct->Identifier)); - } + // NOTE(Peter): Because its recursive (it makes sure all type sizes become known + // if it needs them) we should never get to the end of this function and not have + // the ability to tell how big something is. + // TODO(Peter): We don't parse all types yet however, so for now, this is just an alert, + // not an assert; +#if 0 + Assert(Struct->Size != 0); +#else + PushFError(Errors, "Struct Error: Struct Size = 0. %S\n", Struct->Identifier); #endif + } } internal void -FixUpUnionSize (s32 UnionIndex, type_table TypeTable) +FixUpUnionSize (s32 UnionIndex, type_table TypeTable, errors* Errors) { type_definition* Union = TypeTable.Types.GetElementAtIndex(UnionIndex); Assert(Union->Type == TypeDef_Union); @@ -376,28 +412,7 @@ FixUpUnionSize (s32 UnionIndex, type_table TypeTable) if (Member->TypeIndex >= 0) { type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); - if (MemberTypeDef->Size == 0) - { - if (MemberTypeDef->Type == TypeDef_Struct) - { - FixUpStructSize(Member->TypeIndex, TypeTable); - } - else if(MemberTypeDef->Type == TypeDef_Union) - { - FixUpUnionSize(Member->TypeIndex, TypeTable); - } - else - { - // TODO(Peter): We don't parse all types yet, so for now, this is just an alert, - // not an assert; -#if 0 - InvalidCodePath; -#else - printf("Union Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier)); -#endif - } - } - + FixupStructMember(Member, MemberTypeDef, TypeTable, Errors); s32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef); BiggestMemberSize = GSMax(BiggestMemberSize, MemberSize); } @@ -405,19 +420,21 @@ FixUpUnionSize (s32 UnionIndex, type_table TypeTable) Union->Size = BiggestMemberSize; - // NOTE(Peter): Because its recursive (it makes sure all type sizes become known - // if it needs them) we should never get to the end of this function and not have - // the ability to tell how big something is - // TODO(Peter): We don't parse all types yet however, so for now, this is just an alert, - // not an assert; -#if 0 - Assert(Union->Size != 0); -#else - if (Union->Size == 0) + // NOTE(Peter): It is valid to have an empty struct, which would have a size of + // zero, hence the check here. + if (Union->Size == 0 && Union->Struct.MemberDecls.Used > 0) { - printf("Union Error: Struct Size = 0. %.*s\n", StringExpand(Union->Identifier)); - } + // NOTE(Peter): Because its recursive (it makes sure all type sizes become known + // if it needs them) we should never get to the end of this function and not have + // the ability to tell how big something is + // TODO(Peter): We don't parse all types yet however, so for now, this is just an alert, + // not an assert; +#if 0 + Assert(Union->Size != 0); +#else + PushFError(Errors, "Union Error: Struct Size = 0. %S\n", Union->Identifier); #endif + } } type_definition CPPBasicTypes[] = { diff --git a/meta/gs_meta_lexer.h b/meta/gs_meta_lexer.h index c6b1111..4861cdf 100644 --- a/meta/gs_meta_lexer.h +++ b/meta/gs_meta_lexer.h @@ -104,6 +104,29 @@ GetNextToken (tokenizer* Tokenizer) EatWhitespace(Tokenizer); + // Don't include comments in tokens + while (Tokenizer->At[0] && Tokenizer->At[0] == '/' && Tokenizer->At[1] && Tokenizer->At[1] == '/') + { + EatToNewLine(Tokenizer); + EatWhitespace(Tokenizer); + } + + while(Tokenizer->At[0] && Tokenizer->At[0] == '/' && Tokenizer->At[1] && Tokenizer->At[1] == '*') + { + Tokenizer->At += 2; + while (*Tokenizer->At) + { + if (Tokenizer->At[0] && Tokenizer->At[0] == '*' && Tokenizer->At[1] && Tokenizer->At[1] == '/') + { + Tokenizer->At += 2; + break; + } + EatToNewLine(Tokenizer); + EatWhitespace(Tokenizer); + } + EatWhitespace(Tokenizer); + } + Result.Text = MakeString(Tokenizer->At, 1, 1); // NOTE(Peter): Adding one because I want the tokenizer to work with clear to zero @@ -226,23 +249,6 @@ GetNextToken (tokenizer* Tokenizer) Result.Text.Memory = Tokenizer->At; Result.Text.Length = EatString(Tokenizer); } - else if (C == '/' && Tokenizer->At[0] && Tokenizer->At[0] == '/') - { - Result.Type = Token_Comment; - Result.Text.Length += 1 + EatToNewLine(Tokenizer); - } - else if (C == '/' && Tokenizer->At[0] && Tokenizer->At[0] == '*') - { - s32 CommentLength = 1; - while (Tokenizer->At[0] && Tokenizer->At[0] != '*' && - Tokenizer->At[1] && Tokenizer->At[1] != '/') - { - ++Tokenizer->At; - CommentLength++; - } - - Result.Text.Length += CommentLength; - } // NOTE(Peter): This is after comment parsing so that the division operator // falls through the comment case else if (IsOperator(C)) { Result.Type = Token_Operator; } diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index a7b995b..e98815e 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -5,24 +5,12 @@ // #ifndef FOLDHAUS_APP_CPP -#define GSMetaTag(ident) // this is purely for the sake of the meta layer - +#include "../meta/foldhaus_meta_include.h" #include "foldhaus_platform.h" #include "foldhaus_app.h" -GSMetaTag(node_struct); -struct test_data -{ - r32* Ptr; - - GSMetaTag(output_member); - u32 Output; - - GSMetaTag(foo); - GSMetaTag(input_member); - u32 Input; -}; +#include "./generated/gs_meta_generated_typeinfo.h" internal v4 MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds) diff --git a/src/foldhaus_app.h b/src/foldhaus_app.h index 845dc83..bd9cdf6 100644 --- a/src/foldhaus_app.h +++ b/src/foldhaus_app.h @@ -20,6 +20,11 @@ #include "foldhaus_node.h" +// TODO(Peter): TEMPORARY +u32 NodeSpecificationsCount = 0; +node_specification* NodeSpecifications = 0; + + #include "assembly_parser.cpp" //#include "test_patterns.h" @@ -210,8 +215,8 @@ TestPatternThree(assembly* Assembly, r32 Time) #include "foldhaus_text_entry.cpp" #include "foldhaus_search_lister.cpp" -//#include "foldhaus_default_nodes.h" -#include "generated/foldhaus_nodes_generated.cpp" +#include "foldhaus_default_nodes.h" + #include "foldhaus_node.cpp" FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) diff --git a/src/foldhaus_default_nodes.h b/src/foldhaus_default_nodes.h index ef88cdf..fd68674 100644 --- a/src/foldhaus_default_nodes.h +++ b/src/foldhaus_default_nodes.h @@ -72,12 +72,20 @@ NODE_PROC(AddNodeProc, add_data) // ///////////////////////////////// -NODE_STRUCT(sin_wave_data) +GSMetaTag(node_struct); +struct sin_wave_data { - NODE_IN(r32, Period); - NODE_IN(r32, Min); - NODE_IN(r32, Max); - NODE_OUT(r32, Result); + GSMetaTag(node_input); + r32 Period; + + GSMetaTag(node_input); + r32 Min; + + GSMetaTag(node_input); + r32 Max; + + GSMetaTag(node_input); + r32 Result; r32 Accumulator; }; @@ -109,35 +117,41 @@ NODE_PROC(SinWave, sin_wave_data) // ///////////////////////////////// -NODE_STRUCT(multiply_patterns_data) +GSMetaTag(node_struct); +struct multiply_patterns_data { - NODE_COLOR_BUFFER_IN(A); - NODE_COLOR_BUFFER_IN(B); - NODE_COLOR_BUFFER_OUT(Result); + GSMetaTag(node_input); + color_buffer A; + + GSMetaTag(node_input); + color_buffer B; + + GSMetaTag(node_output); + color_buffer Result; }; NODE_PROC(MultiplyPatterns, multiply_patterns_data) { - 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); - s32 AR = Data->AColors[LED->Index].R; - s32 AG = Data->AColors[LED->Index].G; - s32 AB = Data->AColors[LED->Index].B; + s32 AR = Data->A.Colors[LED->Index].R; + s32 AG = Data->A.Colors[LED->Index].G; + s32 AB = Data->A.Colors[LED->Index].B; - s32 BR = Data->BColors[LED->Index].R; - s32 BG = Data->BColors[LED->Index].G; - s32 BB = Data->BColors[LED->Index].B; + s32 BR = Data->B.Colors[LED->Index].R; + s32 BG = Data->B.Colors[LED->Index].G; + s32 BB = Data->B.Colors[LED->Index].B; s32 RCombined = (AR * BR) / 255; s32 GCombined = (AG * BG) / 255; s32 BCombined = (AB * BB) / 255; - Data->ResultColors[LED->Index].R = (u8)RCombined; - Data->ResultColors[LED->Index].G = (u8)GCombined; - Data->ResultColors[LED->Index].B = (u8)BCombined; + Data->Result.Colors[LED->Index].R = (u8)RCombined; + Data->Result.Colors[LED->Index].G = (u8)GCombined; + Data->Result.Colors[LED->Index].B = (u8)BCombined; LED++; } diff --git a/src/foldhaus_node.h b/src/foldhaus_node.h index 904d3e3..bda5a9f 100644 --- a/src/foldhaus_node.h +++ b/src/foldhaus_node.h @@ -12,19 +12,12 @@ typedef enum node_type node_type; #define DEFAULT_NODE_DIMENSION v2{125, 150} -#define NODE_COLOR_BUFFER \ -led* LEDs; \ -pixel* Colors; \ -s32 LEDCount; - -#define NAMED_NODE_COLOR_BUFFER(name) \ -led* name##LEDs; \ -pixel* name##Colors; \ -s32 name##LEDCount; - -#define NODE_COLOR_BUFFER_INOUT NODE_COLOR_BUFFER -#define NODE_COLOR_BUFFER_IN(name) NAMED_NODE_COLOR_BUFFER(name) -#define NODE_COLOR_BUFFER_OUT(name) NAMED_NODE_COLOR_BUFFER(name) +struct color_buffer +{ + led* LEDs; + pixel* Colors; + s32 LEDCount; +}; // TODO(Peter): Generate this enum struct_member_type @@ -115,7 +108,8 @@ void proc_name(input_type* Data, r32 DeltaTime) struct output_node_data { - NODE_COLOR_BUFFER_IN(Result); + GSMetaTag(node_input); + color_buffer Result; }; void OutputNode(output_node_data* Data, r32 DeltaTime) diff --git a/src/foldhaus_text_entry.cpp b/src/foldhaus_text_entry.cpp index 7909f2e..1d59e10 100644 --- a/src/foldhaus_text_entry.cpp +++ b/src/foldhaus_text_entry.cpp @@ -24,7 +24,7 @@ PipeSearchStringToDestination (text_entry* Input) case TextTranslateTo_R32: { - parse_result FloatParseResult = ParseFloat(Input->Buffer.Memory, Input->Buffer.Length); + parse_result FloatParseResult = ParseFloat(StringExpand(Input->Buffer)); *Input->Destination.FloatDest = FloatParseResult.FloatValue; }break; diff --git a/src/generated/gs_meta_generated_typeinfo.h b/src/generated/gs_meta_generated_typeinfo.h new file mode 100644 index 0000000..8fbbe1b --- /dev/null +++ b/src/generated/gs_meta_generated_typeinfo.h @@ -0,0 +1,67 @@ +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, +}; + +static gsm_struct_member_type_info StructMembers_sin_wave_data[] = { +{ "Period", 6, (u64)&((sin_wave_data*)0)->Period }, +{ "Min", 3, (u64)&((sin_wave_data*)0)->Min }, +{ "Max", 3, (u64)&((sin_wave_data*)0)->Max }, +{ "Result", 6, (u64)&((sin_wave_data*)0)->Result }, +{ "Accumulator", 11, (u64)&((sin_wave_data*)0)->Accumulator }, +}; +static gsm_struct_member_type_info StructMembers_v4[] = { +{ "x", 1, (u64)&((v4*)0)->x }, +{ "y", 1, (u64)&((v4*)0)->y }, +{ "z", 1, (u64)&((v4*)0)->z }, +{ "w", 1, (u64)&((v4*)0)->w }, +{ "r", 1, (u64)&((v4*)0)->r }, +{ "g", 1, (u64)&((v4*)0)->g }, +{ "b", 1, (u64)&((v4*)0)->b }, +{ "a", 1, (u64)&((v4*)0)->a }, +{ "E", 1, (u64)&((v4*)0)->E }, +}; +static gsm_struct_member_type_info StructMembers_led[] = { +{ "Index", 5, (u64)&((led*)0)->Index }, +{ "Position", 8, (u64)&((led*)0)->Position }, +}; +static gsm_struct_member_type_info StructMembers_pixel[] = { +{ "R", 1, (u64)&((pixel*)0)->R }, +{ "G", 1, (u64)&((pixel*)0)->G }, +{ "B", 1, (u64)&((pixel*)0)->B }, +{ "Channels", 8, (u64)&((pixel*)0)->Channels }, +}; +static gsm_struct_member_type_info StructMembers_color_buffer[] = { +{ "LEDs", 4, (u64)&((color_buffer*)0)->LEDs }, +{ "Colors", 6, (u64)&((color_buffer*)0)->Colors }, +{ "LEDCount", 8, (u64)&((color_buffer*)0)->LEDCount }, +}; +static gsm_struct_member_type_info StructMembers_multiply_patterns_data[] = { +{ "A", 1, (u64)&((multiply_patterns_data*)0)->A }, +{ "B", 1, (u64)&((multiply_patterns_data*)0)->B }, +{ "Result", 6, (u64)&((multiply_patterns_data*)0)->Result }, +}; + +static gsm_struct_type_info StructTypes[] = { +{ gsm_StructType_sin_wave_data, "sin_wave_data", 13, 20, 0, 0, StructMembers_sin_wave_data, 5 }, +{ gsm_StructType_r32, "r32", 3, 4, 0, 0, 0, 0 }, +{ gsm_StructType_multiply_patterns_data, "multiply_patterns_data", 22, 60, 0, 0, StructMembers_multiply_patterns_data, 3 }, +{ gsm_StructType_color_buffer, "color_buffer", 12, 20, 0, 0, StructMembers_color_buffer, 3 }, +{ gsm_StructType_led, "led", 3, 20, 0, 0, StructMembers_led, 2 }, +{ gsm_StructType_s32, "s32", 3, 4, 0, 0, 0, 0 }, +{ gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 3 }, +{ gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, +{ 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; diff --git a/src/panels/foldhaus_panel_node_graph.h b/src/panels/foldhaus_panel_node_graph.h index 1d5a3ec..14ce62e 100644 --- a/src/panels/foldhaus_panel_node_graph.h +++ b/src/panels/foldhaus_panel_node_graph.h @@ -491,7 +491,7 @@ PANEL_RENDER_PROC(NodeGraph_Render) string TitleString = MakeStringLiteral("Available Nodes"); DrawListElement(TitleString, &List, Mouse, RenderBuffer, State->Interface); - for (s32 i = 0; i < NodeSpecificationsCount; i++) + for (u32 i = 0; i < NodeSpecificationsCount; i++) { node_specification Spec = NodeSpecifications[i]; string NodeName = MakeString(Spec.Name, Spec.NameLength); diff --git a/src/test_patterns.h b/src/test_patterns.h index d166956..bd6f409 100644 --- a/src/test_patterns.h +++ b/src/test_patterns.h @@ -6,13 +6,18 @@ #ifndef TEST_PATTERNS_H -NODE_STRUCT(solid_color_data) +GSMetaTag(node_struct) +struct solid_color_data { - NODE_IN(v4, Color); - NODE_COLOR_BUFFER_OUT(Result); + GSMetaTag(node_input); + v4 Color; + + GSMetaTag(node_output); + color_buffer Result; }; -NODE_PROC(SolidColorProc, solid_color_data) +GSMetaTag(node_proc); // :TagParamsForNodeParamStructs +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); @@ -30,15 +35,24 @@ NODE_PROC(SolidColorProc, solid_color_data) } } -NODE_STRUCT(vertical_color_fade_data) +GSMetaTag(node_struct) +struct vertical_color_fade_data { - NODE_IN(v4, Color); - NODE_IN(r32, Min); - NODE_IN(r32, Max); - NODE_COLOR_BUFFER_OUT(Result); + GSMetaTag(node_input); + v4 Color; + + GSMetaTag(node_input); + r32 Min; + + GSMetaTag(node_input); + r32 Max; + + GSMetaTag(node_output); + color_buffer Result; }; -NODE_PROC(VerticalColorFadeProc, vertical_color_fade_data) +GSMetaTag(node_proc); // :TagParamsForNodeParamStructs +void VerticalColorFadeProc, vertical_color_fade_data* Data) { r32 R = (Data->Color.r * 255); r32 G = (Data->Color.g * 255); @@ -62,19 +76,36 @@ NODE_PROC(VerticalColorFadeProc, vertical_color_fade_data) } // Original -> DiscPatterns.pde : Revolving Discs -NODE_STRUCT(revolving_discs_data) +GSMetaTag(node_struct) +struct revolving_discs_data { - NODE_IN(r32, Rotation); - NODE_IN(r32, ThetaZ); - NODE_IN(r32, ThetaY); - NODE_IN(r32, DiscWidth); - NODE_IN(r32, InnerRadius); - NODE_IN(r32, OuterRadius); - NODE_IN(v4, Color); - NODE_COLOR_BUFFER_OUT(Result); + GSMetaTag(node_input); + r32 Rotation; + + GSMetaTag(node_input); + r32 ThetaZ; + + GSMetaTag(node_input); + r32 ThetaY; + + GSMetaTag(node_input); + r32 DiscWidth; + + GSMetaTag(node_input); + r32 InnerRadius; + + GSMetaTag(node_input); + r32 OuterRadius; + + GSMetaTag(node_input); + v4 Color; + + GSMetaTag(node_output); + color_buffer Result; }; -NODE_PROC(RevolvingDiscs, revolving_discs_data) +GSMetaTag(node_proc); // :TagParamsForNodeParamStructs +void RevolvingDiscs, revolving_discs_data* Data) { DEBUG_TRACK_FUNCTION;