Пример #1
0
        /// <summary>
        /// Decode an XML list of variables and add the variables to the worksapce.
        /// </summary>
        /// <param name="xmlVariables"> xmlVariables List of XML vale elements.riab</param>
        /// <param name="workspace"> The worksapce to which the variable should be added</param>
        public static void DomToVariables(XmlNode xmlVariables, Workspace workspace)
        {
            for (int i = 0; i < xmlVariables.ChildNodes.Count; i++)
            {
                XmlNode xmlChild = xmlVariables.ChildNodes[i];
                var     type     = xmlChild.GetAttribute("type");
                var     id       = xmlChild.GetAttribute("id");
                var     name     = xmlChild.InnerXml;

                if (type == null)
                {
                    throw new Exception("Variable with id, " + id + " is without a type");
                }
                workspace.CreateVariable(name, type, id);
            }
        }
Пример #2
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));
        }
Пример #3
0
        /// <summary>
        /// Decode an XML block tag and crete a block (and possbly sub blocks) on the
        /// workspace.
        /// </summary>
        /// <param name="xmlBlock"> XML block element.</param>
        /// <param name="workspace"> The workspace</param>
        public static Block DomToBlockHeadless(XmlNode xmlBlock, Workspace workspace)
        {
            var   prototypeName = xmlBlock.GetAttribute("type");
            var   id            = xmlBlock.GetAttribute("id");
            Block block         = workspace.NewBlock(prototypeName, id);
            Block blockChild    = null;

            for (var i = 0; i < xmlBlock.ChildNodes.Count; i++)
            {
                var xmlChild = xmlBlock.ChildNodes[i];
                if (xmlChild.NodeType == (XmlNodeType)3)
                {
                    // Ignore any text at the <block>level. It's all whitespace anyway.
                    continue;
                }
                Input input = null;
                // Find any enclosed blocks or shadows in this tag.
                XmlNode childBlockNode  = null;
                XmlNode childShadowNode = null;
                for (var j = 0; j < xmlChild.ChildNodes.Count; j++)
                {
                    var grandchildNode = xmlChild.ChildNodes[j];
                    if (grandchildNode.NodeType == (XmlNodeType)1)
                    {
                        if (string.Equals(grandchildNode.NodeName().ToLower(), "block"))
                        {
                            childBlockNode = grandchildNode;
                        }
                        else if (string.Equals(grandchildNode.NodeName().ToLower(), "shadow"))
                        {
                            childShadowNode = grandchildNode;
                        }
                    }
                }
                // Use the shadow block if there is no child block.
                if (null == childBlockNode && null != childShadowNode)
                {
                    childBlockNode = childShadowNode;
                }

                var name = xmlChild.GetAttribute("name");
                switch (xmlChild.NodeName().ToLower())
                {
                case "mutation":
                    // Custom data for an advanced block.
                    if (block.Mutator != null)
                    {
                        block.Mutator.FromXml((XmlElement)xmlChild);
                    }
                    break;

                case "data":
                    block.Data = xmlChild.TextContent();
                    break;

                case "title":
                case "field":
                {
                    var field = block.GetField(name);
                    var text  = xmlChild.TextContent();
                    if (field is FieldVariable)
                    {
                        // TODO (marisaleung): When we change setValue and getValue to
                        // interact with id's instead of names,update this so that we get
                        // the variable based on id instead of textContent.
                        var type = string.IsNullOrEmpty(xmlChild.GetAttribute("variableType"))
                                ? xmlChild.GetAttribute("variableType")
                                : "";
                        var variable = workspace.GetVariable(text);
                        if (null == variable)
                        {
                            variable = workspace.CreateVariable(text, type, xmlChild.GetAttribute(id));
                        }

                        if (!string.IsNullOrEmpty(type))
                        {
                            if (!string.Equals(variable.Type, type))
                            {
                                throw new Exception("Serialized variable type with id \'" +
                                                    variable.ID + "\' had type " + variable.Type + ", and " +
                                                    "does not match variable field that references it: " +
                                                    Xml.DomToText(xmlChild) + ".");
                            }
                        }
                    }

                    if (null == field)
                    {
                        Console.WriteLine("Ignoring non-existent field " + name + " in block " + prototypeName);
                        break;
                    }
                    field.SetValue(text);
                }
                break;

                case "value":
                case "statement":
                    input = block.GetInput(name);
                    if (null == input)
                    {
                        Console.WriteLine("Ignoring non-existent input " + name + " in block " +
                                          prototypeName);
                        break;
                    }
                    if (null != childShadowNode)
                    {
//                            input.connection.setShadowDom(childShadowNode);
                    }
                    if (null != childBlockNode)
                    {
                        blockChild = Xml.DomToBlockHeadless(childBlockNode, workspace);
                        if (null != blockChild.OutputConnection)
                        {
                            input.Connection.Connect(blockChild.OutputConnection);
                        }
                        else if (null != blockChild.PreviousConnection)
                        {
                            input.Connection.Connect(blockChild.PreviousConnection);
                        }
                        else
                        {
                            throw new Exception("Child block does not have output or previous statement.");
                        }
                    }
                    break;

                case "next":
                    if (null != childShadowNode && null != block.NextConnection)
                    {
//                            block.nextConnection.setShadowDom(childShadowNode);
                    }
                    if (null != childBlockNode)
                    {
                        blockChild = Xml.DomToBlockHeadless(childBlockNode, workspace);
                        block.NextConnection.Connect(blockChild.PreviousConnection);
                    }
                    break;

                default:
                    // Unknown tag; ignore. Same principle as HTML parsers.
                    Console.WriteLine("Ignoring unknown tag: " + xmlChild.NodeName());
                    break;
                }
            }

            var inline = xmlBlock.GetAttribute("inline");

            if (!string.IsNullOrEmpty(inline))
            {
                block.SetInputsInline(string.Equals(inline, "true"));
            }
            var disabled = xmlBlock.GetAttribute("disabled");

            if (!string.IsNullOrEmpty(disabled))
            {
                block.Disabled = string.Equals(disabled, "true");
            }

            var deletable = xmlBlock.GetAttribute("deletable");

            if (!string.IsNullOrEmpty(deletable))
            {
                block.Deletable = string.Equals(deletable, "true");
            }

            var movable = xmlBlock.GetAttribute("movable");

            if (!string.IsNullOrEmpty(movable))
            {
                block.Movable = string.Equals(movable, "true");
            }

            var editable = xmlBlock.GetAttribute("editable");

            if (!string.IsNullOrEmpty(editable))
            {
                block.Editable = string.Equals(editable, "true");
            }

            var collapsed = xmlBlock.GetAttribute("collapsed");

            if (!string.IsNullOrEmpty(collapsed))
            {
                block.Collapsed = string.Equals(collapsed, "true");
            }
            return(block);
        }