- created an export for P_SpawnMissile so that I can do some tests with functions.

- allow class extensions.

These are separate blocks in different files that get concatenated to one class body for processing. The reason is to allow spreading the many functions in Actor over multiple files, so that they remain manageable. For example, all the Doom action functions should be in their respective files, but their symbols need to be in Actor. To extend a class, both files need to be in the same translation unit, so it won't allow user-side extension of internal classes.
This commit is contained in:
Christoph Oelckers 2016-10-23 12:57:21 +02:00
parent f9cd2c9af7
commit a2116fc7bf
9 changed files with 60 additions and 6 deletions

View file

@ -1013,6 +1013,7 @@ struct AFuncDesc
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0)
#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0)
#define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0)
#define ACTION_RETURN_INT(v) do { int u = v; if (numret > 0) { assert(ret != NULL); ret->SetInt(u); return 1; } return 0; } while(0)
#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v)

View file

@ -171,6 +171,18 @@ class_definition(X) ::= class_head(A) class_body(B).
X = A; /*X-overwrites-A*/
}
class_head(X) ::= EXTEND CLASS(T) IDENTIFIER(A).
{
NEW_AST_NODE(Class,head,T);
head->NodeName = A.Name();
head->ParentName = nullptr;
head->Flags = ZCC_Extension;
head->Replaces = nullptr;
head->Type = nullptr;
head->Symbol = nullptr;
X = head;
}
class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
{
NEW_AST_NODE(Class,head,T);

View file

@ -61,8 +61,29 @@
void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
{
Classes.Push(new ZCC_ClassWork(static_cast<ZCC_Class *>(cnode), treenode));
auto cls = Classes.Last();
ZCC_ClassWork *cls = nullptr;
// If this is a class extension, put the new node directly into the existing class.
if (cnode->Flags == ZCC_Extension)
{
for (auto clss : Classes)
{
if (clss->NodeName() == cnode->NodeName)
{
cls = clss;
break;
}
}
if (cls == nullptr)
{
Error(cnode, "Class %s cannot be found in the current translation unit.");
return;
}
}
else
{
Classes.Push(new ZCC_ClassWork(static_cast<ZCC_Class *>(cnode), treenode));
cls = Classes.Last();
}
auto node = cnode->Body;
PSymbolTreeNode *childnode;
@ -220,6 +241,12 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
switch (node->NodeType)
{
case AST_Class:
// a class extension should not check the tree node symbols.
if (static_cast<ZCC_Class *>(node)->Flags == ZCC_Extension)
{
ProcessClass(static_cast<ZCC_Class *>(node), tnode);
break;
}
case AST_Struct:
case AST_ConstantDef:
case AST_Enum:

View file

@ -198,6 +198,7 @@ static void InitTokenMap()
TOKENDEF (TK_Offset, ZCC_OFFSET);
TOKENDEF (TK_CanRaise, ZCC_CANRAISE);
TOKENDEF (TK_Light, ZCC_LIGHT);
TOKENDEF (TK_Extend, ZCC_EXTEND);
ZCC_InitOperators();
ZCC_InitConversions();

View file

@ -32,6 +32,7 @@ enum
ZCC_ReadOnly = 1 << 9,
ZCC_FuncConst = 1 << 10,
ZCC_Abstract = 1 << 11,
ZCC_Extension = 1 << 12,
};
// Function parameter modifiers