Пример #1
0
        /// <summary>
        /// Update the cached ASTs in the subtree given the modified ASTs
        /// </summary>
        /// <param name="st"></param>
        /// <param name="modifiedASTList"></param>
        private void UpdateCachedASTList(Subtree st, List<AssociativeNode> modifiedASTList)
        {
            // Disable removed nodes from the cache
            Subtree oldSubTree;
            bool cachedTreeExists = currentSubTreeList.TryGetValue(st.GUID, out oldSubTree);

            if (cachedTreeExists && oldSubTree.AstNodes != null)
            {
                List<AssociativeNode> removedNodes = null;
                if (st.IsInput)
                {
                    removedNodes = GetInactiveASTList(oldSubTree.AstNodes, st.AstNodes);
                    (modifiedASTList[0] as BinaryExpressionNode).OriginalAstID = (removedNodes[0] as BinaryExpressionNode).OriginalAstID;
                }
                else if (!st.ForceExecution)
                {
                    removedNodes = GetInactiveASTList(oldSubTree.AstNodes, st.AstNodes);
                    // We only need the removed binary ASTs
                    // Function definitions are handled in ChangeSetData.RemovedFunctionDefNodesFromModification
                    csData.RemovedBinaryNodesFromModification.AddRange(removedNodes.Where(n => n is BinaryExpressionNode));
                }

                foreach (var removedAST in csData.RemovedBinaryNodesFromModification)
                {
                    core.BuildStatus.ClearWarningsForAst(removedAST.ID);
                    runtimeCore.RuntimeStatus.ClearWarningsForAst(removedAST.ID);
                }
            }

            // Cache the modifed functions
            //var modifiedFunctions = st.AstNodes.Where(n => n is FunctionDefinitionNode);
            var modifiedFunctions = modifiedASTList.Where(n => n is FunctionDefinitionNode);
            csData.ModifiedFunctions.AddRange(modifiedFunctions);

            // Handle cached subtree
            if (!cachedTreeExists)
            {
                // Cache the subtree if it does not exist yet
                // This scenario is possible if a subtree was deleted and the same subtree was added again as a modified subtree
                currentSubTreeList.Add(st.GUID, st);
            }
            else
            {
                if (null == oldSubTree.AstNodes)
                {
                    // The ast list for this subtree is null
                    // This is due to the liverunner being passed an empty astlist, such as a codeblock with no content
                    // Populate this subtree with the current ast contents
                    oldSubTree.AstNodes = modifiedASTList;
                    currentSubTreeList[st.GUID] = oldSubTree;
                }
                else
                {
                    if (st.ForceExecution)
                    {
                        // Get the cached AST and append it to the changeSet
                        csData.ForceExecuteASTList.AddRange(GetUnmodifiedASTList(oldSubTree.AstNodes, st.AstNodes));
                    }

                    // Update the cached AST to reflect the change

                    List<AssociativeNode> newCachedASTList = new List<AssociativeNode>();

                    // Get all the unomodified ASTs and append them to the cached ast list 
                    newCachedASTList.AddRange(GetUnmodifiedASTList(oldSubTree.AstNodes, st.AstNodes));

                    // Append all the modified ASTs to the cached ast list 
                    newCachedASTList.AddRange(modifiedASTList);

                    // ================================================================================
                    // Get a list of functions that were removed
                    // This is the list of functions that exist in oldSubTree.AstNodes and no longer exist in st.AstNodes
                    // This will passed to the changeset applier to handle removed functions in the VM
                    // ================================================================================
                    IEnumerable<AssociativeNode> removedFunctions = oldSubTree.AstNodes.Where(f => f is FunctionDefinitionNode && !st.AstNodes.Contains(f));
                    csData.RemovedFunctionDefNodesFromModification.AddRange(removedFunctions);

                    st.AstNodes.Clear();
                    st.AstNodes.AddRange(newCachedASTList);
                    currentSubTreeList[st.GUID] = st;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Gets the only the modified nodes from the subtree by checking of the previous cached instance
        /// </summary>
        /// <param name="subtree"></param>
        /// <returns></returns>
        private List<AssociativeNode> GetModifiedNodes(Subtree subtree, out List<AssociativeNode> modifiedInputAST)
        {
            modifiedInputAST = new List<AssociativeNode>();
            Subtree st;
            if (!currentSubTreeList.TryGetValue(subtree.GUID, out st) || st.AstNodes == null)
            {
                // If the subtree was not cached, it means the cache was delted
                // This means the current subtree is all modified
                return subtree.AstNodes;
            }

            // We want to process only modified statements
            // If the AST is identical to an existing AST in the same GUID, it means it was not modified
            List<AssociativeNode> modifiedASTList = new List<AssociativeNode>();
            foreach (AssociativeNode node in subtree.AstNodes)
            {
                // Check if node exists in the prev AST list
                bool nodeFound = false;
                foreach (AssociativeNode prevNode in st.AstNodes)
                {
                    if (prevNode.Equals(node))
                    {
                        nodeFound = true;
                        break;
                    }
                }
                if (!nodeFound)
                {
                    // At this point, the ast was determined to have been modified
                    // It can then be handled normally regardless of its ForceExecution state
                    subtree.ForceExecution = false;

                    if (st.IsInput)
                    {
                        // An input node is not re-compiled and executed
                        // It is handled by the ChangeSetApply by re-executing the modified node with the updated changes
                        modifiedInputAST.Add(node);
                    }
                    else
                    {
                        modifiedASTList.Add(node);
                        BinaryExpressionNode bnode = node as BinaryExpressionNode;
                        if (null != bnode)
                        {
                            if (bnode.RightNode is LanguageBlockNode)
                            {
                                csData.ModifiedNestedLangBlock.Add(bnode);
                            }
                            else if (bnode.LeftNode is IdentifierNode)
                            {
                                string lhsName = (bnode.LeftNode as IdentifierNode).Name;
                                Validity.Assert(null != lhsName && string.Empty != lhsName);
                                if (CoreUtils.IsSSATemp(lhsName))
                                {
                                    // If the lhs of this binary expression is an SSA temp, and it existed in the lhs of any cached nodes, 
                                    // this means that it was a modified variable within the previous expression.
                                    // Inherit its expression ID 
                                    foreach (AssociativeNode prevNode in st.AstNodes)
                                    {
                                        BinaryExpressionNode prevBinaryNode = prevNode as BinaryExpressionNode;
                                        if (null != prevBinaryNode)
                                        {
                                            IdentifierNode prevIdent = prevBinaryNode.LeftNode as IdentifierNode;
                                            if (null != prevIdent)
                                            {
                                                if (prevIdent.Equals(bnode.LeftNode as IdentifierNode))
                                                {
                                                    bnode.InheritID(prevBinaryNode.ID);
                                                    bnode.ExpressionUID = prevBinaryNode.ExpressionUID;
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    // Handle re-defined lhs expressions
                                    HandleRedefinedLHS(bnode, st.AstNodes);
                                }
                            }
                        }
                    }
                }
            }
            return modifiedASTList;
        }
Пример #3
0
        private IEnumerable<AssociativeNode> GetDeltaAstListDeleted(IEnumerable<Subtree> deletedSubTrees)
        {
            var deltaAstList = new List<AssociativeNode>();

            csData.DeletedBinaryExprASTNodes = new List<AssociativeNode>();
            csData.DeletedFunctionDefASTNodes = new List<AssociativeNode>();

            if (deletedSubTrees != null)
            {
                foreach (var st in deletedSubTrees)
                {
                    if (st.AstNodes != null && st.AstNodes.Count > 0)
                    {
                        csData.DeletedBinaryExprASTNodes.AddRange(st.AstNodes);
                    }
                    else
                    {
                        // Handle the case where only the GUID of the deleted subtree was provided
                        // Get the cached subtree that is now being deleted
                        Subtree removeSubTree = new Subtree();
                        if (currentSubTreeList.TryGetValue(st.GUID, out removeSubTree))
                        {
                            if (removeSubTree.AstNodes != null)
                            {
                                csData.DeletedBinaryExprASTNodes.AddRange(removeSubTree.AstNodes);
                            }
                        }
                    }

                    // Cache removed function definitions
                    Subtree oldSubTree;
                    if (currentSubTreeList.TryGetValue(st.GUID, out oldSubTree))
                    {
                        if (oldSubTree.AstNodes != null)
                        {
                            csData.DeletedFunctionDefASTNodes.AddRange(oldSubTree.AstNodes.Where(n => n is FunctionDefinitionNode));
                        }
                        currentSubTreeList.Remove(st.GUID);
                    }

                    // Build the nullify ASTs
                    var nullNodes = BuildNullAssignments(csData.DeletedBinaryExprASTNodes);
                    deltaAstList.AddRange(nullNodes);

                    foreach (AssociativeNode node in deltaAstList)
                    {
                        var bnode = node as BinaryExpressionNode;
                        if (bnode != null)
                        {
                            bnode.guid = st.GUID;
                        }
                    }

                    core.BuildStatus.ClearWarningsForGraph(st.GUID);

                    runtimeCore.RuntimeStatus.ClearWarningsForGraph(st.GUID);
                }
            }
            return deltaAstList;
        }
Пример #4
0
        [Test]
        public void RegressMAGN5353()
        {
            // This test case tries to verify that when a FFI object is deleted, 
            // the corresponding _Dispose() should be invoked.
            //
            // It is for defect http://adsk-oss.myjetbrains.com/youtrack/issue/MAGN-5353
            var added = new List<Subtree>();

            var guid1 = Guid.NewGuid();
            var code1 = @"import(""FFITarget.dll""); x = DisposeTracer(); DisposeTracer.DisposeCount = 0;";
            added.Add(ProtoTestFx.TD.TestFrameWork.CreateSubTreeFromCode(guid1, code1));

            var guid2 = Guid.NewGuid();
            var code2 = "y = DisposeTracer.DisposeCount;";
            added.Add(ProtoTestFx.TD.TestFrameWork.CreateSubTreeFromCode(guid2, code2));

            // Verify that UpateCount is only called once
            var syncData = new GraphSyncData(null, added, null);
            liveRunner.UpdateGraph(syncData);
            AssertValue("y", 0);

            // Modify CBN2 
            Subtree subtree = new Subtree(new List<AssociativeNode>{}, guid1);
            List<Subtree> deleted = new List<Subtree>();
            deleted.Add(subtree);

            var guid3 = Guid.NewGuid();
            var code3 = "__GC();";
            syncData = new GraphSyncData(deleted, new List<Subtree> { ProtoTestFx.TD.TestFrameWork.CreateSubTreeFromCode(guid3, code3)}, null);
            liveRunner.UpdateGraph(syncData);
            AssertValue("y", 1);
Пример #5
0
        private bool VerifyGraphSyncData(IEnumerable<NodeModel> nodes)
        {
            GraphSyncData graphSyncdata = syncDataManager.GetSyncData();
            syncDataManager.ResetStates();

            var reExecuteNodesIds = new HashSet<Guid>(
                nodes.Where(n => n.NeedsForceExecution)
                     .Select(n => n.GUID));

            if (reExecuteNodesIds.Any())
            {
                for (int i = 0; i < graphSyncdata.ModifiedSubtrees.Count; ++i)
                {
                    var st = graphSyncdata.ModifiedSubtrees[i];
                    if (reExecuteNodesIds.Contains(st.GUID))
                    {
                        Subtree newSt = new Subtree(st.AstNodes, st.GUID);
                        newSt.ForceExecution = true;
                        graphSyncdata.ModifiedSubtrees[i] = newSt;
                    }
                }
            }

            if (graphSyncdata.AddedSubtrees.Any() || graphSyncdata.ModifiedSubtrees.Any() || graphSyncdata.DeletedSubtrees.Any())
            {
                lock (graphSyncDataQueue)
                {
                    graphSyncDataQueue.Enqueue(graphSyncdata);
                }
                return true;
            }

            return false;
        }
Пример #6
0
        private bool VerifyGraphSyncData()
        {
            GraphSyncData data = syncDataManager.GetSyncData();
            syncDataManager.ResetStates();

            var reExecuteNodesIds = controller.DynamoViewModel.Model.HomeSpace.Nodes
                                                                    .Where(n => n.ForceReExecuteOfNode)
                                                                    .Select(n => n.GUID);
            if (reExecuteNodesIds.Any() && data.ModifiedSubtrees != null)
            {
                for (int i = 0; i < data.ModifiedSubtrees.Count; ++i)
                {
                    var st = data.ModifiedSubtrees[i];
                    if (reExecuteNodesIds.Contains(st.GUID))
                    {
                        Subtree newSt = new Subtree(st.AstNodes, st.GUID);
                        newSt.ForceExecution = true;
                        data.ModifiedSubtrees[i] = newSt;
                    }
                }
            }

            if ((data.AddedSubtrees != null && data.AddedSubtrees.Count > 0) ||
                (data.ModifiedSubtrees != null && data.ModifiedSubtrees.Count > 0) ||
                (data.DeletedSubtrees != null && data.DeletedSubtrees.Count > 0))
            {
                lock (graphSyncDataQueue)
                {
                    graphSyncDataQueue.Enqueue(data);
                }
                return true;
            }

            return false;
        }
Пример #7
0
        /// <summary>
        /// Gets the only the modified nodes from the subtree by checking of the previous cached instance
        /// </summary>
        /// <param name="subtree"></param>
        /// <returns></returns>
        private List<AssociativeNode> GetModifiedNodes(Subtree subtree)
        {
            Subtree st;
            if (!currentSubTreeList.TryGetValue(subtree.GUID, out st) || st.AstNodes == null)
            {
                // If the subtree was not cached, it means the cache was delted
                // This means the current subtree is all modified
                return subtree.AstNodes;
            }

            // We want to process only modified statements
            // If the AST is identical to an existing AST in the same GUID, it means it was not modified
            List<AssociativeNode> modifiedASTList = new List<AssociativeNode>();
            foreach (AssociativeNode node in subtree.AstNodes)
            {
                // Check if node exists in the prev AST list
                bool nodeFound = false;
                if (!subtree.ForceExecution)
                {
                    foreach (AssociativeNode prevNode in st.AstNodes)
                    {
                        if (prevNode.Equals(node))
                        {
                            nodeFound = true;
                            break;
                        }
                    }
                }

                if (!nodeFound)
                {
                    // node is modifed as it does not match any existing
                    modifiedASTList.Add(node);

                    BinaryExpressionNode bnode = node as BinaryExpressionNode;
                    if (null != bnode && bnode.LeftNode is IdentifierNode)
                    {
                        string lhsName = (bnode.LeftNode as IdentifierNode).Name;
                        Validity.Assert(null != lhsName && string.Empty != lhsName);
                        if (CoreUtils.IsSSATemp(lhsName))
                        {
                            // If the lhs of this binary expression is an SSA temp, and it existed in the lhs of any cached nodes,
                            // this means that it was a modified variable within the previous expression.
                            // Inherit its expression ID
                            foreach (AssociativeNode prevNode in st.AstNodes)
                            {
                                BinaryExpressionNode prevBinaryNode = prevNode as BinaryExpressionNode;
                                if (null != prevBinaryNode)
                                {
                                    IdentifierNode prevIdent = prevBinaryNode.LeftNode as IdentifierNode;
                                    if (null != prevIdent)
                                    {
                                        if (prevIdent.Equals(bnode.LeftNode as IdentifierNode))
                                        {
                                            bnode.InheritID(prevBinaryNode.ID);
                                            bnode.exprUID = prevBinaryNode.exprUID;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Handle re-defined lhs expressions
                            HandleRedefinedLHS(bnode, st.AstNodes);
                        }
                    }
                }
            }
            return modifiedASTList;
        }