From d22a4c835c54ed073249a9cd44e118ca093bea4b Mon Sep 17 00:00:00 2001 From: Chronos Ouroboros Date: Tue, 7 Jan 2020 16:11:20 -0300 Subject: [PATCH] Mixins now perform a deep copy of the AST. (Fixes default blocks in mixins) --- src/scripting/zscript/zcc_compile.cpp | 146 +++-- src/scripting/zscript/zcc_compile.h | 1 + src/scripting/zscript/zcc_parser.cpp | 800 ++++++++++++++++++++++++++ src/scripting/zscript/zcc_parser.h | 7 + 4 files changed, 911 insertions(+), 43 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1f8109a8f..887c8ab68 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -98,6 +98,31 @@ FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls return static_cast(ex)->GetValue().GetString(); } +ZCC_MixinDef *ZCCCompiler::ResolveMixinStmt(ZCC_MixinStmt *mixinStmt, EZCCMixinType type) +{ + ZCC_MixinDef *mixinDef = nullptr; + + for (auto mx : Mixins) + { + if (mx->mixin->NodeName == mixinStmt->MixinName) + { + if (mx->mixin->MixinType != type) + { + Error(mixinStmt, "Mixin %s is a %s mixin cannot be used here.", FName(mixinStmt->MixinName).GetChars(), GetMixinTypeString(type)); + } + + return mx->mixin; + } + } + + if (mixinDef == nullptr) + { + Error(mixinStmt, "Mixin %s does not exist.", FName(mixinStmt->MixinName).GetChars()); + } + + return mixinDef; +} + //========================================================================== // @@ -132,48 +157,92 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) } auto node = cnode->Body; - auto origNextNode = cnode->Body; - ZCC_MixinDef *mixinDef = nullptr; PSymbolTreeNode *childnode; ZCC_Enum *enumType = nullptr; + // [pbeta] Handle mixins here for the sake of simplifying things. + if (node != nullptr) + { + TArray mixinStmts; + mixinStmts.Clear(); + + // Gather all mixin statement nodes. + do + { + if (node->NodeType == AST_MixinStmt) + { + mixinStmts.Push(static_cast(node)); + } + + node = node->SiblingNext; + } + while (node != cnode->Body); + + for (auto mixinStmt : mixinStmts) + { + ZCC_MixinDef *mixinDef = ResolveMixinStmt(mixinStmt, ZCC_Mixin_Class); + + // Insert the mixin if there's a body. If not, just remove this node. + if (mixinDef->Body != nullptr) + { + auto newNode = TreeNodeDeepCopy(&AST, mixinDef->Body, true); + + if (mixinStmt->SiblingNext != mixinStmt && mixinStmt->SiblingPrev != mixinStmt) + { + auto prevSibling = mixinStmt->SiblingPrev; + auto nextSibling = mixinStmt->SiblingNext; + + auto newFirst = newNode; + auto newLast = newNode->SiblingPrev; + + newFirst->SiblingPrev = prevSibling; + newLast->SiblingNext = nextSibling; + + prevSibling->SiblingNext = newFirst; + nextSibling->SiblingPrev = newLast; + } + + if (cnode->Body == mixinStmt) + { + cnode->Body = newNode; + } + } + else + { + if (mixinStmt->SiblingNext != mixinStmt && mixinStmt->SiblingPrev != mixinStmt) + { + auto prevSibling = mixinStmt->SiblingPrev; + auto nextSibling = mixinStmt->SiblingNext; + + prevSibling->SiblingNext = nextSibling; + nextSibling->SiblingPrev = prevSibling; + + if (cnode->Body == mixinStmt) + { + cnode->Body = nextSibling; + } + } + else if (cnode->Body == mixinStmt) + { + cnode->Body = nullptr; + } + } + } + + mixinStmts.Clear(); + } + + node = cnode->Body; + // Need to check if the class actually has a body. if (node != nullptr) do { switch (node->NodeType) { case AST_MixinStmt: - { - auto mixinStmt = static_cast(node); - for (auto mx : Mixins) - { - if (mx->mixin->NodeName == mixinStmt->MixinName) - { - if (mx->mixin->MixinType != ZCC_Mixin_Class) - { - Error(node, "Mixin %s is not a class mixin.", FName(mixinStmt->MixinName).GetChars()); - } - - mixinDef = mx->mixin; - break; - } - } - - if (mixinDef == nullptr) - { - Error(node, "Mixin %s does not exist.", FName(mixinStmt->MixinName).GetChars()); - break; - } - - if (mixinDef->Body != nullptr) - { - origNextNode = node->SiblingNext; - node = mixinDef->Body; - - continue; - } - } - break; + assert(0 && "Unhandled mixin statement in class parsing loop. If this has been reached, something is seriously wrong"); + Error(node, "Internal mixin error."); + break; case AST_Struct: case AST_ConstantDef: @@ -248,12 +317,6 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) } node = node->SiblingNext; - - if (mixinDef != nullptr && node == mixinDef->Body) - { - node = origNextNode; - mixinDef = nullptr; - } } while (node != cnode->Body); } @@ -286,13 +349,10 @@ void ZCCCompiler::ProcessMixin(ZCC_MixinDef *cnode, PSymbolTreeNode *treenode) case AST_EnumTerminator: case AST_States: case AST_FuncDeclarator: + case AST_Default: case AST_StaticArrayStatement: break; - case AST_Default: - Error(node, "Default blocks currently disabled in mixins"); - return; - default: assert(0 && "Unhandled AST node type"); break; diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 5dfa0bb3b..040d28bd3 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -114,6 +114,7 @@ private: int IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls); FString StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls); + ZCC_MixinDef *ResolveMixinStmt(ZCC_MixinStmt *mixinStmt, EZCCMixinType type); void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); void ProcessMixin(ZCC_MixinDef *cnode, PSymbolTreeNode *treenode); diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 4540e3a20..0f9a06f42 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -578,3 +578,803 @@ void AppendTreeNodeSibling(ZCC_TreeNode *thisnode, ZCC_TreeNode *sibling) SiblingPrev = siblingend; siblingend->SiblingNext = thisnode; } + +//**-------------------------------------------------------------------------- + +const char *GetMixinTypeString(EZCCMixinType type) { + switch (type) { + case ZCC_Mixin_Class: + return "class"; + + default: + assert(0 && "Unhandled mixin type"); + return "invalid type"; + } +} + +//**-------------------------------------------------------------------------- + +ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings, TMap *copiedNodesList); +void TreeNodeDeepCopy_Base(ZCC_AST *ast, ZCC_TreeNode *orig, ZCC_TreeNode *copy, bool copySiblings, TMap *copiedNodesList) +{ + copy->SourceName = orig->SourceName; + copy->SourceLump = orig->SourceLump; + copy->SourceLoc = orig->SourceLoc; + copy->NodeType = orig->NodeType; + + if (copySiblings) + { + auto node = orig->SiblingNext; + while (node != orig) + { + auto nextNode = TreeNodeDeepCopy_Internal(ast, node, false, copiedNodesList); + auto newLast = nextNode->SiblingPrev; + + auto firstNode = copy; + auto lastNode = firstNode->SiblingPrev; + + lastNode->SiblingNext = nextNode; + firstNode->SiblingPrev = newLast; + + nextNode->SiblingPrev = lastNode; + newLast->SiblingNext = firstNode; + + node = node->SiblingNext; + } + } +} + +#define GetTreeNode(type) static_cast(ast->InitNode(sizeof(ZCC_##type), AST_##type, nullptr)); +#define TreeNodeDeepCopy_Start(type) \ + auto copy = GetTreeNode(type); \ + auto origCasted = static_cast(orig); \ + ret = copy; \ + copiedNodesList->Insert(orig, ret); + +ZCC_TreeNode *TreeNodeDeepCopy(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings) +{ + TMap copiedNodesList; + copiedNodesList.Clear(); + + return TreeNodeDeepCopy_Internal(ast, orig, copySiblings, &copiedNodesList); +} + +ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings, TMap *copiedNodesList) +{ + // [pbeta] This is a legitimate case as otherwise this function would need + // an excessive amount of "if" statements, so just return null. + if (orig == nullptr) + { + return nullptr; + } + + // [pbeta] We need to keep and check a list of already copied nodes, because + // some are supposed to be the same, and it can cause infinite loops. + auto existingCopy = copiedNodesList->CheckKey(orig); + if (existingCopy != nullptr) + { + return *existingCopy; + } + + ZCC_TreeNode *ret = nullptr; + + switch (orig->NodeType) + { + case AST_Identifier: + { + TreeNodeDeepCopy_Start(Identifier); + + // ZCC_Identifier + copy->Id = origCasted->Id; + + break; + } + + case AST_Struct: + { + TreeNodeDeepCopy_Start(Struct); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_Struct + copy->Flags = origCasted->Flags; + copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList); + copy->Type = origCasted->Type; + copy->Version = origCasted->Version; + + break; + } + + case AST_Class: + { + TreeNodeDeepCopy_Start(Class); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_Struct + copy->Flags = origCasted->Flags; + copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList); + copy->Type = origCasted->Type; + copy->Version = origCasted->Version; + // ZCC_Class + copy->ParentName = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ParentName, true, copiedNodesList)); + copy->Replaces = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Replaces, true, copiedNodesList)); + + break; + } + + case AST_Enum: + { + TreeNodeDeepCopy_Start(Enum); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_Enum + copy->EnumType = origCasted->EnumType; + copy->Elements = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Elements, false, copiedNodesList)); + + break; + } + + case AST_EnumTerminator: + { + TreeNodeDeepCopy_Start (EnumTerminator); + break; + } + + case AST_States: + { + TreeNodeDeepCopy_Start(States); + + // ZCC_States + copy->Body = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList)); + copy->Flags = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Flags, true, copiedNodesList)); + + break; + } + + case AST_StatePart: + { + TreeNodeDeepCopy_Start (StatePart); + break; + } + + case AST_StateLabel: + { + TreeNodeDeepCopy_Start(StateLabel); + + // ZCC_StateLabel + copy->Label = origCasted->Label; + + break; + } + + case AST_StateStop: + { + TreeNodeDeepCopy_Start (StateStop); + break; + } + + case AST_StateWait: + { + TreeNodeDeepCopy_Start (StateWait); + break; + } + + case AST_StateFail: + { + TreeNodeDeepCopy_Start (StateFail); + break; + } + + case AST_StateLoop: + { + TreeNodeDeepCopy_Start (StateLoop); + break; + } + + case AST_StateGoto: + { + TreeNodeDeepCopy_Start(StateGoto); + + // ZCC_StateGoto + copy->Qualifier = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Qualifier, true, copiedNodesList)); + copy->Label = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Label, true, copiedNodesList)); + copy->Offset = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Offset, true, copiedNodesList)); + + break; + } + + case AST_StateLine: + { + TreeNodeDeepCopy_Start(StateLine); + + // ZCC_StateLine + copy->Sprite = origCasted->Sprite; + + copy->bBright = origCasted->bBright; + copy->bFast = origCasted->bFast; + copy->bSlow = origCasted->bSlow; + copy->bNoDelay = origCasted->bNoDelay; + copy->bCanRaise = origCasted->bCanRaise; + + copy->Frames = origCasted->Frames; + copy->Duration = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Duration, true, copiedNodesList)); + copy->Offset = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Offset, true, copiedNodesList)); + copy->Lights = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Lights, true, copiedNodesList)); + copy->Action = TreeNodeDeepCopy_Internal(ast, origCasted->Action, true, copiedNodesList); + + break; + } + + case AST_VarName: + { + TreeNodeDeepCopy_Start(VarName); + + // ZCC_VarName + copy->Name = origCasted->Name; + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + + break; + } + + case AST_VarInit: + { + TreeNodeDeepCopy_Start(VarInit); + + // ZCC_VarName + copy->Name = origCasted->Name; + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + // ZCC_VarInit + copy->Init = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Init, true, copiedNodesList)); + copy->InitIsArray = origCasted->InitIsArray; + + break; + } + + case AST_Type: + { + TreeNodeDeepCopy_Start(Type); + + // ZCC_Type + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + + break; + } + + case AST_BasicType: + { + TreeNodeDeepCopy_Start(BasicType); + + // ZCC_Type + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + // ZCC_BasicType + copy->Type = origCasted->Type; + copy->UserType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->UserType, true, copiedNodesList)); + copy->isconst = origCasted->isconst; + + break; + } + + case AST_MapType: + { + TreeNodeDeepCopy_Start(MapType); + + // ZCC_Type + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + // ZCC_MapType + copy->KeyType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList)); + copy->ValueType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList)); + + break; + } + + case AST_DynArrayType: + { + TreeNodeDeepCopy_Start(DynArrayType); + + // ZCC_Type + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + // ZCC_DynArrayType + copy->ElementType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ElementType, true, copiedNodesList)); + + break; + } + + case AST_ClassType: + { + TreeNodeDeepCopy_Start(ClassType); + + // ZCC_Type + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + // ZCC_ClassType + copy->Restriction = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Restriction, true, copiedNodesList)); + + break; + } + + case AST_Expression: + { + TreeNodeDeepCopy_Start(Expression); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + + break; + } + + case AST_ExprID: + { + TreeNodeDeepCopy_Start(ExprID); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprID + copy->Identifier = origCasted->Identifier; + + break; + } + + case AST_ExprTypeRef: + { + TreeNodeDeepCopy_Start(ExprTypeRef); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprTypeRef + copy->RefType = origCasted->RefType; + + break; + } + + case AST_ExprConstant: + { + TreeNodeDeepCopy_Start(ExprConstant); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprConstant + // Currently handled: StringVal, IntVal and DoubleVal. (UIntVal appears to be completely unused.) + if (origCasted->Type == TypeString) + { + copy->StringVal = origCasted->StringVal; + } + else if (origCasted->Type == TypeFloat64 || origCasted->Type == TypeFloat32) + { + copy->DoubleVal = origCasted->DoubleVal; + } + else if (origCasted->Type == TypeName || origCasted->Type->isIntCompatible()) + { + copy->IntVal = origCasted->IntVal; + } + + break; + } + + case AST_ExprFuncCall: + { + TreeNodeDeepCopy_Start(ExprFuncCall); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprFuncCall + copy->Function = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Function, true, copiedNodesList)); + copy->Parameters = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Parameters, true, copiedNodesList)); + + break; + } + + case AST_ExprMemberAccess: + { + TreeNodeDeepCopy_Start(ExprMemberAccess); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprMemberAccess + copy->Left = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList)); + copy->Right = origCasted->Right; + + break; + } + + case AST_ExprUnary: + { + TreeNodeDeepCopy_Start(ExprUnary); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprUnary + copy->Operand = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Operand, true, copiedNodesList)); + + break; + } + + case AST_ExprBinary: + { + TreeNodeDeepCopy_Start(ExprBinary); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprBinary + copy->Left = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList)); + copy->Right = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Right, true, copiedNodesList)); + + break; + } + + case AST_ExprTrinary: + { + TreeNodeDeepCopy_Start(ExprTrinary); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ExprTrinary + copy->Test = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Test, true, copiedNodesList)); + copy->Left = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList)); + copy->Right = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Right, true, copiedNodesList)); + + break; + } + + case AST_FuncParm: + { + TreeNodeDeepCopy_Start(FuncParm); + + // ZCC_FuncParm + copy->Value = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Value, true, copiedNodesList)); + copy->Label = origCasted->Label; + + break; + } + + case AST_Statement: + { + TreeNodeDeepCopy_Start (Statement); + break; + } + + case AST_CompoundStmt: + { + TreeNodeDeepCopy_Start(CompoundStmt); + + // ZCC_CompoundStmt + copy->Content = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList)); + + break; + } + + case AST_ContinueStmt: + { + TreeNodeDeepCopy_Start (ContinueStmt); + break; + } + + case AST_BreakStmt: + { + TreeNodeDeepCopy_Start (BreakStmt); + break; + } + + case AST_ReturnStmt: + { + TreeNodeDeepCopy_Start(ReturnStmt); + + // ZCC_ReturnStmt + copy->Values = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList)); + + break; + } + + case AST_ExpressionStmt: + { + TreeNodeDeepCopy_Start(ExpressionStmt); + + // ZCC_ExpressionStmt + copy->Expression = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Expression, true, copiedNodesList)); + + break; + } + + case AST_IterationStmt: + { + TreeNodeDeepCopy_Start(IterationStmt); + + // ZCC_IterationStmt + copy->LoopCondition = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopCondition, true, copiedNodesList)); + copy->LoopStatement = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList)); + copy->LoopBumper = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopBumper, true, copiedNodesList)); + copy->CheckAt = origCasted->CheckAt; + + break; + } + + case AST_IfStmt: + { + TreeNodeDeepCopy_Start(IfStmt); + + // ZCC_IfStmt + copy->Condition = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList)); + copy->TruePath = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->TruePath, true, copiedNodesList)); + copy->FalsePath = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->FalsePath, true, copiedNodesList)); + + break; + } + + case AST_SwitchStmt: + { + TreeNodeDeepCopy_Start(SwitchStmt); + + // ZCC_SwitchStmt + copy->Condition = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList)); + copy->Content = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList)); + + break; + } + + case AST_CaseStmt: + { + TreeNodeDeepCopy_Start(CaseStmt); + + // ZCC_CaseStmt + copy->Condition = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList)); + + break; + } + + case AST_AssignStmt: + { + TreeNodeDeepCopy_Start(AssignStmt); + + // ZCC_AssignStmt + copy->Dests = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Dests, true, copiedNodesList)); + copy->Sources = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Sources, true, copiedNodesList)); + copy->AssignOp = origCasted->AssignOp; + + break; + } + + case AST_LocalVarStmt: + { + TreeNodeDeepCopy_Start(LocalVarStmt); + + // ZCC_LocalVarStmt + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Vars = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Vars, true, copiedNodesList)); + + break; + } + + case AST_FuncParamDecl: + { + TreeNodeDeepCopy_Start(FuncParamDecl); + + // ZCC_FuncParamDecl + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Default = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Default, true, copiedNodesList)); + copy->Name = origCasted->Name; + copy->Flags = origCasted->Flags; + + break; + } + + case AST_ConstantDef: + { + TreeNodeDeepCopy_Start(ConstantDef); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_ConstantDef + copy->Value = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Value, true, copiedNodesList)); + copy->Symbol = origCasted->Symbol; + if (copy->Symbol != nullptr) + { + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + } + + break; + } + + case AST_Declarator: + { + TreeNodeDeepCopy_Start(Declarator); + + // ZCC_Declarator + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Flags = origCasted->Flags; + copy->Version = origCasted->Version; + + break; + } + + case AST_VarDeclarator: + { + TreeNodeDeepCopy_Start(VarDeclarator); + + // ZCC_Declarator + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Flags = origCasted->Flags; + copy->Version = origCasted->Version; + // ZCC_VarDeclarator + copy->Names = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Names, true, copiedNodesList)); + copy->DeprecationMessage = origCasted->DeprecationMessage; + + break; + } + + case AST_FuncDeclarator: + { + TreeNodeDeepCopy_Start(FuncDeclarator); + + // ZCC_Declarator + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Flags = origCasted->Flags; + copy->Version = origCasted->Version; + // ZCC_FuncDeclarator + copy->Params = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Params, true, copiedNodesList)); + copy->Name = origCasted->Name; + copy->Body = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList)); + copy->UseFlags = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->UseFlags, true, copiedNodesList)); + copy->DeprecationMessage = origCasted->DeprecationMessage; + + break; + } + + case AST_Default: + { + TreeNodeDeepCopy_Start(Default); + + // ZCC_CompoundStmt + copy->Content = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList)); + + break; + } + + case AST_FlagStmt: + { + TreeNodeDeepCopy_Start(FlagStmt); + + // ZCC_FlagStmt + copy->name = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->name, true, copiedNodesList)); + copy->set = origCasted->set; + + break; + } + + case AST_PropertyStmt: + { + TreeNodeDeepCopy_Start(PropertyStmt); + + // ZCC_PropertyStmt + copy->Prop = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Prop, true, copiedNodesList)); + copy->Values = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList)); + + break; + } + + case AST_VectorValue: + { + TreeNodeDeepCopy_Start(VectorValue); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_VectorValue + copy->X = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->X, true, copiedNodesList)); + copy->Y = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Y, true, copiedNodesList)); + copy->Z = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Z, true, copiedNodesList)); + + break; + } + + case AST_DeclFlags: + { + TreeNodeDeepCopy_Start(DeclFlags); + + // ZCC_DeclFlags + copy->Id = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Id, true, copiedNodesList)); + copy->DeprecationMessage = origCasted->DeprecationMessage; + copy->Version = origCasted->Version; + copy->Flags = origCasted->Flags; + + break; + } + + case AST_ClassCast: + { + TreeNodeDeepCopy_Start(ClassCast); + + // ZCC_Expression + copy->Operation = origCasted->Operation; + copy->Type = origCasted->Type; + // ZCC_ClassCast + copy->ClassName = origCasted->ClassName; + copy->Parameters = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Parameters, true, copiedNodesList)); + + break; + } + + case AST_StaticArrayStatement: + { + TreeNodeDeepCopy_Start(StaticArrayStatement); + + // ZCC_StaticArrayStatement + copy->Type = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList)); + copy->Id = origCasted->Id; + copy->Values = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList)); + + break; + } + + case AST_Property: + { + TreeNodeDeepCopy_Start(Property); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_Property + copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList); + + break; + } + + case AST_FlagDef: + { + TreeNodeDeepCopy_Start(FlagDef); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_FlagDef + copy->RefName = origCasted->RefName; + copy->BitValue = origCasted->BitValue; + + break; + } + + case AST_MixinDef: + { + TreeNodeDeepCopy_Start(MixinDef); + + // ZCC_NamedNode + copy->NodeName = origCasted->NodeName; + copy->Symbol = origCasted->Symbol; + // ZCC_MixinDef + copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList); + copy->MixinType = origCasted->MixinType; + + break; + } + + case AST_MixinStmt: + { + TreeNodeDeepCopy_Start(MixinStmt); + + // ZCC_MixinStmt + copy->MixinName = origCasted->MixinName; + + break; + } + + default: + assert(0 && "Unimplemented node type"); + break; + } + + TreeNodeDeepCopy_Base(ast, orig, ret, copySiblings, copiedNodesList); + + return ret; +} \ No newline at end of file diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index b5507f6af..3b0e9eb19 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -76,6 +76,7 @@ enum // Syntax tree structures. +// [pbeta] Any changes to AST node structure or new node types require TreeNodeDeepCopy in zcc_parser.cpp to be updated! enum EZCCTreeNodeType { AST_Identifier, @@ -386,6 +387,8 @@ struct ZCC_ExprTypeRef : ZCC_Expression struct ZCC_ExprConstant : ZCC_Expression { + // [pbeta] The ZCC_ExprConstant case in TreeNodeDeepCopy in zcc_parser.cpp + // must be updated if this union is changed! union { FString *StringVal; @@ -611,4 +614,8 @@ struct ZCCParseState : public ZCC_AST FScanner *sc; }; +const char *GetMixinTypeString(EZCCMixinType type); + +ZCC_TreeNode *TreeNodeDeepCopy(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings); + #endif