mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-04-25 00:41:15 +00:00
- implemented complete resolving of constants - both global and class-local.
This uses a different algorithm as the old implementation - instead of recursively resolving unknown symbols it will first collect all constants from all scopes and then process them in one operation, doing multiple passes over the list until no more constants can be resolved anymore.
This commit is contained in:
parent
5bb6bb31ca
commit
08f313d011
9 changed files with 252 additions and 136 deletions
|
@ -2647,6 +2647,16 @@ void PClass::StaticInit ()
|
||||||
// Keep built-in classes in consistant order. I did this before, though
|
// Keep built-in classes in consistant order. I did this before, though
|
||||||
// I'm not sure if this is really necessary to maintain any sort of sync.
|
// I'm not sure if this is really necessary to maintain any sort of sync.
|
||||||
qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp);
|
qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp);
|
||||||
|
|
||||||
|
// Set all symbol table relations here so that they are valid right from the start.
|
||||||
|
for (auto c : AllClasses)
|
||||||
|
{
|
||||||
|
if (c->ParentClass != nullptr)
|
||||||
|
{
|
||||||
|
c->Symbols.SetParentTable(&c->ParentClass->Symbols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3131,6 +3141,7 @@ PClass *PClass::FindClassTentative(FName name, bool fatal)
|
||||||
type->ParentClass = this;
|
type->ParentClass = this;
|
||||||
type->Size = TentativeClass;
|
type->Size = TentativeClass;
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
|
type->Symbols.SetParentTable(&Symbols);
|
||||||
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,10 @@ struct PSymbolTable
|
||||||
// Sets the table to use for searches if this one doesn't contain the
|
// Sets the table to use for searches if this one doesn't contain the
|
||||||
// requested symbol.
|
// requested symbol.
|
||||||
void SetParentTable (PSymbolTable *parent);
|
void SetParentTable (PSymbolTable *parent);
|
||||||
|
PSymbolTable *GetParentTable() const
|
||||||
|
{
|
||||||
|
return ParentSymbolTable;
|
||||||
|
}
|
||||||
|
|
||||||
// Finds a symbol in the table, optionally searching parent tables
|
// Finds a symbol in the table, optionally searching parent tables
|
||||||
// as well.
|
// as well.
|
||||||
|
@ -108,6 +112,7 @@ struct PSymbolTable
|
||||||
// specific symbol table the symbol was found in.
|
// specific symbol table the symbol was found in.
|
||||||
PSymbol *FindSymbolInTable(FName symname, PSymbolTable *&symtable);
|
PSymbol *FindSymbolInTable(FName symname, PSymbolTable *&symtable);
|
||||||
|
|
||||||
|
|
||||||
// Places the symbol in the table and returns a pointer to it or NULL if
|
// Places the symbol in the table and returns a pointer to it or NULL if
|
||||||
// a symbol with the same name is already in the table. This symbol is
|
// a symbol with the same name is already in the table. This symbol is
|
||||||
// not copied and will be freed when the symbol table is destroyed.
|
// not copied and will be freed when the symbol table is destroyed.
|
||||||
|
@ -120,6 +125,15 @@ struct PSymbolTable
|
||||||
// Frees all symbols from this table.
|
// Frees all symbols from this table.
|
||||||
void ReleaseSymbols();
|
void ReleaseSymbols();
|
||||||
|
|
||||||
|
// add a name to help debugging.
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FString name;
|
||||||
|
void SetName(const char *nm) { name = nm; }
|
||||||
|
#else
|
||||||
|
void SetName(const char *) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef TMap<FName, PSymbol *> MapType;
|
typedef TMap<FName, PSymbol *> MapType;
|
||||||
|
|
||||||
|
@ -702,6 +716,7 @@ protected:
|
||||||
TArray<FTypeAndOffset> SpecialInits;
|
TArray<FTypeAndOffset> SpecialInits;
|
||||||
virtual void Derive(PClass *newclass);
|
virtual void Derive(PClass *newclass);
|
||||||
void InitializeSpecials(void *addr) const;
|
void InitializeSpecials(void *addr) const;
|
||||||
|
void SetSuper();
|
||||||
public:
|
public:
|
||||||
typedef PClassClass MetaClass;
|
typedef PClassClass MetaClass;
|
||||||
MetaClass *GetClass() const;
|
MetaClass *GetClass() const;
|
||||||
|
|
|
@ -361,7 +361,6 @@ size_t PClassActor::PropagateMark()
|
||||||
|
|
||||||
void PClassActor::InitializeNativeDefaults()
|
void PClassActor::InitializeNativeDefaults()
|
||||||
{
|
{
|
||||||
Symbols.SetParentTable(&ParentClass->Symbols);
|
|
||||||
assert(Defaults == NULL);
|
assert(Defaults == NULL);
|
||||||
Defaults = (BYTE *)M_Malloc(Size);
|
Defaults = (BYTE *)M_Malloc(Size);
|
||||||
if (ParentClass->Defaults != NULL)
|
if (ParentClass->Defaults != NULL)
|
||||||
|
|
|
@ -176,6 +176,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
|
||||||
head->Flags = C.Flags;
|
head->Flags = C.Flags;
|
||||||
head->Replaces = C.Replaces;
|
head->Replaces = C.Replaces;
|
||||||
head->Type = nullptr;
|
head->Type = nullptr;
|
||||||
|
head->Symbol = nullptr;
|
||||||
X = head;
|
X = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +250,7 @@ struct_def(X) ::= STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRACE opt_s
|
||||||
def->NodeName = A.Name();
|
def->NodeName = A.Name();
|
||||||
def->Body = B;
|
def->Body = B;
|
||||||
def->Type = nullptr;
|
def->Type = nullptr;
|
||||||
|
def->Symbol = nullptr;
|
||||||
X = def;
|
X = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright -2016 Randy Heit
|
** Copyright -2016 Randy Heit
|
||||||
|
** Copyright 2016 Christoph Oelckers
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
#include "zcc_parser.h"
|
#include "zcc_parser.h"
|
||||||
#include "zcc_compile.h"
|
#include "zcc_compile.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
|
#include "p_lnspec.h"
|
||||||
#include "gdtoa.h"
|
#include "gdtoa.h"
|
||||||
|
|
||||||
#define DEFINING_CONST ((PSymbolConst *)(void *)1)
|
#define DEFINING_CONST ((PSymbolConst *)(void *)1)
|
||||||
|
@ -155,7 +157,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
|
||||||
case AST_Class:
|
case AST_Class:
|
||||||
case AST_Struct:
|
case AST_Struct:
|
||||||
case AST_ConstantDef:
|
case AST_ConstantDef:
|
||||||
if ((tnode = AddNamedNode(static_cast<ZCC_NamedNode *>(node))))
|
if ((tnode = AddNamedNode(static_cast<ZCC_NamedNode *>(node), Symbols)))
|
||||||
{
|
{
|
||||||
switch (node->NodeType)
|
switch (node->NodeType)
|
||||||
{
|
{
|
||||||
|
@ -204,6 +206,9 @@ PSymbolTreeNode *ZCCCompiler::AddNamedNode(ZCC_NamedNode *node, PSymbolTable *pa
|
||||||
{
|
{
|
||||||
auto sy = new PSymbolTreeNode(name, node);
|
auto sy = new PSymbolTreeNode(name, node);
|
||||||
sy->Symbols.SetParentTable(parentsym);
|
sy->Symbols.SetParentTable(parentsym);
|
||||||
|
FString name;
|
||||||
|
name << "nodes - " << FName(node->NodeName);
|
||||||
|
sy->Symbols.SetName(name);
|
||||||
Symbols->AddSymbol(sy);
|
Symbols->AddSymbol(sy);
|
||||||
return sy;
|
return sy;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +280,7 @@ int ZCCCompiler::Compile()
|
||||||
{
|
{
|
||||||
CreateClassTypes();
|
CreateClassTypes();
|
||||||
CreateStructTypes();
|
CreateStructTypes();
|
||||||
CompileConstants(Constants);
|
CompileAllConstants();
|
||||||
return ErrorCount;
|
return ErrorCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +297,9 @@ void ZCCCompiler::CreateStructTypes()
|
||||||
for(auto s : Structs)
|
for(auto s : Structs)
|
||||||
{
|
{
|
||||||
s->Type = NewStruct(s->NodeName, nullptr);
|
s->Type = NewStruct(s->NodeName, nullptr);
|
||||||
|
s->Symbol = new PSymbolType(s->NodeName, s->Type);
|
||||||
|
s->Type->Symbols.SetName(FName(s->NodeName));
|
||||||
|
GlobalSymbols.AddSymbol(s->Symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +374,9 @@ void ZCCCompiler::CreateClassTypes()
|
||||||
// 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->Type = parent->FindClassTentative(c->NodeName);
|
||||||
}
|
}
|
||||||
|
c->Symbol = new PSymbolType(c->NodeName, c->Type);
|
||||||
|
GlobalSymbols.AddSymbol(c->Symbol);
|
||||||
|
c->Type->Symbols.SetName(FName(c->NodeName).GetChars());
|
||||||
Classes.Push(c);
|
Classes.Push(c);
|
||||||
OrigClasses.Delete(i);
|
OrigClasses.Delete(i);
|
||||||
i--;
|
i--;
|
||||||
|
@ -389,6 +400,9 @@ void ZCCCompiler::CreateClassTypes()
|
||||||
Error(c, "Class %s has unknown base class %s", FName(c->NodeName).GetChars(), FName(c->ParentName->Id).GetChars());
|
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.
|
// create a placeholder so that the compiler can continue looking for errors.
|
||||||
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName);
|
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName);
|
||||||
|
c->Symbol = new PSymbolType(c->NodeName, c->Type);
|
||||||
|
GlobalSymbols.AddSymbol(c->Symbol);
|
||||||
|
c->Type->Symbols.SetName(FName(c->NodeName).GetChars());
|
||||||
Classes.Push(c);
|
Classes.Push(c);
|
||||||
OrigClasses.Delete(i);
|
OrigClasses.Delete(i);
|
||||||
donesomething = true;
|
donesomething = true;
|
||||||
|
@ -403,28 +417,132 @@ void ZCCCompiler::CreateClassTypes()
|
||||||
{
|
{
|
||||||
Error(c, "Class %s has circular inheritance", FName(c->NodeName).GetChars());
|
Error(c, "Class %s has circular inheritance", FName(c->NodeName).GetChars());
|
||||||
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName);
|
c->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName);
|
||||||
|
c->Symbol = new PSymbolType(c->NodeName, c->Type);
|
||||||
|
c->Type->Symbols.SetName(FName(c->NodeName).GetChars());
|
||||||
|
GlobalSymbols.AddSymbol(c->Symbol);
|
||||||
Classes.Push(c);
|
Classes.Push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ZCCCompiler :: CompileConstants
|
// ZCCCompiler :: AddConstants
|
||||||
//
|
//
|
||||||
// Make symbols from every constant defined at this level.
|
// Helper for CompileAllConstants
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void ZCCCompiler::CompileConstants(const TArray<ZCC_ConstantDef *> &defs)
|
void ZCCCompiler::AddConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PSymbolTable *nt, PSymbolTable *ot)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < defs.Size(); ++i)
|
for (auto c : Constants)
|
||||||
{
|
{
|
||||||
ZCC_ConstantDef *def = defs[i];
|
dest.Push({ c, nt, ot });
|
||||||
if (def->Symbol == NULL)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ZCCCompiler :: CompileAllConstants
|
||||||
|
//
|
||||||
|
// Make symbols from every constant defined at all levels.
|
||||||
|
// Since constants may only depend on other constants this can be done
|
||||||
|
// without any more involved processing of the AST as a first step.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void ZCCCompiler::CompileAllConstants()
|
||||||
|
{
|
||||||
|
// put all constants in one list to make resolving this easier.
|
||||||
|
TArray<ZCC_ConstantWork> constantwork;
|
||||||
|
|
||||||
|
AddConstants(constantwork, Constants, Symbols, OutputSymbols);
|
||||||
|
for (auto &c : Classes)
|
||||||
|
{
|
||||||
|
AddConstants(constantwork, c.Constants, &c.node->Symbols, &c->Type->Symbols);
|
||||||
|
for (auto &s : c.Structs)
|
||||||
{
|
{
|
||||||
PSymbolConst *sym = CompileConstant(def);
|
AddConstants(constantwork, s.Constants, &s.node->Symbols, &s->Type->Symbols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto &s : Structs)
|
||||||
|
{
|
||||||
|
AddConstants(constantwork, s.Constants, &s.node->Symbols, &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.
|
||||||
|
for (unsigned i = 0; i<constantwork.Size(); i++)
|
||||||
|
{
|
||||||
|
if (constantwork[i].node->Value->NodeType == AST_ExprConstant)
|
||||||
|
{
|
||||||
|
AddConstant(constantwork[i]);
|
||||||
|
// Remove the constant from the list
|
||||||
|
constantwork.Delete(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool donesomething = true;
|
||||||
|
// Now go through this list until no more constants can be resolved. The remaining ones will be non-constant values.
|
||||||
|
while (donesomething && constantwork.Size() > 0)
|
||||||
|
{
|
||||||
|
donesomething = false;
|
||||||
|
for (unsigned i = 0; i < constantwork.Size(); i++)
|
||||||
|
{
|
||||||
|
if (CompileConstant(constantwork[i].node, constantwork[i].outputtable))
|
||||||
|
{
|
||||||
|
AddConstant(constantwork[i]);
|
||||||
|
// Remove the constant from the list
|
||||||
|
constantwork.Delete(i);
|
||||||
|
i--;
|
||||||
|
donesomething = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < constantwork.Size(); i++)
|
||||||
|
{
|
||||||
|
Error(constantwork[i].node, "%s is not a constant", FName(constantwork[i].node->NodeName).GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ZCCCompiler :: AddConstant
|
||||||
|
//
|
||||||
|
// Adds a constant to its assigned symbol table
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
|
||||||
|
{
|
||||||
|
auto def = constant.node;
|
||||||
|
auto val = def->Value;
|
||||||
|
if (val->NodeType == AST_ExprConstant)
|
||||||
|
{
|
||||||
|
ZCC_ExprConstant *cval = static_cast<ZCC_ExprConstant *>(val);
|
||||||
|
if (cval->Type == TypeString)
|
||||||
|
{
|
||||||
|
def->Symbol = new PSymbolConstString(def->NodeName, *(cval->StringVal));
|
||||||
|
}
|
||||||
|
else if (cval->Type->IsA(RUNTIME_CLASS(PInt)))
|
||||||
|
{
|
||||||
|
def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal);
|
||||||
|
}
|
||||||
|
else if (cval->Type->IsA(RUNTIME_CLASS(PFloat)))
|
||||||
|
{
|
||||||
|
def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Error(def->Value, "Bad type for constant definiton");
|
||||||
|
def->Symbol = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->Symbol == nullptr)
|
||||||
|
{
|
||||||
|
// Create a dummy constant so we don't make any undefined value warnings.
|
||||||
|
def->Symbol = new PSymbolConstNumeric(def->NodeName, TypeError, 0);
|
||||||
|
}
|
||||||
|
constant.outputtable->ReplaceSymbol(def->Symbol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -432,51 +550,19 @@ void ZCCCompiler::CompileConstants(const TArray<ZCC_ConstantDef *> &defs)
|
||||||
// ZCCCompiler :: CompileConstant
|
// ZCCCompiler :: CompileConstant
|
||||||
//
|
//
|
||||||
// For every constant definition, evaluate its value (which should result
|
// For every constant definition, evaluate its value (which should result
|
||||||
// in a constant), and create a symbol for it. Simplify() uses recursion
|
// in a constant), and create a symbol for it.
|
||||||
// to resolve constants used before their declarations.
|
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def)
|
bool ZCCCompiler::CompileConstant(ZCC_ConstantDef *def, PSymbolTable *sym)
|
||||||
{
|
{
|
||||||
assert(def->Symbol == NULL);
|
assert(def->Symbol == nullptr);
|
||||||
|
|
||||||
def->Symbol = DEFINING_CONST; // avoid recursion
|
def->Symbol = DEFINING_CONST; // avoid recursion
|
||||||
ZCC_Expression *val = Simplify(def->Value);
|
ZCC_Expression *val = Simplify(def->Value, sym);
|
||||||
def->Value = val;
|
def->Value = val;
|
||||||
PSymbolConst *sym = NULL;
|
if (def->Symbol == DEFINING_CONST) def->Symbol = nullptr;
|
||||||
if (val->NodeType == AST_ExprConstant)
|
return (val->NodeType == AST_ExprConstant);
|
||||||
{
|
|
||||||
ZCC_ExprConstant *cval = static_cast<ZCC_ExprConstant *>(val);
|
|
||||||
if (cval->Type == TypeString)
|
|
||||||
{
|
|
||||||
sym = new PSymbolConstString(def->NodeName, *(cval->StringVal));
|
|
||||||
}
|
|
||||||
else if (cval->Type->IsA(RUNTIME_CLASS(PInt)))
|
|
||||||
{
|
|
||||||
sym = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal);
|
|
||||||
}
|
|
||||||
else if (cval->Type->IsA(RUNTIME_CLASS(PFloat)))
|
|
||||||
{
|
|
||||||
sym = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Error(def->Value, "Bad type for constant definiton");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Error(def->Value, "Constant definition requires a constant value");
|
|
||||||
}
|
|
||||||
if (sym == NULL)
|
|
||||||
{
|
|
||||||
// Create a dummy constant so we don't make any undefined value warnings.
|
|
||||||
sym = new PSymbolConstNumeric(def->NodeName, TypeError, 0);
|
|
||||||
}
|
|
||||||
def->Symbol = sym;
|
|
||||||
OutputSymbols->ReplaceSymbol(sym);
|
|
||||||
return sym;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -493,27 +579,27 @@ PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root)
|
ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root, PSymbolTable *sym)
|
||||||
{
|
{
|
||||||
if (root->NodeType == AST_ExprUnary)
|
if (root->NodeType == AST_ExprUnary)
|
||||||
{
|
{
|
||||||
return SimplifyUnary(static_cast<ZCC_ExprUnary *>(root));
|
return SimplifyUnary(static_cast<ZCC_ExprUnary *>(root), sym);
|
||||||
}
|
}
|
||||||
else if (root->NodeType == AST_ExprBinary)
|
else if (root->NodeType == AST_ExprBinary)
|
||||||
{
|
{
|
||||||
return SimplifyBinary(static_cast<ZCC_ExprBinary *>(root));
|
return SimplifyBinary(static_cast<ZCC_ExprBinary *>(root), sym);
|
||||||
}
|
}
|
||||||
else if (root->Operation == PEX_ID)
|
else if (root->Operation == PEX_ID)
|
||||||
{
|
{
|
||||||
return IdentifyIdentifier(static_cast<ZCC_ExprID *>(root));
|
return IdentifyIdentifier(static_cast<ZCC_ExprID *>(root), sym);
|
||||||
}
|
}
|
||||||
else if (root->Operation == PEX_MemberAccess)
|
else if (root->Operation == PEX_MemberAccess)
|
||||||
{
|
{
|
||||||
return SimplifyMemberAccess(static_cast<ZCC_ExprMemberAccess *>(root));
|
return SimplifyMemberAccess(static_cast<ZCC_ExprMemberAccess *>(root), sym);
|
||||||
}
|
}
|
||||||
else if (root->Operation == PEX_FuncCall)
|
else if (root->Operation == PEX_FuncCall)
|
||||||
{
|
{
|
||||||
return SimplifyFunctionCall(static_cast<ZCC_ExprFuncCall *>(root));
|
return SimplifyFunctionCall(static_cast<ZCC_ExprFuncCall *>(root), sym);
|
||||||
}
|
}
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
@ -524,9 +610,13 @@ ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary)
|
ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *sym)
|
||||||
{
|
{
|
||||||
unary->Operand = Simplify(unary->Operand);
|
unary->Operand = Simplify(unary->Operand, sym);
|
||||||
|
if (unary->Operand->Type == nullptr)
|
||||||
|
{
|
||||||
|
return unary;
|
||||||
|
}
|
||||||
ZCC_OpProto *op = PromoteUnary(unary->Operation, unary->Operand);
|
ZCC_OpProto *op = PromoteUnary(unary->Operation, unary->Operand);
|
||||||
if (op == NULL)
|
if (op == NULL)
|
||||||
{ // Oh, poo!
|
{ // Oh, poo!
|
||||||
|
@ -545,10 +635,15 @@ ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary)
|
ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *sym)
|
||||||
{
|
{
|
||||||
binary->Left = Simplify(binary->Left);
|
binary->Left = Simplify(binary->Left, sym);
|
||||||
binary->Right = Simplify(binary->Right);
|
binary->Right = Simplify(binary->Right, sym);
|
||||||
|
if (binary->Left->Type == nullptr || binary->Right->Type == nullptr)
|
||||||
|
{
|
||||||
|
// We do not know yet what this is so we cannot promote it (yet.)
|
||||||
|
return binary;
|
||||||
|
}
|
||||||
ZCC_OpProto *op = PromoteBinary(binary->Operation, binary->Left, binary->Right);
|
ZCC_OpProto *op = PromoteBinary(binary->Operation, binary->Left, binary->Right);
|
||||||
if (op == NULL)
|
if (op == NULL)
|
||||||
{
|
{
|
||||||
|
@ -569,32 +664,41 @@ ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop)
|
ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *symt)
|
||||||
{
|
{
|
||||||
dotop->Left = Simplify(dotop->Left);
|
PSymbolTable *symtable;
|
||||||
|
|
||||||
|
dotop->Left = Simplify(dotop->Left, symt);
|
||||||
|
|
||||||
if (dotop->Left->Operation == PEX_TypeRef)
|
if (dotop->Left->Operation == PEX_TypeRef)
|
||||||
{ // Type refs can be evaluated now.
|
{ // Type refs can be evaluated now.
|
||||||
PType *ref = static_cast<ZCC_ExprTypeRef *>(dotop->Left)->RefType;
|
PType *ref = static_cast<ZCC_ExprTypeRef *>(dotop->Left)->RefType;
|
||||||
PSymbolTable *symtable;
|
|
||||||
PSymbol *sym = ref->Symbols.FindSymbolInTable(dotop->Right, symtable);
|
PSymbol *sym = ref->Symbols.FindSymbolInTable(dotop->Right, symtable);
|
||||||
if (sym == NULL)
|
if (sym != nullptr)
|
||||||
{
|
|
||||||
Error(dotop, "'%s' is not a valid member", FName(dotop->Right).GetChars());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable);
|
ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable);
|
||||||
if (expr == NULL)
|
if (expr != nullptr)
|
||||||
{
|
|
||||||
Error(dotop, "Unhandled symbol type encountered");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (dotop->Left->Operation == PEX_Super)
|
||||||
|
{
|
||||||
|
symt = symt->GetParentTable();
|
||||||
|
if (symt != nullptr)
|
||||||
|
{
|
||||||
|
PSymbol *sym = symt->FindSymbolInTable(dotop->Right, symtable);
|
||||||
|
if (sym != nullptr)
|
||||||
|
{
|
||||||
|
ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable);
|
||||||
|
if (expr != nullptr)
|
||||||
|
{
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return dotop;
|
return dotop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,12 +711,12 @@ ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop)
|
ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *sym)
|
||||||
{
|
{
|
||||||
ZCC_FuncParm *parm;
|
ZCC_FuncParm *parm;
|
||||||
int parmcount = 0;
|
int parmcount = 0;
|
||||||
|
|
||||||
callop->Function = Simplify(callop->Function);
|
callop->Function = Simplify(callop->Function, sym);
|
||||||
parm = callop->Parameters;
|
parm = callop->Parameters;
|
||||||
if (parm != NULL)
|
if (parm != NULL)
|
||||||
{
|
{
|
||||||
|
@ -620,7 +724,7 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop)
|
||||||
{
|
{
|
||||||
parmcount++;
|
parmcount++;
|
||||||
assert(parm->NodeType == AST_FuncParm);
|
assert(parm->NodeType == AST_FuncParm);
|
||||||
parm->Value = Simplify(parm->Value);
|
parm->Value = Simplify(parm->Value, sym);
|
||||||
parm = static_cast<ZCC_FuncParm *>(parm->SiblingNext);
|
parm = static_cast<ZCC_FuncParm *>(parm->SiblingNext);
|
||||||
}
|
}
|
||||||
while (parm != callop->Parameters);
|
while (parm != callop->Parameters);
|
||||||
|
@ -751,12 +855,14 @@ ZCC_Expression *ZCCCompiler::AddCastNode(PType *type, ZCC_Expression *expr)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode)
|
ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *symt)
|
||||||
{
|
{
|
||||||
// Check the symbol table for the identifier.
|
// Check the symbol table for the identifier.
|
||||||
PSymbolTable *table;
|
PSymbolTable *table;
|
||||||
PSymbol *sym = Symbols->FindSymbolInTable(idnode->Identifier, table);
|
PSymbol *sym = symt->FindSymbolInTable(idnode->Identifier, table);
|
||||||
if (sym != NULL)
|
// GlobalSymbols cannot be the parent of a class's symbol table so we have to look for global symbols explicitly.
|
||||||
|
if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(idnode->Identifier, table);
|
||||||
|
if (sym != nullptr)
|
||||||
{
|
{
|
||||||
ZCC_Expression *node = NodeFromSymbol(sym, idnode, table);
|
ZCC_Expression *node = NodeFromSymbol(sym, idnode, table);
|
||||||
if (node != NULL)
|
if (node != NULL)
|
||||||
|
@ -766,46 +872,26 @@ ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Also handle line specials.
|
||||||
|
// To call this like a function this needs to be done differently, but for resolving constants this is ok.
|
||||||
|
int spec = P_FindLineSpecial(FName(idnode->Identifier).GetChars());
|
||||||
|
if (spec != 0)
|
||||||
|
{
|
||||||
|
ZCC_ExprConstant *val = static_cast<ZCC_ExprConstant *>(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode));
|
||||||
|
val->Operation = PEX_ConstValue;
|
||||||
|
val->Type = TypeSInt32;
|
||||||
|
val->IntVal = spec;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
symt->DumpSymbolTable();
|
||||||
|
GlobalSymbols.DumpSymbolTable();
|
||||||
|
|
||||||
Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars());
|
Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars());
|
||||||
|
idnode->ToErrorNode();
|
||||||
}
|
}
|
||||||
// Identifier didn't refer to anything good, so type error it.
|
|
||||||
idnode->ToErrorNode();
|
|
||||||
return idnode;
|
return idnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ZCCCompiler :: CompileNode
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
PSymbol *ZCCCompiler::CompileNode(ZCC_NamedNode *node)
|
|
||||||
{
|
|
||||||
assert(node != NULL);
|
|
||||||
if (node->NodeType == AST_ConstantDef)
|
|
||||||
{
|
|
||||||
ZCC_ConstantDef *def = static_cast<ZCC_ConstantDef *>(node);
|
|
||||||
PSymbolConst *sym = def->Symbol;
|
|
||||||
|
|
||||||
if (sym == DEFINING_CONST)
|
|
||||||
{
|
|
||||||
Error(node, "Definition of '%s' is infinitely recursive", FName(node->NodeName).GetChars());
|
|
||||||
sym = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(sym == NULL);
|
|
||||||
sym = CompileConstant(def);
|
|
||||||
}
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
else if (node->NodeType == AST_Struct)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ZCCCompiler :: NodeFromSymbol
|
// ZCCCompiler :: NodeFromSymbol
|
||||||
|
@ -814,18 +900,8 @@ PSymbol *ZCCCompiler::CompileNode(ZCC_NamedNode *node)
|
||||||
|
|
||||||
ZCC_Expression *ZCCCompiler::NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table)
|
ZCC_Expression *ZCCCompiler::NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table)
|
||||||
{
|
{
|
||||||
assert(sym != NULL);
|
assert(sym != nullptr);
|
||||||
if (sym->IsA(RUNTIME_CLASS(PSymbolTreeNode)))
|
|
||||||
{
|
|
||||||
PSymbolTable *prevtable = Symbols;
|
|
||||||
Symbols = table;
|
|
||||||
sym = CompileNode(static_cast<PSymbolTreeNode *>(sym)->Node);
|
|
||||||
Symbols = prevtable;
|
|
||||||
if (sym == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
|
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
|
||||||
{
|
{
|
||||||
return NodeFromSymbolConst(static_cast<PSymbolConst *>(sym), source);
|
return NodeFromSymbolConst(static_cast<PSymbolConst *>(sym), source);
|
||||||
|
|
|
@ -51,6 +51,13 @@ struct ZCC_ClassWork
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ZCC_ConstantWork
|
||||||
|
{
|
||||||
|
ZCC_ConstantDef *node;
|
||||||
|
PSymbolTable *nodetable;
|
||||||
|
PSymbolTable *outputtable;
|
||||||
|
};
|
||||||
|
|
||||||
class ZCCCompiler
|
class ZCCCompiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -62,8 +69,11 @@ private:
|
||||||
void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode);
|
void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode);
|
||||||
void CreateStructTypes();
|
void CreateStructTypes();
|
||||||
void CreateClassTypes();
|
void CreateClassTypes();
|
||||||
void CompileConstants(const TArray<ZCC_ConstantDef *> &defs);
|
void AddConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PSymbolTable *nt, PSymbolTable *ot);
|
||||||
PSymbolConst *CompileConstant(ZCC_ConstantDef *def);
|
void CompileAllConstants();
|
||||||
|
void AddConstant(ZCC_ConstantWork &constant);
|
||||||
|
int CompileConstants(const TArray<ZCC_ConstantDef *> &defs, PSymbolTable *Nodes, PSymbolTable *Output);
|
||||||
|
bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols);
|
||||||
|
|
||||||
TArray<ZCC_ConstantDef *> Constants;
|
TArray<ZCC_ConstantDef *> Constants;
|
||||||
TArray<ZCC_StructWork> Structs;
|
TArray<ZCC_StructWork> Structs;
|
||||||
|
@ -71,11 +81,11 @@ private:
|
||||||
|
|
||||||
PSymbolTreeNode *AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym = nullptr);
|
PSymbolTreeNode *AddNamedNode(ZCC_NamedNode *node, PSymbolTable *parentsym = nullptr);
|
||||||
|
|
||||||
ZCC_Expression *Simplify(ZCC_Expression *root);
|
ZCC_Expression *Simplify(ZCC_Expression *root, PSymbolTable *Symbols);
|
||||||
ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary);
|
ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *Symbols);
|
||||||
ZCC_Expression *SimplifyBinary(ZCC_ExprBinary *binary);
|
ZCC_Expression *SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *Symbols);
|
||||||
ZCC_Expression *SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop);
|
ZCC_Expression *SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *Symbols);
|
||||||
ZCC_Expression *SimplifyFunctionCall(ZCC_ExprFuncCall *callop);
|
ZCC_Expression *SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *Symbols);
|
||||||
ZCC_OpProto *PromoteUnary(EZCCExprType op, ZCC_Expression *&expr);
|
ZCC_OpProto *PromoteUnary(EZCCExprType op, ZCC_Expression *&expr);
|
||||||
ZCC_OpProto *PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right);
|
ZCC_OpProto *PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right);
|
||||||
|
|
||||||
|
@ -87,11 +97,10 @@ private:
|
||||||
ZCC_Expression *ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen);
|
ZCC_Expression *ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen);
|
||||||
ZCC_Expression *AddCastNode(PType *type, ZCC_Expression *expr);
|
ZCC_Expression *AddCastNode(PType *type, ZCC_Expression *expr);
|
||||||
|
|
||||||
ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode);
|
ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *sym);
|
||||||
ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table);
|
ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table);
|
||||||
ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode);
|
ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode);
|
||||||
ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode);
|
ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode);
|
||||||
PSymbol *CompileNode(ZCC_NamedNode *node);
|
|
||||||
|
|
||||||
|
|
||||||
void Warn(ZCC_TreeNode *node, const char *msg, ...);
|
void Warn(ZCC_TreeNode *node, const char *msg, ...);
|
||||||
|
|
|
@ -338,7 +338,8 @@ static void DoParse(int lumpnum)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PSymbolTable symtable(&GlobalSymbols);
|
PSymbolTable symtable;
|
||||||
|
symtable.SetName("Global_Node");
|
||||||
ZCCCompiler cc(state, NULL, symtable, GlobalSymbols);
|
ZCCCompiler cc(state, NULL, symtable, GlobalSymbols);
|
||||||
cc.Compile();
|
cc.Compile();
|
||||||
// ... and another one afterward so we can see what the compiler does with the data.
|
// ... and another one afterward so we can see what the compiler does with the data.
|
||||||
|
|
|
@ -188,12 +188,14 @@ struct ZCC_Class : ZCC_NamedNode
|
||||||
VM_UWORD Flags;
|
VM_UWORD Flags;
|
||||||
ZCC_TreeNode *Body;
|
ZCC_TreeNode *Body;
|
||||||
PClass *Type;
|
PClass *Type;
|
||||||
|
PSymbolType *Symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZCC_Struct : ZCC_NamedNode
|
struct ZCC_Struct : ZCC_NamedNode
|
||||||
{
|
{
|
||||||
ZCC_TreeNode *Body;
|
ZCC_TreeNode *Body;
|
||||||
PStruct *Type;
|
PStruct *Type;
|
||||||
|
PSymbolType *Symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZCC_Enum : ZCC_NamedNode
|
struct ZCC_Enum : ZCC_NamedNode
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
/*
|
||||||
// Flags for A_PainAttack
|
// Flags for A_PainAttack
|
||||||
enum EPainAttackFlags
|
enum EPainAttackFlags
|
||||||
{
|
{
|
||||||
|
@ -806,3 +806,4 @@ enum ERenderStyles
|
||||||
STYLE_AddStencil,
|
STYLE_AddStencil,
|
||||||
STYLE_AddShaded,
|
STYLE_AddShaded,
|
||||||
};
|
};
|
||||||
|
*/
|
Loading…
Reference in a new issue