mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 15:02:01 +00:00
- create class types from the AST.
This is the first thing the compiler has to do to get access to the class's symbol table. Of course at this point the final size of a class is not known yet so these are currently all treated as tentative.
This commit is contained in:
parent
fff428c71d
commit
b71e8d09ed
5 changed files with 149 additions and 6 deletions
|
@ -175,6 +175,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
|
|||
head->ParentName = B;
|
||||
head->Flags = C.Flags;
|
||||
head->Replaces = C.Replaces;
|
||||
head->Type = nullptr;
|
||||
X = head;
|
||||
}
|
||||
|
||||
|
@ -184,8 +185,8 @@ class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ }
|
|||
|
||||
%type class_flags{ClassFlagsBlock}
|
||||
class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; }
|
||||
class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | 0/*FIXME*/; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | 0/*FIXME*/; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; }
|
||||
|
||||
/*----- Dottable Identifier -----*/
|
||||
|
|
|
@ -181,10 +181,128 @@ void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char
|
|||
|
||||
int ZCCCompiler::Compile()
|
||||
{
|
||||
CreateClasses();
|
||||
CompileConstants(Constants);
|
||||
return ErrorCount;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: CreateClassTypes
|
||||
//
|
||||
// Creates a PClass for every class so that we get access to the symbol table
|
||||
// These will be created with unknown size because for that we need to
|
||||
// process all fields first, but to do that we need the PClass and some
|
||||
// other info depending on the PClass.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ZCCCompiler::CreateClasses()
|
||||
{
|
||||
auto OrigClasses = std::move(Classes);
|
||||
Classes.Clear();
|
||||
bool donesomething = true;
|
||||
while (donesomething)
|
||||
{
|
||||
for (unsigned i=0;i<OrigClasses.Size();i++)
|
||||
{
|
||||
donesomething = false;
|
||||
auto c = OrigClasses[i];
|
||||
// Check if we got the parent already defined.
|
||||
PClass *parent;
|
||||
|
||||
if (c->ParentName != nullptr && c->ParentName->SiblingNext == c->ParentName) parent = PClass::FindClass(c->ParentName->Id);
|
||||
else if (c->ParentName == nullptr) parent = RUNTIME_CLASS(DObject);
|
||||
else
|
||||
{
|
||||
// The parent is a dotted name which the type system currently does not handle.
|
||||
// Once it does this needs to be implemented here.
|
||||
auto p = c->ParentName;
|
||||
FString build;
|
||||
|
||||
do
|
||||
{
|
||||
if (build.IsNotEmpty()) build += '.';
|
||||
build += FName(p->Id);
|
||||
p = static_cast<decltype(p)>(p->SiblingNext);
|
||||
} while (p != c->ParentName);
|
||||
Error(c, "Qualified name '%s' for base class not supported in '%s'", build.GetChars(), FName(c->NodeName).GetChars());
|
||||
parent = RUNTIME_CLASS(DObject);
|
||||
}
|
||||
|
||||
if (parent != nullptr)
|
||||
{
|
||||
// The parent exists, we may create a type for this class
|
||||
if (c->Flags & ZCC_Native)
|
||||
{
|
||||
// If this is a native class, its own type must also already exist.
|
||||
auto me = PClass::FindClass(c->NodeName);
|
||||
if (me == nullptr)
|
||||
{
|
||||
Error(c, "Unknown native class %s", FName(c->NodeName).GetChars());
|
||||
me = parent->FindClassTentative(c->NodeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars());
|
||||
}
|
||||
c->Type = me;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto me = PClass::FindClass(c->NodeName);
|
||||
if (me != nullptr)
|
||||
{
|
||||
Error(c, "Redefining class %s", FName(c->NodeName).GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
me = parent->FindClassTentative(c->NodeName);
|
||||
DPrintf(DMSG_SPAMMY, "Created %s with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars());
|
||||
}
|
||||
c->Type = me;
|
||||
}
|
||||
Classes.Push(c);
|
||||
OrigClasses.Delete(i);
|
||||
i--;
|
||||
donesomething = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No base class found. Now check if something in the unprocessed classes matches.
|
||||
// If not, print an error. If something is found let's retry again in the next iteration.
|
||||
bool found = false;
|
||||
for (auto d : OrigClasses)
|
||||
{
|
||||
if (d->NodeName == c->ParentName->Id)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
Error(c, "Class %s has unknown base class %s", FName(c->NodeName).GetChars(), FName(c->ParentName->Id).GetChars());
|
||||
// create a placeholder so that the compiler can continue looking for errors.
|
||||
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName);
|
||||
Classes.Push(c);
|
||||
OrigClasses.Delete(i);
|
||||
donesomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// What's left refers to some other class in the list but could not be resolved.
|
||||
// This normally means a circular reference.
|
||||
for (auto c : OrigClasses)
|
||||
{
|
||||
Error(c, "Class %s has circular inheritance", FName(c->NodeName).GetChars());
|
||||
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName);
|
||||
Classes.Push(c);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: CompileConstants
|
||||
|
|
|
@ -8,6 +8,7 @@ public:
|
|||
int Compile();
|
||||
|
||||
private:
|
||||
void CreateClasses();
|
||||
void CompileConstants(const TArray<ZCC_ConstantDef *> &defs);
|
||||
PSymbolConst *CompileConstant(ZCC_ConstantDef *def);
|
||||
|
||||
|
|
|
@ -318,8 +318,8 @@ static void DoParse(int lumpnum)
|
|||
ZCCParse(parser, 0, value, &state);
|
||||
ZCCParseFree(parser, free);
|
||||
|
||||
ZCCCompiler cc(state, NULL, GlobalSymbols);
|
||||
cc.Compile();
|
||||
{
|
||||
// Make a dump of the AST before running the compiler for diagnostic purposes.
|
||||
#ifdef _DEBUG
|
||||
if (f != NULL)
|
||||
{
|
||||
|
@ -328,7 +328,28 @@ static void DoParse(int lumpnum)
|
|||
FString ast = ZCC_PrintAST(state.TopNode);
|
||||
FString filename = Wads.GetLumpFullName(lumpnum);
|
||||
FString astfile = ExtractFileBase(filename, false);
|
||||
astfile << ".ast";
|
||||
astfile << "-before.ast";
|
||||
f = fopen(astfile, "w");
|
||||
if (f != NULL)
|
||||
{
|
||||
fputs(ast.GetChars(), f);
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ZCCCompiler cc(state, NULL, GlobalSymbols);
|
||||
cc.Compile();
|
||||
// ... and another one afterward so we can see what the compiler does with the data.
|
||||
#ifdef _DEBUG
|
||||
if (f != NULL)
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
FString ast = ZCC_PrintAST(state.TopNode);
|
||||
FString filename = Wads.GetLumpFullName(lumpnum);
|
||||
FString astfile = ExtractFileBase(filename, false);
|
||||
astfile << "-after.ast";
|
||||
f = fopen(astfile, "w");
|
||||
if (f != NULL)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ struct ZCCToken
|
|||
ENamedName Name() { return ENamedName(Int); }
|
||||
};
|
||||
|
||||
// Variable / Function modifiers
|
||||
// Variable / Function / Class modifiers
|
||||
enum
|
||||
{
|
||||
ZCC_Native = 1 << 0,
|
||||
|
@ -30,6 +30,7 @@ enum
|
|||
ZCC_Deprecated = 1 << 8,
|
||||
ZCC_ReadOnly = 1 << 9,
|
||||
ZCC_FuncConst = 1 << 10,
|
||||
ZCC_Abstract = 1 << 11,
|
||||
};
|
||||
|
||||
// Function parameter modifiers
|
||||
|
@ -185,6 +186,7 @@ struct ZCC_Class : ZCC_NamedNode
|
|||
ZCC_Identifier *Replaces;
|
||||
VM_UWORD Flags;
|
||||
ZCC_TreeNode *Body;
|
||||
PClass *Type;
|
||||
};
|
||||
|
||||
struct ZCC_Struct : ZCC_NamedNode
|
||||
|
|
Loading…
Reference in a new issue