- 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:
Christoph Oelckers 2016-10-08 22:16:10 +02:00
parent 5bb6bb31ca
commit 08f313d011
9 changed files with 252 additions and 136 deletions

View file

@ -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;
} }

View file

@ -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;

View file

@ -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)

View file

@ -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;
} }

View file

@ -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);

View file

@ -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, ...);

View file

@ -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.

View file

@ -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

View file

@ -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,
}; };
*/