Lots of work on the meta system. Most changes in src are just due to me putting test data in place
This commit is contained in:
parent
af68881e04
commit
b11d9da9e4
|
@ -20,7 +20,7 @@ del *.pdb > NUL 2> NUL
|
|||
|
||||
REM Run the Preprocessor
|
||||
pushd ..\src\
|
||||
..\build\foldhaus_meta.exe C:\projects\foldhaus\src\
|
||||
..\build\foldhaus_meta.exe C:\projects\foldhaus\src\foldhaus_app.cpp
|
||||
popd
|
||||
|
||||
REM cl %CommonCompilerFlags% F:\src\foldhaus_util_radialumia_file_converter.cpp /link %CommonLinkerFlags%
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,409 @@
|
|||
//
|
||||
// File: foldhaus_meta_type_table.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-17
|
||||
//
|
||||
#ifndef FOLDHAUS_META_TYPE_TABLE_H
|
||||
|
||||
enum type_definition_type
|
||||
{
|
||||
TypeDef_Invalid,
|
||||
|
||||
TypeDef_Unknown, // NOTE(Peter): these require fixup later
|
||||
TypeDef_Struct,
|
||||
TypeDef_Union,
|
||||
TypeDef_BasicType,
|
||||
TypeDef_FunctionPointer,
|
||||
|
||||
TypeDef_Count,
|
||||
};
|
||||
|
||||
struct meta_tag
|
||||
{
|
||||
string Identifier;
|
||||
};
|
||||
|
||||
struct struct_member_decl
|
||||
{
|
||||
// NOTE(Peter): Because of the way the tokenizer works, we don't lex and parse
|
||||
// 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;
|
||||
string Identifier;
|
||||
b32 Pointer;
|
||||
|
||||
// NOTE(Peter): Zero means its not an array, since you cannot initialize a static
|
||||
// array to size 0. ie this is invalid: r32 x[0]; and will throw a compiler error
|
||||
u32 ArrayCount;
|
||||
|
||||
// :SmallAllocationsAllOver
|
||||
gs_bucket<meta_tag> MetaTags;
|
||||
};
|
||||
|
||||
// TODO(Peter): This is just a struct_decl
|
||||
struct struct_decl
|
||||
{
|
||||
// TODO(Peter): Lots of tiny arrays everywhere! Pull these into a central allocation
|
||||
// buffer somewhere
|
||||
// :SmallAllocationsAllOver
|
||||
gs_bucket<struct_member_decl> MemberDecls;
|
||||
};
|
||||
|
||||
struct type_definition
|
||||
{
|
||||
string Identifier;
|
||||
|
||||
s32 Size;
|
||||
gs_bucket<meta_tag> MetaTags;
|
||||
|
||||
type_definition_type Type;
|
||||
union
|
||||
{
|
||||
struct_decl Struct;
|
||||
};
|
||||
b32 Pointer;
|
||||
};
|
||||
|
||||
struct type_table
|
||||
{
|
||||
gs_bucket<type_definition> Types;
|
||||
};
|
||||
|
||||
internal void
|
||||
CopyMetaTagsAndClear(gs_bucket<token*>* Source, gs_bucket<meta_tag>* Dest)
|
||||
{
|
||||
for (u32 i = 0; i < Source->Used; i++)
|
||||
{
|
||||
token* TagToken = *Source->GetElementAtIndex(i);
|
||||
meta_tag TagDest = {0};
|
||||
TagDest.Identifier = TagToken->Text;
|
||||
Dest->PushElementOnBucket(TagDest);
|
||||
}
|
||||
Source->Used = 0;
|
||||
}
|
||||
|
||||
internal type_definition*
|
||||
PushStructOnTypeTable(string Identifier, type_definition_type DeclType, gs_bucket<token*>* TagList, type_table* TypeTable)
|
||||
{
|
||||
Assert(DeclType == TypeDef_Struct || DeclType == TypeDef_Union);
|
||||
|
||||
type_definition* Result = TypeTable->Types.TakeElement();
|
||||
*Result = {0};
|
||||
|
||||
Result->Type = DeclType;
|
||||
Result->Identifier = Identifier;
|
||||
CopyMetaTagsAndClear(TagList, &Result->MetaTags);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
PushTypeDefOnTypeTable(type_definition TypeDef, type_table* TypeTable)
|
||||
{
|
||||
s32 Index = -1;
|
||||
if (TypeDef.Type != TypeDef_BasicType)
|
||||
{
|
||||
printf("Invalid TypeDef: %.*s\n", StringExpand(TypeDef.Identifier));
|
||||
}
|
||||
else
|
||||
{
|
||||
Index = TypeTable->Types.PushElementOnBucket(TypeDef);
|
||||
}
|
||||
return Index;
|
||||
}
|
||||
|
||||
internal s32
|
||||
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;
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetIndexOfType (string Identifier, type_table TypeTable)
|
||||
{
|
||||
s32 Result = -1;
|
||||
for (u32 i = 0; i < TypeTable.Types.Used; i++)
|
||||
{
|
||||
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i);
|
||||
if (StringsEqual(Identifier, TypeDef->Identifier))
|
||||
{
|
||||
Result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetSizeOfType (s32 TypeIndex, type_table TypeTable)
|
||||
{
|
||||
s32 Result = -1;
|
||||
Assert(TypeIndex >= 0 && (u32)TypeIndex < TypeTable.Types.Used);
|
||||
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(TypeIndex);
|
||||
Result = TypeDef->Size;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetSizeOfType (string Identifier, type_table TypeTable)
|
||||
{
|
||||
s32 Result = -1;
|
||||
for (u32 i = 0; i < TypeTable.Types.Used; i++)
|
||||
{
|
||||
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i);
|
||||
if (StringsEqual(Identifier, TypeDef->Identifier))
|
||||
{
|
||||
Result = TypeDef->Size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
StructMembersEqual (struct_member_decl A, struct_member_decl B)
|
||||
{
|
||||
b32 Result = false;
|
||||
if (A.TypeIndex == B.TypeIndex &&
|
||||
A.ArrayCount == B.ArrayCount &&
|
||||
StringsEqual(A.Identifier, B.Identifier))
|
||||
{
|
||||
Result = true;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
StructOrUnionsEqual (type_definition A, type_definition B)
|
||||
{
|
||||
// NOTE(Peter): Fairly certain the only places this is used are when we
|
||||
// already know the identifiers match
|
||||
Assert(StringsEqual(A.Identifier, B.Identifier));
|
||||
Assert(A.Type == TypeDef_Struct || A.Type == TypeDef_Union);
|
||||
Assert(B.Type == TypeDef_Struct || B.Type == TypeDef_Union);
|
||||
|
||||
b32 Result = false;
|
||||
if (A.Struct.MemberDecls.Used == B.Struct.MemberDecls.Used)
|
||||
{
|
||||
Result = true;
|
||||
for (u32 i = 0; i < A.Struct.MemberDecls.Used; i++)
|
||||
{
|
||||
struct_member_decl* AMember = A.Struct.MemberDecls.GetElementAtIndex(i);
|
||||
struct_member_decl* BMember = A.Struct.MemberDecls.GetElementAtIndex(i);
|
||||
|
||||
if (!StructMembersEqual(*AMember, *BMember))
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
FindIndexOfMatchingType (type_definition Match, type_table TypeTable)
|
||||
{
|
||||
s32 Result = -1;
|
||||
for (u32 i = 0; i < TypeTable.Types.Used; i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void FixUpStructSize (type_definition* Struct, type_table TypeTable);
|
||||
internal void FixUpUnionSize (type_definition* Union, type_table TypeTable);
|
||||
|
||||
internal void
|
||||
FixupMemberType (struct_member_decl* Member, type_table TypeTable)
|
||||
{
|
||||
if (Member->TypeIndex == -1)
|
||||
{
|
||||
Member->TypeIndex = GetIndexOfType(Member->Identifier, TypeTable);
|
||||
}
|
||||
Assert(Member->TypeIndex >= 0);
|
||||
}
|
||||
|
||||
internal s32
|
||||
CalculateStructMemberSize (struct_member_decl Member, type_definition MemberType)
|
||||
{
|
||||
Assert(Member.TypeIndex >= 0);
|
||||
// TODO(Peter): Assert(MemberType.Size != 0);
|
||||
|
||||
s32 Result = MemberType.Size;
|
||||
if (Member.ArrayCount > 0)
|
||||
{
|
||||
Result *= Member.ArrayCount;
|
||||
}
|
||||
|
||||
if (Member.Pointer)
|
||||
{
|
||||
Result = sizeof(void*);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
FixUpStructSize (type_definition* Struct, type_table TypeTable)
|
||||
{
|
||||
Assert(Struct->Type == TypeDef_Struct);
|
||||
|
||||
s32 SizeAcc = 0;
|
||||
for (u32 j = 0; j < Struct->Struct.MemberDecls.Used; j++)
|
||||
{
|
||||
struct_member_decl* Member = Struct->Struct.MemberDecls.GetElementAtIndex(j);
|
||||
FixupMemberType(Member, TypeTable);
|
||||
|
||||
if (Member->TypeIndex >= 0)
|
||||
{
|
||||
type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex);
|
||||
if (MemberTypeDef->Size == 0)
|
||||
{
|
||||
if (MemberTypeDef->Type == TypeDef_Struct)
|
||||
{
|
||||
FixUpStructSize(MemberTypeDef, TypeTable);
|
||||
}
|
||||
else if(MemberTypeDef->Type == TypeDef_Union)
|
||||
{
|
||||
FixUpUnionSize(MemberTypeDef, 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("Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
u32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef);
|
||||
SizeAcc += MemberSize;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
printf("Error: Struct Size = 0. %.*s\n", StringExpand(Struct->Identifier));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void
|
||||
FixUpUnionSize (type_definition* Union, type_table TypeTable)
|
||||
{
|
||||
Assert(Union->Type == TypeDef_Union);
|
||||
|
||||
s32 BiggestMemberSize = 0;
|
||||
for (u32 j = 0; j < Union->Struct.MemberDecls.Used; j++)
|
||||
{
|
||||
struct_member_decl* Member = Union->Struct.MemberDecls.GetElementAtIndex(j);
|
||||
FixupMemberType(Member, TypeTable);
|
||||
|
||||
if (Member->TypeIndex >= 0)
|
||||
{
|
||||
type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex);
|
||||
if (MemberTypeDef->Size == 0)
|
||||
{
|
||||
if (MemberTypeDef->Type == TypeDef_Struct)
|
||||
{
|
||||
FixUpStructSize(MemberTypeDef, TypeTable);
|
||||
}
|
||||
else if(MemberTypeDef->Type == TypeDef_Union)
|
||||
{
|
||||
FixUpUnionSize(MemberTypeDef, 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("Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
s32 MemberSize = CalculateStructMemberSize(*Member, *MemberTypeDef);
|
||||
BiggestMemberSize = GSMax(BiggestMemberSize, MemberSize);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
printf("Error: Struct Size = 0. %.*s\n", StringExpand(Union->Identifier));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
type_definition CPPBasicTypes[] = {
|
||||
{ MakeStringLiteral("float"), sizeof(float), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("double"), sizeof(double), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("char"), sizeof(char), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("wchar_t"), sizeof(wchar_t), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("int"), sizeof(int), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("short"), sizeof(short), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("short int"), sizeof(short int), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("long int"), sizeof(long int), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("long long int"), sizeof(long long int), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("void"), sizeof(void*), {}, TypeDef_BasicType, {}, false },
|
||||
{ MakeStringLiteral("bool"), sizeof(bool), {}, TypeDef_BasicType, {}, false },
|
||||
};
|
||||
|
||||
internal void
|
||||
PopulateTableWithDefaultCPPTypes(type_table* TypeTable)
|
||||
{
|
||||
for (u32 i = 0; i < GSArrayLength(CPPBasicTypes); i++)
|
||||
{
|
||||
PushTypeDefOnTypeTable(CPPBasicTypes[i], TypeTable);
|
||||
}
|
||||
}
|
||||
|
||||
#define FOLDHAUS_META_TYPE_TABLE_H
|
||||
#endif // FOLDHAUS_META_TYPE_TABLE_H
|
|
@ -5,18 +5,32 @@ struct token_selection_spec
|
|||
};
|
||||
|
||||
internal s32
|
||||
EatPreprocessor (tokenizer* Tokenizer, token_type* Type)
|
||||
EatPreprocessor (tokenizer* Tokenizer)
|
||||
{
|
||||
s32 Length = 0;
|
||||
|
||||
// TODO(Peter): Make this actually separate out the different arguments?
|
||||
while (Tokenizer->At[0] && !IsNewline(Tokenizer->At[0]))
|
||||
char* TStart = Tokenizer->At;
|
||||
while (AtValidPosition(*Tokenizer) && !IsNewline(*Tokenizer->At))
|
||||
{
|
||||
++Tokenizer->At;
|
||||
Length++;
|
||||
if (Tokenizer->At[0] == '\\')
|
||||
{
|
||||
EatChar(Tokenizer);
|
||||
|
||||
while (IsWhitespace(*Tokenizer->At))
|
||||
{
|
||||
EatChar(Tokenizer);
|
||||
}
|
||||
|
||||
if (IsNewline(*Tokenizer->At))
|
||||
{
|
||||
EatPastNewLine(Tokenizer);
|
||||
}
|
||||
}
|
||||
else if (!IsNewline(*Tokenizer->At))
|
||||
{
|
||||
EatChar(Tokenizer);
|
||||
}
|
||||
}
|
||||
|
||||
return Length;
|
||||
return Tokenizer->At - TStart;
|
||||
}
|
||||
|
||||
internal s32
|
||||
|
@ -55,6 +69,34 @@ EatIdentifier (tokenizer* Tokenizer)
|
|||
return Length;
|
||||
}
|
||||
|
||||
internal b32
|
||||
TokenAtEquals(tokenizer* Tokenizer, char* Needle)
|
||||
{
|
||||
b32 Result = true;
|
||||
|
||||
char* TokenizerStart = Tokenizer->At;
|
||||
|
||||
char* NeedleAt = Needle;
|
||||
while (AtValidPosition(*Tokenizer) && *NeedleAt)
|
||||
{
|
||||
if (*NeedleAt != *Tokenizer->At)
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
NeedleAt++;
|
||||
EatChar(Tokenizer);
|
||||
}
|
||||
|
||||
// NOTE(Peter): rewind tokenizer
|
||||
if (!Result)
|
||||
{
|
||||
Tokenizer->At = TokenizerStart;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal token
|
||||
GetNextToken (tokenizer* Tokenizer)
|
||||
{
|
||||
|
@ -64,6 +106,9 @@ GetNextToken (tokenizer* Tokenizer)
|
|||
|
||||
Result.Text = MakeString(Tokenizer->At, 1, 1);
|
||||
|
||||
// NOTE(Peter): Adding one because I want the tokenizer to work with clear to zero
|
||||
// but line numbers generally start at 1, not 0
|
||||
Result.LineNumber = Tokenizer->LineNumber + 1;
|
||||
|
||||
char C = Tokenizer->At[0];
|
||||
++Tokenizer->At;
|
||||
|
@ -86,37 +131,82 @@ GetNextToken (tokenizer* Tokenizer)
|
|||
}
|
||||
else if (C == '#')
|
||||
{
|
||||
Result.Text.Length += EatPreprocessor(Tokenizer, &Result.Type);
|
||||
// NOTE(Peter): Technically correct to do things like "# define"
|
||||
EatWhitespace(Tokenizer);
|
||||
|
||||
if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#define", 7))
|
||||
{ Result.Type = Token_PoundDefine; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#undef", 6))
|
||||
{ Result.Type = Token_PoundUndef; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#include", 8))
|
||||
{ Result.Type = Token_PoundInclude; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#ifdef", 6))
|
||||
{ Result.Type = Token_PoundIfDef; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#ifndef", 7))
|
||||
{ Result.Type = Token_PoundIfNDef; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#if", 3))
|
||||
{ Result.Type = Token_PoundIf; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#elif", 5))
|
||||
{ Result.Type = Token_PoundElif; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#else", 5))
|
||||
{ Result.Type = Token_PoundElse; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#endif", 6))
|
||||
{ Result.Type = Token_PoundEndif; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#error", 6))
|
||||
{ Result.Type = Token_PoundError; }
|
||||
else if (CharArraysEqual(Result.Text.Memory, Result.Text.Length, "#pragma", 7))
|
||||
{ Result.Type = Token_PoundPragma; }
|
||||
if (TokenAtEquals(Tokenizer, "define"))
|
||||
{
|
||||
Result.Type = Token_PoundDefine;
|
||||
EatPreprocessor(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "undef"))
|
||||
{
|
||||
Result.Type = Token_PoundUndef;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "include"))
|
||||
{
|
||||
Result.Type = Token_PoundInclude;
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "ifdef"))
|
||||
{
|
||||
Result.Type = Token_PoundIfDef;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "ifndef"))
|
||||
{
|
||||
Result.Type = Token_PoundIfNDef;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "if"))
|
||||
{
|
||||
Result.Type = Token_PoundIf;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "elif"))
|
||||
{
|
||||
Result.Type = Token_PoundElif;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "else"))
|
||||
{
|
||||
Result.Type = Token_PoundElse;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "endif"))
|
||||
{
|
||||
Result.Type = Token_PoundEndif;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "error"))
|
||||
{
|
||||
Result.Type = Token_PoundError;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
else if (TokenAtEquals(Tokenizer, "pragma"))
|
||||
{
|
||||
Result.Type = Token_PoundPragma;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Result.Text.Memory;
|
||||
}
|
||||
}
|
||||
else if (IsNumeric(C))
|
||||
{
|
||||
Result.Type = Token_Number;
|
||||
char* Start = Tokenizer->At;
|
||||
EatNumber(Tokenizer);
|
||||
Result.Text.Length = Tokenizer->At - Start;
|
||||
|
||||
// NOTE(Peter): adding 1 to account for the fact that we've already advanced
|
||||
// Tokenizer once
|
||||
Result.Text.Length = 1 + EatNumber(Tokenizer);
|
||||
}
|
||||
else if (C == '\'')
|
||||
{
|
||||
|
@ -139,9 +229,7 @@ GetNextToken (tokenizer* Tokenizer)
|
|||
else if (C == '/' && Tokenizer->At[0] && Tokenizer->At[0] == '/')
|
||||
{
|
||||
Result.Type = Token_Comment;
|
||||
char* Start = Tokenizer->At;
|
||||
EatToNewLine(Tokenizer);
|
||||
Result.Text.Length += 1 + (Tokenizer->At - Start);
|
||||
Result.Text.Length += 1 + EatToNewLine(Tokenizer);
|
||||
}
|
||||
else if (C == '/' && Tokenizer->At[0] && Tokenizer->At[0] == '*')
|
||||
{
|
||||
|
@ -167,46 +255,44 @@ GetNextToken (tokenizer* Tokenizer)
|
|||
return Result;
|
||||
}
|
||||
|
||||
internal token*
|
||||
FindNextMatchingToken (token* Tokens, token_selection_spec Spec)
|
||||
internal s32
|
||||
FindNextMatchingToken (u32 TokenAt, u32 TokenMax, gs_bucket<token> Tokens, token_selection_spec Spec)
|
||||
{
|
||||
token* Result = 0;
|
||||
s32 Result = -1;
|
||||
|
||||
token* Token = Tokens;
|
||||
while (Token)
|
||||
s32 Start = (s32)TokenAt + 1;
|
||||
for (s32 i = Start; i < (s32)TokenMax; i++)
|
||||
{
|
||||
token* Token = Tokens.GetElementAtIndex(i);
|
||||
|
||||
if (Token->Text.Memory)
|
||||
{
|
||||
b32 Matches = false;
|
||||
if (Spec.MatchText && StringsEqual(Spec.Text, Token->Text))
|
||||
{
|
||||
Matches = true;
|
||||
}
|
||||
|
||||
if (Matches)
|
||||
{
|
||||
Result = Token;
|
||||
Result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Token = Token->Next;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal token*
|
||||
GetNextTokenOfType (token* Tokens, token_type Type)
|
||||
internal s32
|
||||
GetNextTokenOfType (s32 TokenAtIndex, s32 Max, gs_bucket<token> Tokens, token_type Type)
|
||||
{
|
||||
token* Result = 0;
|
||||
s32 Result = -1;
|
||||
|
||||
token* Iter = Tokens->Next;
|
||||
while((Iter != 0) && (Iter->Type != Type))
|
||||
s32 Start = TokenAtIndex + 1;
|
||||
for (s32 i = Start; i < Max; i++)
|
||||
{
|
||||
Iter = Iter->Next;
|
||||
token* At = Tokens.GetElementAtIndex(i);
|
||||
if (At->Type == Type)
|
||||
{
|
||||
Result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Result = Iter;
|
||||
return Result;
|
||||
}
|
|
@ -12,7 +12,7 @@ ParseToken (tokenizer* Tokenizer)
|
|||
assembly_token Result = {};
|
||||
Result.Token = Tokenizer->At;
|
||||
Result.Length = 1;
|
||||
Tokenizer->At++;
|
||||
EatChar(Tokenizer);
|
||||
|
||||
if (*Result.Token == ':'){ Result.Type = AssemblyToken_Colon; }
|
||||
else if (*Result.Token == ';'){ Result.Type = AssemblyToken_SemiColon; }
|
||||
|
@ -21,20 +21,20 @@ ParseToken (tokenizer* Tokenizer)
|
|||
else if (*Result.Token ==','){ Result.Type = AssemblyToken_Comma; }
|
||||
else if (IsNumericExtended(*Result.Token))
|
||||
{
|
||||
while(*Tokenizer->At && IsNumericExtended(*Tokenizer->At)) { Tokenizer->At++; }
|
||||
while(*Tokenizer->At && IsNumericExtended(*Tokenizer->At)) { EatChar(Tokenizer); }
|
||||
Result.Type = AssemblyToken_Number;
|
||||
Result.Length = Tokenizer->At - Result.Token;
|
||||
}
|
||||
else if (*Result.Token =='\"')
|
||||
{
|
||||
while(*Tokenizer->At && *Tokenizer->At != '\"') { Tokenizer->At++; }
|
||||
while(*Tokenizer->At && *Tokenizer->At != '\"') { EatChar(Tokenizer); }
|
||||
Result.Token++; // Skip the quote
|
||||
Result.Type = AssemblyToken_String;
|
||||
Result.Length = (Tokenizer->At - Result.Token) - 1;
|
||||
}
|
||||
else if (*Result.Token == '(')
|
||||
{
|
||||
while(*Tokenizer->At && *Tokenizer->At != ')') { Tokenizer->At++; }
|
||||
while(*Tokenizer->At && *Tokenizer->At != ')') { EatChar(Tokenizer); }
|
||||
Result.Token++; // Skip the paren
|
||||
Result.Type = AssemblyToken_Vector;
|
||||
Result.Length = (Tokenizer->At - Result.Token) - 1;
|
||||
|
@ -54,7 +54,7 @@ ParseToken (tokenizer* Tokenizer)
|
|||
else
|
||||
{
|
||||
Result.Type = AssemblyToken_Identifier;
|
||||
while(*Tokenizer->At && !IsWhitespace(*Tokenizer->At)) { Tokenizer->At++; }
|
||||
while(*Tokenizer->At && !IsWhitespace(*Tokenizer->At)) { EatChar(Tokenizer); }
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
@ -116,7 +116,7 @@ ParseLEDStrip (tokenizer* Tokenizer)
|
|||
led_strip_definition Result = {};
|
||||
|
||||
// Control Box Index
|
||||
while (*Tokenizer->At && !IsNumericExtended(*Tokenizer->At)) { Tokenizer->At++; }
|
||||
while (*Tokenizer->At && !IsNumericExtended(*Tokenizer->At)) { EatChar(Tokenizer); }
|
||||
assembly_token BoxIDToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
Result.ControlBoxID = ParseSignedIntUnsafe(BoxIDToken.Token).SignedIntValue;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
typedef INITIALIZE_APPLICATION(initialize_application);
|
||||
|
||||
//
|
||||
// File: foldhaus_app.cpp
|
||||
// Author: Peter Slattery
|
||||
|
@ -5,9 +7,25 @@
|
|||
//
|
||||
#ifndef FOLDHAUS_APP_CPP
|
||||
|
||||
#define GSMetaTag(ident) // this is purely for the sake of the meta layer
|
||||
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
internal v4
|
||||
MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds)
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "foldhaus_node.h"
|
||||
|
||||
#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
|
||||
|
@ -210,7 +210,7 @@ TestPatternThree(assembly* Assembly, r32 Time)
|
|||
#include "foldhaus_text_entry.cpp"
|
||||
#include "foldhaus_search_lister.cpp"
|
||||
|
||||
#include "foldhaus_default_nodes.h"
|
||||
//#include "foldhaus_default_nodes.h"
|
||||
#include "generated/foldhaus_nodes_generated.cpp"
|
||||
#include "foldhaus_node.cpp"
|
||||
|
||||
|
|
|
@ -113,12 +113,12 @@ void proc_name(input_type* Data, r32 DeltaTime)
|
|||
// OUTPUT NODE
|
||||
///////////////////////////////////////////////
|
||||
|
||||
NODE_STRUCT(output_node_data)
|
||||
struct output_node_data
|
||||
{
|
||||
NODE_COLOR_BUFFER_IN(Result);
|
||||
};
|
||||
|
||||
NODE_PROC(OutputNode, output_node_data)
|
||||
void OutputNode(output_node_data* Data, r32 DeltaTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define GS_LANGUAGE_NO_PROFILER_DEFINES
|
||||
#include <gs_language.h>
|
||||
#include "C:\programs-dev\gs_libs\src\gs_language.h"
|
||||
#include "gs_platform.h"
|
||||
|
||||
#include <gs_radix_sort.h>
|
||||
#include <gs_list.h>
|
||||
#include <gs_bucket.h>
|
||||
#include "C:\programs-dev\gs_libs\src\gs_radix_sort.h"
|
||||
#include "C:\programs-dev\gs_libs\src\gs_list.h"
|
||||
#include "C:\programs-dev\gs_libs\src\gs_bucket.h"
|
||||
|
||||
#define GS_MEMORY_TRACK_ALLOCATIONS
|
||||
#include <gs_memory_arena.h>
|
||||
#include "C:\programs-dev\gs_libs\src\gs_memory_arena.h"
|
||||
|
||||
#include <gs_string.h>
|
||||
#include "C:\programs-dev\gs_libs\src\gs_string.h"
|
||||
#include "foldhaus_debug.h"
|
||||
|
||||
global_variable debug_services* GlobalDebugServices;
|
||||
|
@ -27,7 +27,7 @@ global_variable debug_services* GlobalDebugServices;
|
|||
global_variable platform_alloc* GSAlloc;
|
||||
global_variable platform_free* GSFree;
|
||||
|
||||
#include <gs_vector_matrix.h>
|
||||
#include "C:\programs-dev\gs_libs\src\gs_vector_matrix.h"
|
||||
|
||||
#include "gs_input.h"
|
||||
|
||||
|
|
|
@ -1,111 +1,16 @@
|
|||
enum node_type
|
||||
{
|
||||
NodeType_FloatValue,
|
||||
NodeType_VectorValue,
|
||||
NodeType_MultiplyNodeProc,
|
||||
NodeType_AddNodeProc,
|
||||
NodeType_SinWave,
|
||||
NodeType_MultiplyPatterns,
|
||||
NodeType_OutputNode,
|
||||
NodeType_SolidColorProc,
|
||||
NodeType_VerticalColorFadeProc,
|
||||
NodeType_RevolvingDiscs,
|
||||
NodeType_Count,
|
||||
};
|
||||
|
||||
node_struct_member MemberList_float_value_data[] = {
|
||||
{ MemberType_r32, "Value", (u64)&((float_value_data*)0)->Value, IsInputMember },
|
||||
{ MemberType_r32, "Result", (u64)&((float_value_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_vector_data[] = {
|
||||
{ MemberType_r32, "X", (u64)&((vector_data*)0)->X, IsInputMember },
|
||||
{ MemberType_r32, "Y", (u64)&((vector_data*)0)->Y, IsInputMember },
|
||||
{ MemberType_r32, "Z", (u64)&((vector_data*)0)->Z, IsInputMember },
|
||||
{ MemberType_r32, "W", (u64)&((vector_data*)0)->W, IsInputMember },
|
||||
{ MemberType_v4, "Result", (u64)&((vector_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_multiply_data[] = {
|
||||
{ MemberType_r32, "A", (u64)&((multiply_data*)0)->A, IsInputMember },
|
||||
{ MemberType_r32, "B", (u64)&((multiply_data*)0)->B, IsInputMember },
|
||||
{ MemberType_r32, "Result", (u64)&((multiply_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_add_data[] = {
|
||||
{ MemberType_v4, "A", (u64)&((add_data*)0)->A, IsInputMember },
|
||||
{ MemberType_v4, "B", (u64)&((add_data*)0)->B, IsInputMember },
|
||||
{ MemberType_v4, "Result", (u64)&((add_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_sin_wave_data[] = {
|
||||
{ MemberType_r32, "Period", (u64)&((sin_wave_data*)0)->Period, IsInputMember },
|
||||
{ MemberType_r32, "Min", (u64)&((sin_wave_data*)0)->Min, IsInputMember },
|
||||
{ MemberType_r32, "Max", (u64)&((sin_wave_data*)0)->Max, IsInputMember },
|
||||
{ MemberType_r32, "Result", (u64)&((sin_wave_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_multiply_patterns_data[] = {
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ALEDs", (u64)&((multiply_patterns_data*)0)->ALEDs, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "BLEDs", (u64)&((multiply_patterns_data*)0)->BLEDs, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((multiply_patterns_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_output_node_data[] = {
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((output_node_data*)0)->ResultLEDs, IsInputMember },
|
||||
};
|
||||
|
||||
node_struct_member MemberList_solid_color_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((solid_color_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((solid_color_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_vertical_color_fade_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((vertical_color_fade_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_r32, "Min", (u64)&((vertical_color_fade_data*)0)->Min, IsInputMember },
|
||||
{ MemberType_r32, "Max", (u64)&((vertical_color_fade_data*)0)->Max, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((vertical_color_fade_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_revolving_discs_data[] = {
|
||||
{ MemberType_r32, "Rotation", (u64)&((revolving_discs_data*)0)->Rotation, IsInputMember },
|
||||
{ MemberType_r32, "ThetaZ", (u64)&((revolving_discs_data*)0)->ThetaZ, IsInputMember },
|
||||
{ MemberType_r32, "ThetaY", (u64)&((revolving_discs_data*)0)->ThetaY, IsInputMember },
|
||||
{ MemberType_r32, "DiscWidth", (u64)&((revolving_discs_data*)0)->DiscWidth, IsInputMember },
|
||||
{ MemberType_r32, "InnerRadius", (u64)&((revolving_discs_data*)0)->InnerRadius, IsInputMember },
|
||||
{ MemberType_r32, "OuterRadius", (u64)&((revolving_discs_data*)0)->OuterRadius, IsInputMember },
|
||||
{ MemberType_v4, "Color", (u64)&((revolving_discs_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((revolving_discs_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_specification NodeSpecifications[] = {
|
||||
{ NodeType_FloatValue, "FloatValue", 10, MemberList_float_value_data, 8, 2, false},
|
||||
{ NodeType_VectorValue, "VectorValue", 11, MemberList_vector_data, 32, 5, false},
|
||||
{ NodeType_MultiplyNodeProc, "MultiplyNodeProc", 16, MemberList_multiply_data, 12, 3, false},
|
||||
{ NodeType_AddNodeProc, "AddNodeProc", 11, MemberList_add_data, 48, 3, false},
|
||||
{ NodeType_SinWave, "SinWave", 7, MemberList_sin_wave_data, 20, 4, false},
|
||||
{ NodeType_MultiplyPatterns, "MultiplyPatterns", 16, MemberList_multiply_patterns_data, 60, 3, false},
|
||||
{ NodeType_OutputNode, "OutputNode", 10, MemberList_output_node_data, 20, 1, false},
|
||||
{ NodeType_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 36, 2, false},
|
||||
{ NodeType_VerticalColorFadeProc, "VerticalColorFadeProc", 21, MemberList_vertical_color_fade_data, 44, 4, false},
|
||||
{ NodeType_RevolvingDiscs, "RevolvingDiscs", 14, MemberList_revolving_discs_data, 60, 8, false},
|
||||
};
|
||||
s32 NodeSpecificationsCount = 10;
|
||||
s32 NodeSpecificationsCount = 0;
|
||||
|
||||
internal void CallNodeProc(u32 SpecificationIndex, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)
|
||||
{
|
||||
node_specification Spec = NodeSpecifications[SpecificationIndex];
|
||||
switch (Spec.Type)
|
||||
{
|
||||
case NodeType_FloatValue: { FloatValue((float_value_data*)Data, DeltaTime); } break;
|
||||
case NodeType_VectorValue: { VectorValue((vector_data*)Data, DeltaTime); } break;
|
||||
case NodeType_MultiplyNodeProc: { MultiplyNodeProc((multiply_data*)Data, DeltaTime); } break;
|
||||
case NodeType_AddNodeProc: { AddNodeProc((add_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SinWave: { SinWave((sin_wave_data*)Data, DeltaTime); } break;
|
||||
case NodeType_MultiplyPatterns: { MultiplyPatterns((multiply_patterns_data*)Data, DeltaTime); } break;
|
||||
case NodeType_OutputNode: { OutputNode((output_node_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SolidColorProc: { SolidColorProc((solid_color_data*)Data, DeltaTime); } break;
|
||||
case NodeType_VerticalColorFadeProc: { VerticalColorFadeProc((vertical_color_fade_data*)Data, DeltaTime); } break;
|
||||
case NodeType_RevolvingDiscs: { RevolvingDiscs((revolving_discs_data*)Data, DeltaTime); } break;
|
||||
}
|
||||
}
|
||||
|
|
64
todo.txt
64
todo.txt
|
@ -1,5 +1,69 @@
|
|||
TODO FOLDHAUS
|
||||
|
||||
Ground Up Reengineering
|
||||
- Metaprogramming
|
||||
- refactor for speed
|
||||
- use #include statements to crawl through the codebase
|
||||
- generalize the system
|
||||
- panels metaprogramming
|
||||
|
||||
- Rendering
|
||||
- OpenGL 3
|
||||
- Vertex Buffers
|
||||
- Layers
|
||||
- Lighting
|
||||
- Clipping (with error checking)
|
||||
|
||||
- Asset Loading
|
||||
- images
|
||||
- icon system
|
||||
|
||||
- Sculptures
|
||||
- cache led vertex buffers
|
||||
- custom sculpture update functions (for motion)
|
||||
- placing sculptures
|
||||
- editing sculpture files (change universe output)
|
||||
|
||||
- Network
|
||||
- Artnet
|
||||
- Universe offsets (per sculpture)
|
||||
|
||||
- Interface
|
||||
- Layout functionality
|
||||
- styling
|
||||
- text input
|
||||
- lister with icon options
|
||||
|
||||
- Sculpture View
|
||||
- mouse spatial interaction - handles, and hover for info
|
||||
- debug capabilities (toggle strip/led/universe colors)
|
||||
|
||||
- Animation System
|
||||
- snapping clips
|
||||
- blending between animation
|
||||
- layers
|
||||
- layer masks by sculpture
|
||||
- blend modes
|
||||
|
||||
- Node System
|
||||
- automatic node layout
|
||||
- blending node layouts
|
||||
- workspace -> animation block
|
||||
- generating node workspace as code
|
||||
- compiling node workspace
|
||||
- hotload compiled pattern sets
|
||||
|
||||
- Serialization
|
||||
- saving scenes
|
||||
- saving node graphs
|
||||
- saving animation timelines
|
||||
- saving projects
|
||||
|
||||
- Settings
|
||||
|
||||
- Platform Layer
|
||||
- Mac Platform Layer
|
||||
|
||||
Reimplement Node View
|
||||
- probably want to take a fresh pass at nodes all together
|
||||
|
||||
|
|
Loading…
Reference in New Issue