mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-15 06:51:36 +00:00
Allow using constants in other constants before their definitions.
- Something like this is now valid: const foo = bar + 10; const bar = 1000;
This commit is contained in:
parent
76d2e8cfc4
commit
6384613487
3 changed files with 89 additions and 12 deletions
|
@ -10,6 +10,8 @@
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "gdtoa.h"
|
#include "gdtoa.h"
|
||||||
|
|
||||||
|
#define DEFINING_CONST ((PSymbolConst *)(void *)1)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ZCCCompiler Constructor
|
// ZCCCompiler Constructor
|
||||||
|
@ -27,12 +29,33 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols)
|
||||||
{
|
{
|
||||||
switch (node->NodeType)
|
switch (node->NodeType)
|
||||||
{
|
{
|
||||||
case AST_Class: Classes.Push(static_cast<ZCC_Class *>(node)); break;
|
case AST_Class:
|
||||||
case AST_Struct: Structs.Push(static_cast<ZCC_Struct *>(node)); break;
|
// if (AddNamedNode(static_cast<ZCC_Class *>(node)->ClassName, node))
|
||||||
|
{
|
||||||
|
Classes.Push(static_cast<ZCC_Class *>(node));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AST_Struct:
|
||||||
|
if (AddNamedNode(static_cast<ZCC_Struct *>(node)->StructName, node))
|
||||||
|
{
|
||||||
|
Structs.Push(static_cast<ZCC_Struct *>(node));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case AST_Enum: break;
|
case AST_Enum: break;
|
||||||
case AST_EnumTerminator:break;
|
case AST_EnumTerminator:break;
|
||||||
case AST_ConstantDef: Constants.Push(static_cast<ZCC_ConstantDef *>(node)); break;
|
|
||||||
default: assert(0 && "Unhandled AST node type"); break;
|
case AST_ConstantDef:
|
||||||
|
if (AddNamedNode(static_cast<ZCC_ConstantDef *>(node)->Name, node))
|
||||||
|
{
|
||||||
|
Constants.Push(static_cast<ZCC_ConstantDef *>(node));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0 && "Unhandled AST node type");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
node = node->SiblingNext;
|
node = node->SiblingNext;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +63,31 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ZCCCompiler :: AddNamedNode
|
||||||
|
//
|
||||||
|
// Keeps track of definition nodes by their names. Ensures that all names
|
||||||
|
// in this scope are unique.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool ZCCCompiler::AddNamedNode(FName name, ZCC_TreeNode *node)
|
||||||
|
{
|
||||||
|
ZCC_TreeNode **check = NamedNodes.CheckKey(name);
|
||||||
|
if (check != NULL && *check != NULL)
|
||||||
|
{
|
||||||
|
Message(node, ERR_symbol_redefinition, "Attempt to redefine '%s'", name.GetChars());
|
||||||
|
Message(*check, ERR_original_definition, " Original definition is here");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NamedNodes.Insert(name, node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ZCCCompiler :: Message
|
// ZCCCompiler :: Message
|
||||||
|
@ -104,11 +152,7 @@ void ZCCCompiler::CompileConstants()
|
||||||
ZCC_ConstantDef *def = Constants[i];
|
ZCC_ConstantDef *def = Constants[i];
|
||||||
if (def->Symbol == NULL)
|
if (def->Symbol == NULL)
|
||||||
{
|
{
|
||||||
PSymbolConst *sym = CompileConstant(def);
|
CompileConstant(def);
|
||||||
if (NULL == Symbols.AddSymbol(sym))
|
|
||||||
{
|
|
||||||
Message(Constants[i], ERR_symbol_redefinition, "Redefinition of symbol '%s'", FName(def->Name).GetChars());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +171,7 @@ PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def)
|
||||||
{
|
{
|
||||||
assert(def->Symbol == NULL);
|
assert(def->Symbol == NULL);
|
||||||
|
|
||||||
def->Symbol = (PSymbolConst *)(void *)1; // mark as being defined (avoid recursion)
|
def->Symbol = DEFINING_CONST; // avoid recursion
|
||||||
ZCC_Expression *val = Simplify(def->Value);
|
ZCC_Expression *val = Simplify(def->Value);
|
||||||
def->Value = val;
|
def->Value = val;
|
||||||
PSymbolConst *sym = NULL;
|
PSymbolConst *sym = NULL;
|
||||||
|
@ -161,6 +205,8 @@ PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def)
|
||||||
sym = new PSymbolConstNumeric(def->Name, TypeError, 0);
|
sym = new PSymbolConstNumeric(def->Name, TypeError, 0);
|
||||||
}
|
}
|
||||||
def->Symbol = sym;
|
def->Symbol = sym;
|
||||||
|
PSymbol *addsym = Symbols.AddSymbol(sym);
|
||||||
|
assert(NULL != addsym && "Symbol was redefined (but we shouldn't have even had the chance to do so)");
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +393,28 @@ ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ // Check nodes that haven't had symbols created for them yet.
|
||||||
|
ZCC_TreeNode **node = NamedNodes.CheckKey(idnode->Identifier);
|
||||||
|
if (node != NULL && *node != NULL)
|
||||||
|
{
|
||||||
|
if ((*node)->NodeType == AST_ConstantDef)
|
||||||
|
{
|
||||||
|
ZCC_ConstantDef *def = static_cast<ZCC_ConstantDef *>(*node);
|
||||||
|
PSymbolConst *sym = def->Symbol;
|
||||||
|
|
||||||
|
if (sym == DEFINING_CONST)
|
||||||
|
{
|
||||||
|
Message(idnode, ERR_recursive_definition, "Definition of '%s' is infinitely recursive", FName(idnode->Identifier).GetChars());
|
||||||
|
sym = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(sym == NULL);
|
||||||
|
sym = CompileConstant(def);
|
||||||
|
}
|
||||||
|
return NodeFromSymbolConst(sym, idnode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Identifier didn't refer to anything good, so type error it.
|
// Identifier didn't refer to anything good, so type error it.
|
||||||
idnode->Type = TypeError;
|
idnode->Type = TypeError;
|
||||||
|
@ -368,7 +435,12 @@ ZCC_ExprConstant *ZCCCompiler::NodeFromSymbolConst(PSymbolConst *sym, ZCC_ExprID
|
||||||
{
|
{
|
||||||
ZCC_ExprConstant *val = static_cast<ZCC_ExprConstant *>(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode));
|
ZCC_ExprConstant *val = static_cast<ZCC_ExprConstant *>(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode));
|
||||||
val->Operation = PEX_ConstValue;
|
val->Operation = PEX_ConstValue;
|
||||||
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConstString)))
|
if (sym == NULL)
|
||||||
|
{
|
||||||
|
val->Type = TypeError;
|
||||||
|
val->IntVal = 0;
|
||||||
|
}
|
||||||
|
else if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConstString)))
|
||||||
{
|
{
|
||||||
val->StringVal = AST.Strings.Alloc(static_cast<PSymbolConstString *>(sym)->Str);
|
val->StringVal = AST.Strings.Alloc(static_cast<PSymbolConstString *>(sym)->Str);
|
||||||
val->Type = TypeString;
|
val->Type = TypeString;
|
||||||
|
|
|
@ -16,6 +16,9 @@ private:
|
||||||
TArray<ZCC_ConstantDef *> Constants;
|
TArray<ZCC_ConstantDef *> Constants;
|
||||||
TArray<ZCC_Struct *> Structs;
|
TArray<ZCC_Struct *> Structs;
|
||||||
TArray<ZCC_Class *> Classes;
|
TArray<ZCC_Class *> Classes;
|
||||||
|
TMap<FName, ZCC_TreeNode *> NamedNodes;
|
||||||
|
|
||||||
|
bool AddNamedNode(FName name, ZCC_TreeNode *node);
|
||||||
|
|
||||||
ZCC_Expression *Simplify(ZCC_Expression *root);
|
ZCC_Expression *Simplify(ZCC_Expression *root);
|
||||||
ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary);
|
ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary);
|
||||||
|
|
|
@ -5,4 +5,6 @@ enum EZCCError
|
||||||
ERR_const_def_not_constant = 20000 | ZCCERR_ERROR,
|
ERR_const_def_not_constant = 20000 | ZCCERR_ERROR,
|
||||||
ERR_bad_const_def_type = 20001 | ZCCERR_ERROR,
|
ERR_bad_const_def_type = 20001 | ZCCERR_ERROR,
|
||||||
ERR_symbol_redefinition = 20002 | ZCCERR_ERROR,
|
ERR_symbol_redefinition = 20002 | ZCCERR_ERROR,
|
||||||
|
ERR_original_definition = 20003 | ZCCERR_ERROR,
|
||||||
|
ERR_recursive_definition = 20004 | ZCCERR_ERROR,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue