mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- 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:
parent
4ecd7dd13a
commit
e84d6a06d8
4 changed files with 156 additions and 121 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue