Example #1
0
        /// <summary>
        /// Updates all blocks related to a specific procedure with respect to name, arguments, and
        /// whether the definition can contain a statement sequence. If any of the optional arguments are
        /// null, the existing values from the blocks are used.
        /// </summary>
        /// <param name="originalProcedureName">The name of the procedure, before this method.</param>
        /// <param name="updatedProcedure">The info with which to update procedure mutators.</param>
        /// <param name="argIndexUpdates">A list of mappings from original argument index to new index.</param>
        public void MutateProcedure(string originalProcedureName, Procedure updatedProcedure,
                                    List <ProcedureArgumentIndexUpdate> argIndexUpdates = null)
        {
            Block definition = GetDefinitionBlock(originalProcedureName);

            if (definition == null)
            {
                throw new Exception("Unknown procedure \"" + originalProcedureName + "\"");
            }

            List <Block> procedureCalls = GetCallers(originalProcedureName);
            ProcedureDefinitionMutator definitionMutator = definition.Mutator as ProcedureDefinitionMutator;
            Procedure oldInfo = definitionMutator.ProcedureInfo;

            mNameMgr.RemoveDistinctName(originalProcedureName);
            string newProcedureName = mNameMgr.GetDistinctName(updatedProcedure.Name);
            bool   isFuncRename     = !newProcedureName.Equals(originalProcedureName);

            if (isFuncRename)
            {
                mProcedureDefinitions.Remove(originalProcedureName);
                mProcedureDefinitions[newProcedureName] = definition;
                mProcedureCallers.Remove(originalProcedureName);
                mProcedureCallers[newProcedureName] = procedureCalls;
            }

            List <string> newArgs = updatedProcedure.Arguments;

            for (int i = 0; i < newArgs.Count; i++)
            {
                string argName = newArgs[i];
                if (!Names.IsSafe(argName))
                {
                    throw new Exception("Invalid variable name \"" + argName + "\" " + "(argument #" + i + " )");
                }

                // create new variable
                if (!mWorkspace.HasVariable(argName))
                {
                    mWorkspace.CreateVariable(argName);
                }
            }

            definitionMutator.Mutate(updatedProcedure);

            //mutate each procedure call
            foreach (Block procRef in procedureCalls)
            {
                ProcedureCallMutator callMutator = procRef.Mutator as ProcedureCallMutator;
                int     oldArgCount = callMutator.GetArgumentNameList().Count;
                Block[] oldValues   = new Block[oldArgCount];

                //disconnect prior value blocks
                for (int i = 0; i < oldArgCount; i++)
                {
                    Input argInput   = callMutator.GetArgumenInput(i);
                    Block valueBlock = argInput.ConnectedBlock;
                    if (valueBlock != null)
                    {
                        oldValues[i] = valueBlock;
                        argInput.Connection.Disconnect();
                    }
                }

                callMutator.Mutate(updatedProcedure);

                //reconnect any blocks to orginal inputs
                if (argIndexUpdates != null)
                {
                    foreach (ProcedureArgumentIndexUpdate indexUpdate in argIndexUpdates)
                    {
                        Block originalValue = oldValues[indexUpdate.Before];
                        if (originalValue != null)
                        {
                            Input argInput = callMutator.GetArgumenInput(indexUpdate.After);
                            argInput.Connection.Connect(originalValue.OutputConnection);
                        }
                    }
                }
            }

            FireUpdate(new ProcedureUpdateData(oldInfo, updatedProcedure));
        }