- changed PClass:AddField so that it doesn't create defaults if none are present. The ZScript compiler will not create any defaults until after all fields have been added and this function created bad data if it was run on a class without defaults.

- added checks for duplicate field names.
- moved the tree node symbol tables out of PSymbolTreeNode to the worker data. That symbol is a bad location because it restricts the usefulness of the symbol class which is also needed for variables which use different AST structs.
- fixed some memory management issues with the work classes for the compiler that became apparent after moving the symbol tables in there. In several places these were copied around, possibly losing data.
This commit is contained in:
Christoph Oelckers 2016-10-10 01:18:47 +02:00
parent 4ecd7dd13a
commit e84d6a06d8
4 changed files with 156 additions and 121 deletions

View file

@ -1325,7 +1325,7 @@ bool PString::ReadValue(FSerializer &ar, const char *key, void *addr) const
void PString::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const void PString::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{ {
new((BYTE *)base + offset) FString; if (base != nullptr) new((BYTE *)base + offset) FString;
if (special != NULL) if (special != NULL)
{ {
special->Push(std::make_pair(this, offset)); special->Push(std::make_pair(this, offset));
@ -1340,7 +1340,14 @@ void PString::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset
void PString::InitializeValue(void *addr, const void *def) const void PString::InitializeValue(void *addr, const void *def) const
{ {
new(addr) FString(*(FString *)def); if (def != nullptr)
{
new(addr) FString(*(FString *)def);
}
else
{
new(addr) FString;
}
} }
//========================================================================== //==========================================================================
@ -2982,7 +2989,7 @@ void PClass::InitializeSpecials(void *addr) const
ParentClass->InitializeSpecials(addr); ParentClass->InitializeSpecials(addr);
for (auto tao : SpecialInits) for (auto tao : SpecialInits)
{ {
tao.first->InitializeValue((BYTE*)addr + tao.second, Defaults + tao.second); tao.first->InitializeValue((BYTE*)addr + tao.second, Defaults == nullptr? nullptr : Defaults + tao.second);
} }
} }
@ -3113,15 +3120,15 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
{ {
unsigned oldsize = Size; unsigned oldsize = Size;
PField *field = Super::AddField(name, type, flags); PField *field = Super::AddField(name, type, flags);
if (field != NULL)
// Only initialize the defaults if they have already been created.
// For ZScript this is not the case, it will first define all fields before
// setting up any defaults for any class.
if (field != nullptr && !(flags & VARF_Native) && Defaults != nullptr)
{ {
Defaults = (BYTE *)M_Realloc(Defaults, Size); Defaults = (BYTE *)M_Realloc(Defaults, Size);
memset(Defaults + oldsize, 0, Size - oldsize); memset(Defaults + oldsize, 0, Size - oldsize);
// If this is a native class, then we must not initialize and type->SetDefaultValue(Defaults, field->Offset, &SpecialInits);
// destroy any of its members. We do, however, initialize the
// default instance since it's not a normal instance of the class.
type->SetDefaultValue(Defaults, field->Offset,
bRuntimeClass ? &SpecialInits : NULL);
} }
return field; return field;
} }

View file

@ -155,10 +155,9 @@ class PSymbolTreeNode : public PSymbol
{ {
DECLARE_CLASS(PSymbolTreeNode, PSymbol); DECLARE_CLASS(PSymbolTreeNode, PSymbol);
public: public:
struct ZCC_NamedNode *Node; struct ZCC_TreeNode *Node;
PSymbolTable TreeNodes;
PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {} PSymbolTreeNode(FName name, struct ZCC_TreeNode *node) : PSymbol(name), Node(node) {}
PSymbolTreeNode() : PSymbol(NAME_None) {} PSymbolTreeNode() : PSymbol(NAME_None) {}
}; };

View file

@ -55,13 +55,18 @@
void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
{ {
Classes.Push(ZCC_ClassWork(static_cast<ZCC_Class *>(cnode), treenode)); Classes.Push(new ZCC_ClassWork(static_cast<ZCC_Class *>(cnode), treenode));
ZCC_ClassWork &cls = Classes.Last(); auto cls = Classes.Last();
auto node = cnode->Body; auto node = cnode->Body;
PSymbolTreeNode *childnode; PSymbolTreeNode *childnode;
ZCC_Enum *enumType = nullptr; ZCC_Enum *enumType = nullptr;
FString name;
name << "nodes - " << FName(cnode->NodeName);
cls->TreeNodes.SetName(name);
// Need to check if the class actually has a body. // Need to check if the class actually has a body.
if (node != nullptr) do if (node != nullptr) do
{ {
@ -70,22 +75,22 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
case AST_Struct: case AST_Struct:
case AST_ConstantDef: case AST_ConstantDef:
case AST_Enum: case AST_Enum:
if ((childnode = AddNamedNode(static_cast<ZCC_NamedNode *>(node), &treenode->TreeNodes))) if ((childnode = AddTreeNode(static_cast<ZCC_NamedNode *>(node)->NodeName, node, &cls->TreeNodes)))
{ {
switch (node->NodeType) switch (node->NodeType)
{ {
case AST_Enum: case AST_Enum:
enumType = static_cast<ZCC_Enum *>(node); enumType = static_cast<ZCC_Enum *>(node);
cls.Enums.Push(enumType); cls->Enums.Push(enumType);
break; break;
case AST_Struct: case AST_Struct:
ProcessStruct(static_cast<ZCC_Struct *>(node), childnode, cls.cls); ProcessStruct(static_cast<ZCC_Struct *>(node), childnode, cls->cls);
break; break;
case AST_ConstantDef: case AST_ConstantDef:
cls.Constants.Push(static_cast<ZCC_ConstantDef *>(node)); cls->Constants.Push(static_cast<ZCC_ConstantDef *>(node));
cls.Constants.Last()->Type = enumType; cls->Constants.Last()->Type = enumType;
break; break;
default: default:
@ -95,7 +100,7 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
break; break;
case AST_VarDeclarator: case AST_VarDeclarator:
cls.Fields.Push(static_cast<ZCC_VarDeclarator *>(node)); cls->Fields.Push(static_cast<ZCC_VarDeclarator *>(node));
break; break;
case AST_EnumTerminator: case AST_EnumTerminator:
@ -125,8 +130,8 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer) void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer)
{ {
Structs.Push(ZCC_StructWork(static_cast<ZCC_Struct *>(cnode), treenode, outer)); Structs.Push(new ZCC_StructWork(static_cast<ZCC_Struct *>(cnode), treenode, outer));
ZCC_StructWork &cls = Structs.Last(); ZCC_StructWork *cls = Structs.Last();
auto node = cnode->Body; auto node = cnode->Body;
PSymbolTreeNode *childnode; PSymbolTreeNode *childnode;
@ -139,18 +144,18 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC
{ {
case AST_ConstantDef: case AST_ConstantDef:
case AST_Enum: case AST_Enum:
if ((childnode = AddNamedNode(static_cast<ZCC_NamedNode *>(node), &treenode->TreeNodes))) if ((childnode = AddTreeNode(static_cast<ZCC_NamedNode *>(node)->NodeName, node, &cls->TreeNodes)))
{ {
switch (node->NodeType) switch (node->NodeType)
{ {
case AST_Enum: case AST_Enum:
enumType = static_cast<ZCC_Enum *>(node); enumType = static_cast<ZCC_Enum *>(node);
cls.Enums.Push(enumType); cls->Enums.Push(enumType);
break; break;
case AST_ConstantDef: case AST_ConstantDef:
cls.Constants.Push(static_cast<ZCC_ConstantDef *>(node)); cls->Constants.Push(static_cast<ZCC_ConstantDef *>(node));
cls.Constants.Last()->Type = enumType; cls->Constants.Last()->Type = enumType;
break; break;
default: default:
@ -160,7 +165,7 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC
break; break;
case AST_VarDeclarator: case AST_VarDeclarator:
cls.Fields.Push(static_cast<ZCC_VarDeclarator *>(node)); cls->Fields.Push(static_cast<ZCC_VarDeclarator *>(node));
break; break;
case AST_EnumTerminator: case AST_EnumTerminator:
@ -201,7 +206,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
case AST_Struct: case AST_Struct:
case AST_ConstantDef: case AST_ConstantDef:
case AST_Enum: case AST_Enum:
if ((tnode = AddNamedNode(static_cast<ZCC_NamedNode *>(node), GlobalTreeNodes))) if ((tnode = AddTreeNode(static_cast<ZCC_NamedNode *>(node)->NodeName, node, GlobalTreeNodes)))
{ {
switch (node->NodeType) switch (node->NodeType)
{ {
@ -243,19 +248,32 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
} }
} }
ZCCCompiler::~ZCCCompiler()
{
for (auto s : Structs)
{
delete s;
}
for (auto c : Classes)
{
delete c;
}
Structs.Clear();
Classes.Clear();
}
//========================================================================== //==========================================================================
// //
// ZCCCompiler :: AddNamedNode // ZCCCompiler :: AddTreeNode
// //
// Keeps track of definition nodes by their names. Ensures that all names // Keeps track of definition nodes by their names. Ensures that all names
// in this scope are unique. // in this scope are unique.
// //
//========================================================================== //==========================================================================
PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *treenodes) PSymbolTreeNode *ZCCCompiler::AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents)
{ {
FName name = node->NodeName; PSymbol *check = treenodes->FindSymbol(name, searchparents);
PSymbol *check = treenodes->FindSymbol(name, false);
if (check != NULL) if (check != NULL)
{ {
assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode))); assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode)));
@ -267,8 +285,6 @@ PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *tr
{ {
auto sy = new PSymbolTreeNode(name, node); auto sy = new PSymbolTreeNode(name, node);
FString name; FString name;
name << "nodes - " << FName(node->NodeName);
sy->TreeNodes.SetName(name);
treenodes->AddSymbol(sy); treenodes->AddSymbol(sy);
return sy; return sy;
} }
@ -357,16 +373,16 @@ void ZCCCompiler::CreateStructTypes()
{ {
for(auto s : Structs) for(auto s : Structs)
{ {
s.Outer = s.OuterDef == nullptr? nullptr : s.OuterDef->Type; s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->Type;
s->Type = NewStruct(s->NodeName, s.Outer); s->strct->Type = NewStruct(s->NodeName(), s->Outer);
s->Symbol = new PSymbolType(s->NodeName, s->Type); s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type());
s->Type->Symbols.SetName(FName(s->NodeName)); s->Type()->Symbols.SetName(FName(s->NodeName()));
GlobalSymbols.AddSymbol(s->Symbol); GlobalSymbols.AddSymbol(s->strct->Symbol);
for (auto e : s.Enums) for (auto e : s->Enums)
{ {
auto etype = NewEnum(e->NodeName, s->Type); auto etype = NewEnum(e->NodeName, s->Type());
s->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); s->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype));
} }
} }
} }
@ -384,6 +400,8 @@ void ZCCCompiler::CreateStructTypes()
void ZCCCompiler::CreateClassTypes() void ZCCCompiler::CreateClassTypes()
{ {
// we are going to sort the classes array so that entries are sorted in order of inheritance.
auto OrigClasses = std::move(Classes); auto OrigClasses = std::move(Classes);
Classes.Clear(); Classes.Clear();
bool donesomething = true; bool donesomething = true;
@ -395,14 +413,15 @@ void ZCCCompiler::CreateClassTypes()
auto c = OrigClasses[i]; auto c = OrigClasses[i];
// Check if we got the parent already defined. // Check if we got the parent already defined.
PClass *parent; PClass *parent;
auto ParentName = c->cls->ParentName;
if (c->ParentName != nullptr && c->ParentName->SiblingNext == c->ParentName) parent = PClass::FindClass(c->ParentName->Id); if (ParentName != nullptr && ParentName->SiblingNext == ParentName) parent = PClass::FindClass(ParentName->Id);
else if (c->ParentName == nullptr) parent = RUNTIME_CLASS(DObject); else if (ParentName == nullptr) parent = RUNTIME_CLASS(DObject);
else else
{ {
// The parent is a dotted name which the type system currently does not handle. // The parent is a dotted name which the type system currently does not handle.
// Once it does this needs to be implemented here. // Once it does this needs to be implemented here.
auto p = c->ParentName; auto p = ParentName;
FString build; FString build;
do do
@ -410,44 +429,43 @@ void ZCCCompiler::CreateClassTypes()
if (build.IsNotEmpty()) build += '.'; if (build.IsNotEmpty()) build += '.';
build += FName(p->Id); build += FName(p->Id);
p = static_cast<decltype(p)>(p->SiblingNext); p = static_cast<decltype(p)>(p->SiblingNext);
} while (p != c->ParentName); } while (p != ParentName);
Error(c, "Qualified name '%s' for base class not supported in '%s'", build.GetChars(), FName(c->NodeName).GetChars()); Error(c->cls, "Qualified name '%s' for base class not supported in '%s'", build.GetChars(), FName(c->NodeName()).GetChars());
parent = RUNTIME_CLASS(DObject); parent = RUNTIME_CLASS(DObject);
} }
if (parent != nullptr) if (parent != nullptr)
{ {
// The parent exists, we may create a type for this class // The parent exists, we may create a type for this class
if (c->Flags & ZCC_Native) if (c->cls->Flags & ZCC_Native)
{ {
// If this is a native class, its own type must also already exist and not be a runtime class. // If this is a native class, its own type must also already exist and not be a runtime class.
auto me = PClass::FindClass(c->NodeName); auto me = PClass::FindClass(c->NodeName());
if (me == nullptr) if (me == nullptr)
{ {
Error(c, "Unknown native class %s", FName(c->NodeName).GetChars()); Error(c->cls, "Unknown native class %s", c->NodeName().GetChars());
me = parent->FindClassTentative(c->NodeName); me = parent->FindClassTentative(c->NodeName());
} }
else if (me->bRuntimeClass) else if (me->bRuntimeClass)
{ {
Error(c, "%s is not a native class", FName(c->NodeName).GetChars()); Error(c->cls, "%s is not a native class", c->NodeName().GetChars());
} }
else else
{ {
DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars());
} }
c->Type = me; c->cls->Type = me;
} }
else else
{ {
// We will never get here if the name is a duplicate, so we can just do the assignment. // We will never get here if the name is a duplicate, so we can just do the assignment.
c->Type = parent->FindClassTentative(c->NodeName); c->cls->Type = parent->FindClassTentative(c->NodeName());
} }
c->Symbol = new PSymbolType(c->NodeName, c->Type); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->Symbol); GlobalSymbols.AddSymbol(c->cls->Symbol);
c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); c->Type()->Symbols.SetName(c->NodeName());
Classes.Push(c); Classes.Push(c);
OrigClasses.Delete(i); OrigClasses.Delete(i--);
i--;
donesomething = true; donesomething = true;
} }
else else
@ -457,7 +475,7 @@ void ZCCCompiler::CreateClassTypes()
bool found = false; bool found = false;
for (auto d : OrigClasses) for (auto d : OrigClasses)
{ {
if (d->NodeName == c->ParentName->Id) if (d->NodeName() == c->cls->ParentName->Id)
{ {
found = true; found = true;
break; break;
@ -465,14 +483,14 @@ void ZCCCompiler::CreateClassTypes()
} }
if (!found) if (!found)
{ {
Error(c, "Class %s has unknown base class %s", FName(c->NodeName).GetChars(), FName(c->ParentName->Id).GetChars()); Error(c->cls, "Class %s has unknown base class %s", c->NodeName().GetChars(), FName(c->cls->ParentName->Id).GetChars());
// create a placeholder so that the compiler can continue looking for errors. // create a placeholder so that the compiler can continue looking for errors.
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName());
c->Symbol = new PSymbolType(c->NodeName, c->Type); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->Symbol); GlobalSymbols.AddSymbol(c->cls->Symbol);
c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); c->Type()->Symbols.SetName(c->NodeName());
Classes.Push(c); Classes.Push(c);
OrigClasses.Delete(i); OrigClasses.Delete(i--);
donesomething = true; donesomething = true;
} }
} }
@ -483,21 +501,30 @@ void ZCCCompiler::CreateClassTypes()
// This normally means a circular reference. // This normally means a circular reference.
for (auto c : OrigClasses) for (auto c : OrigClasses)
{ {
Error(c, "Class %s has circular inheritance", FName(c->NodeName).GetChars()); Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars());
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName); c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName());
c->Symbol = new PSymbolType(c->NodeName, c->Type); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
c->Type->Symbols.SetName(FName(c->NodeName).GetChars()); c->Type()->Symbols.SetName(FName(c->NodeName()).GetChars());
GlobalSymbols.AddSymbol(c->Symbol); GlobalSymbols.AddSymbol(c->cls->Symbol);
Classes.Push(c); Classes.Push(c);
} }
// Last but not least: Now that all classes have been created, we can create the symbols for the internal enums // Last but not least: Now that all classes have been created, we can create the symbols for the internal enums and link the treenode symbol tables
for (auto cd : Classes) for (auto cd : Classes)
{ {
for (auto e : cd.Enums) for (auto e : cd->Enums)
{ {
auto etype = NewEnum(e->NodeName, cd->Type); auto etype = NewEnum(e->NodeName, cd->Type());
cd->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); cd->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype));
}
// Link the tree node tables. We only can do this after we know the class relations.
for (auto cc : Classes)
{
if (cc->Type() == cd->Type()->ParentClass)
{
cd->TreeNodes.SetParentTable(&cc->TreeNodes);
break;
}
} }
} }
} }
@ -534,13 +561,13 @@ void ZCCCompiler::CompileAllConstants()
TArray<ZCC_ConstantWork> constantwork; TArray<ZCC_ConstantWork> constantwork;
CopyConstants(constantwork, Constants, OutputSymbols); CopyConstants(constantwork, Constants, OutputSymbols);
for (auto &c : Classes) for (auto c : Classes)
{ {
CopyConstants(constantwork, c.Constants, &c->Type->Symbols); CopyConstants(constantwork, c->Constants, &c->Type()->Symbols);
} }
for (auto &s : Structs) for (auto s : Structs)
{ {
CopyConstants(constantwork, s.Constants, &s->Type->Symbols); CopyConstants(constantwork, s->Constants, &s->Type()->Symbols);
} }
// Before starting to resolve the list, let's create symbols for all already resolved ones first (i.e. all literal constants), to reduce work. // Before starting to resolve the list, let's create symbols for all already resolved ones first (i.e. all literal constants), to reduce work.
@ -1070,16 +1097,15 @@ void ZCCCompiler::CompileAllFields()
{ {
auto c = Classes[i]; auto c = Classes[i];
if (c->Type->Size != TentativeClass && c.Fields.Size() > 0) if (c->Type()->Size != TentativeClass && c->Fields.Size() > 0)
{ {
// We need to search the global class table here because not all children may have a scripted definition attached. // We need to search the global class table here because not all children may have a scripted definition attached.
for (auto ac : PClass::AllClasses) for (auto ac : PClass::AllClasses)
{ {
if (ac->ParentClass == c->Type && ac->Size != TentativeClass) if (ac->ParentClass == c->Type() && ac->Size != TentativeClass)
{ {
Error(c, "Trying to add fields to class '%s' with native children", c->Type->TypeName.GetChars()); Error(c->cls, "Trying to add fields to class '%s' with native children", c->Type()->TypeName.GetChars());
Classes.Delete(i); Classes.Delete(i--);
i--;
break; break;
} }
} }
@ -1091,19 +1117,19 @@ void ZCCCompiler::CompileAllFields()
donesomething = false; donesomething = false;
for (unsigned i = 0; i < Structs.Size(); i++) for (unsigned i = 0; i < Structs.Size(); i++)
{ {
if (CompileFields(Structs[i]->Type, Structs[i].Fields, Structs[i].Outer, true)) if (CompileFields(Structs[i]->Type(), Structs[i]->Fields, Structs[i]->Outer, &Structs[i]->TreeNodes, true))
{ {
// Remove from the list if all fields got compiled. // Remove from the list if all fields got compiled.
Structs.Delete(i); Structs.Delete(i--);
i--;
donesomething = true; donesomething = true;
} }
} }
for (unsigned i = 0; i < Classes.Size(); i++) for (unsigned i = 0; i < Classes.Size(); i++)
{ {
if (Classes[i]->Type->Size == TentativeClass) auto type = Classes[i]->Type();
if (type->Size == TentativeClass)
{ {
if (Classes[i]->Type->ParentClass->Size == TentativeClass) if (type->ParentClass->Size == TentativeClass)
{ {
// we do not know the parent class's size yet, so skip this class for now. // we do not know the parent class's size yet, so skip this class for now.
continue; continue;
@ -1111,14 +1137,13 @@ void ZCCCompiler::CompileAllFields()
else else
{ {
// Inherit the size of the parent class // Inherit the size of the parent class
Classes[i]->Type->Size = Classes[i]->Type->ParentClass->Size; type->Size = Classes[i]->Type()->ParentClass->Size;
} }
} }
if (CompileFields(Classes[i]->Type, Classes[i].Fields, nullptr, false)) if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false))
{ {
// Remove from the list if all fields got compiled. // Remove from the list if all fields got compiled.
Classes.Delete(i); Classes.Delete(i--);
i--;
donesomething = true; donesomething = true;
} }
} }
@ -1126,11 +1151,11 @@ void ZCCCompiler::CompileAllFields()
// This really should never happen, but if it does, let's better print an error. // This really should never happen, but if it does, let's better print an error.
for (auto s : Structs) for (auto s : Structs)
{ {
Error(s.strct, "Unable to resolve all fields for struct %s", FName(s->NodeName).GetChars()); Error(s->strct, "Unable to resolve all fields for struct %s", FName(s->NodeName()).GetChars());
} }
for (auto s : Classes) for (auto s : Classes)
{ {
Error(s.cls, "Unable to resolve all fields for class %s", FName(s->NodeName).GetChars()); Error(s->cls, "Unable to resolve all fields for class %s", FName(s->NodeName()).GetChars());
} }
} }
@ -1142,7 +1167,7 @@ void ZCCCompiler::CompileAllFields()
// //
//========================================================================== //==========================================================================
bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, bool forstruct) bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct)
{ {
while (Fields.Size() > 0) while (Fields.Size() > 0)
{ {
@ -1158,7 +1183,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed)); Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed));
field->Flags &= notallowed; field->Flags &= notallowed;
} }
uint32_t varflags; uint32_t varflags = 0;
// These map directly to implementation flags. // These map directly to implementation flags.
if (field->Flags & ZCC_Private) varflags |= VARF_Private; if (field->Flags & ZCC_Private) varflags |= VARF_Private;
@ -1184,13 +1209,16 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
auto name = field->Names; auto name = field->Names;
do do
{ {
auto thisfieldtype = fieldtype; if (AddTreeNode(name->Name, name, TreeNodes, !forstruct))
if (name->ArraySize != nullptr)
{ {
thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); auto thisfieldtype = fieldtype;
} if (name->ArraySize != nullptr)
{
thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols);
}
type->AddField(name->Name, thisfieldtype, varflags); type->AddField(name->Name, thisfieldtype, varflags);
}
name = static_cast<ZCC_VarName*>(name->SiblingNext); name = static_cast<ZCC_VarName*>(name->SiblingNext);
} while (name != field->Names); } while (name != field->Names);
Fields.Delete(0); Fields.Delete(0);

View file

@ -3,6 +3,7 @@
struct ZCC_StructWork struct ZCC_StructWork
{ {
PSymbolTable TreeNodes;
ZCC_Struct *strct; ZCC_Struct *strct;
ZCC_Class *OuterDef; ZCC_Class *OuterDef;
PClass *Outer; PClass *Outer;
@ -19,22 +20,22 @@ struct ZCC_StructWork
Outer = nullptr; Outer = nullptr;
}; };
ZCC_Struct *operator->() FName NodeName() const
{ {
return strct; return strct->NodeName;
} }
operator ZCC_Struct *() PStruct *Type()
{ {
return strct; return strct->Type;
} }
}; };
struct ZCC_ClassWork struct ZCC_ClassWork
{ {
ZCC_Class *cls; ZCC_Class *cls;
PSymbolTable TreeNodes;
PSymbolTreeNode *node; PSymbolTreeNode *node;
TArray<ZCC_Enum *> Enums; TArray<ZCC_Enum *> Enums;
TArray<ZCC_ConstantDef *> Constants; TArray<ZCC_ConstantDef *> Constants;
@ -44,16 +45,16 @@ struct ZCC_ClassWork
{ {
cls = s; cls = s;
node = n; node = n;
};
ZCC_Class *operator->()
{
return cls;
} }
operator ZCC_Class *() FName NodeName() const
{ {
return cls; return cls->NodeName;
}
PClass *Type()
{
return cls->Type;
} }
}; };
@ -68,6 +69,7 @@ class ZCCCompiler
{ {
public: public:
ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols); ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols);
~ZCCCompiler();
int Compile(); int Compile();
private: private:
@ -78,21 +80,20 @@ private:
void CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PSymbolTable *ot); void CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PSymbolTable *ot);
void CompileAllConstants(); void CompileAllConstants();
void AddConstant(ZCC_ConstantWork &constant); void AddConstant(ZCC_ConstantWork &constant);
int CompileConstants(const TArray<ZCC_ConstantDef *> &defs, PSymbolTable *Output);
bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols);
void CompileAllFields(); void CompileAllFields();
bool CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, bool forstruct); bool CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct);
FString FlagsToString(uint32_t flags); FString FlagsToString(uint32_t flags);
PType *DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes); PType *DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes);
PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym);
PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym);
TArray<ZCC_ConstantDef *> Constants; TArray<ZCC_ConstantDef *> Constants;
TArray<ZCC_StructWork> Structs; TArray<ZCC_StructWork *> Structs;
TArray<ZCC_ClassWork> Classes; TArray<ZCC_ClassWork *> Classes;
PSymbolTreeNode *AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym = nullptr); PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false);
ZCC_Expression *Simplify(ZCC_Expression *root, PSymbolTable *Symbols); ZCC_Expression *Simplify(ZCC_Expression *root, PSymbolTable *Symbols);
ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *Symbols); ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *Symbols);