Beispiel #1
0
        protected override bool UpdateValueCore(string name, string value, UndoRedoRecorder recorder)
        {
            if (name != "Code")
            {
                return(base.UpdateValueCore(name, value, recorder));
            }

            //Remove the UpdateValue's recording
            recorder.PopFromUndoGroup();

            value = CodeBlockUtils.FormatUserText(value);

            //Since an empty Code Block Node should not exist, this checks for such instances.
            // If an empty Code Block Node is found, it is deleted. Since the creation and deletion of
            // an empty Code Block Node should not be recorded, this method also checks and removes
            // any unwanted recordings
            if (value == "")
            {
                Code = "";
            }
            else
            {
                if (!value.Equals(Code))
                {
                    SetCodeContent(value, recorder);
                }
            }
            return(true);
        }
Beispiel #2
0
        protected override bool UpdateValueCore(UpdateValueParams updateValueParams)
        {
            string          name  = updateValueParams.PropertyName;
            string          value = updateValueParams.PropertyValue;
            ElementResolver workspaceElementResolver = updateValueParams.ElementResolver;

            if (name != "Code")
            {
                return(base.UpdateValueCore(updateValueParams));
            }

            value = CodeBlockUtils.FormatUserText(value);

            //Since an empty Code Block Node should not exist, this checks for such instances.
            // If an empty Code Block Node is found, it is deleted. Since the creation and deletion of
            // an empty Code Block Node should not be recorded, this method also checks and removes
            // any unwanted recordings
            if (value == "")
            {
                Code = "";
            }
            else
            {
                if (!value.Equals(Code))
                {
                    SetCodeContent(value, workspaceElementResolver);
                }
            }
            return(true);
        }
Beispiel #3
0
        private Statement GetStatementForOutput(int portIndex)
        {
            if (State == ElementState.Error)
            {
                return(null);
            }

            // Here the "portIndex" is back mapped to the corresponding "Statement"
            // object. However, not all "Statement" objects produce an output port,
            // so "portIndex" cannot be used directly to index into "codeStatements"
            // list. This loop goes through "codeStatements", decrementing "portIndex"
            // along the way to determine the right "Statement" object matching the
            // port index.
            //
            Statement statement = null;
            var       svs       = CodeBlockUtils.GetStatementVariables(codeStatements, true);

            for (int stmt = 0, port = 0; stmt < codeStatements.Count; stmt++)
            {
                if (CodeBlockUtils.DoesStatementRequireOutputPort(svs, stmt))
                {
                    if (port == portIndex)
                    {
                        statement = codeStatements[stmt];
                        break;
                    }

                    port = port + 1;
                }
            }

            return(statement);
        }
Beispiel #4
0
        private void SetInputPorts()
        {
            // Generate input port data list from the unbound identifiers.
            var inportData = CodeBlockUtils.GenerateInputPortData(inputIdentifiers);

            foreach (var portData in inportData)
            {
                InPortData.Add(portData);
            }
        }
Beispiel #5
0
        /// <summary>
        /// For code block nodes, each output identifier of an output port is mapped.
        /// For an example, "p = 1" would have its internal identifier renamed to
        /// "pXXXX", where "XXXX" is the GUID of the code block node. This mapping is
        /// done to ensure the uniqueness of the output variable name.
        /// </summary>
        /// <param name="portIndex">Output port index</param>
        /// <param name="forRawName">Set this parameter to true to retrieve the
        /// original identifier name "p". If this parameter is false, the mapped
        /// identifer name "pXXXX" is returned instead.</param>
        /// <returns></returns>
        private IdentifierNode GetAstIdentifierForOutputIndexInternal(int portIndex, bool forRawName)
        {
            if (State == ElementState.Error)
            {
                return(null);
            }

            // Here the "portIndex" is back mapped to the corresponding "Statement"
            // object. However, not all "Statement" objects produce an output port,
            // so "portIndex" cannot be used directly to index into "codeStatements"
            // list. This loop goes through "codeStatements", decrementing "portIndex"
            // along the way to determine the right "Statement" object matching the
            // port index.
            //
            Statement statement = null;
            var       svs       = CodeBlockUtils.GetStatementVariables(codeStatements, true);

            for (int stmt = 0, port = 0; stmt < codeStatements.Count; stmt++)
            {
                if (CodeBlockUtils.DoesStatementRequireOutputPort(svs, stmt))
                {
                    if (port == portIndex)
                    {
                        statement = codeStatements[stmt];
                        break;
                    }

                    port = port + 1;
                }
            }

            if (statement == null)
            {
                return(null);
            }

            var binExprNode = statement.AstNode as BinaryExpressionNode;

            if (binExprNode == null || (binExprNode.LeftNode == null))
            {
                return(null);
            }

            var identNode   = binExprNode.LeftNode as IdentifierNode;
            var mappedIdent = NodeUtils.Clone(identNode);

            if (!forRawName)
            {
                MapIdentifiers(mappedIdent);
            }

            return(mappedIdent as IdentifierNode);
        }
Beispiel #6
0
        protected override void DeserializeCore(XmlElement nodeElement, SaveContext context)
        {
            base.DeserializeCore(nodeElement, context);
            var helper = new XmlElementHelper(nodeElement);

            shouldFocus = helper.ReadBoolean("ShouldFocus");
            code        = helper.ReadString("CodeText");

            // Lookup namespace resolution map if available and initialize new instance of ElementResolver
            var resolutionMap = CodeBlockUtils.DeserializeElementResolver(nodeElement);

            ElementResolver = new ElementResolver(resolutionMap);

            ProcessCodeDirect();
        }
Beispiel #7
0
        protected override void DeserializeCore(XmlElement nodeElement, SaveContext context)
        {
            base.DeserializeCore(nodeElement, context);
            foreach (var subNode in
                     nodeElement.ChildNodes.Cast <XmlNode>()
                     .Where(subNode => subNode.Name == "Symbol"))
            {
                InputSymbol = subNode.Attributes[0].Value;
            }

            ArgumentLacing = LacingStrategy.Disabled;

            var resolutionMap = CodeBlockUtils.DeserializeElementResolver(nodeElement);

            elementResolver = new ElementResolver(resolutionMap);
        }
Beispiel #8
0
        /// <summary>
        ///  Returns the corresponding output port index for a given defined variable
        /// </summary>
        /// <param name="variableName"></param>
        /// <returns></returns>
        public int GetOutportIndex(string variableName)
        {
            var svs = CodeBlockUtils.GetStatementVariables(codeStatements, true);

            for (int i = 0; i < codeStatements.Count; i++)
            {
                Statement s = codeStatements[i];
                if (CodeBlockUtils.DoesStatementRequireOutputPort(svs, i))
                {
                    List <string> varNames = Statement.GetDefinedVariableNames(s, true);
                    if (varNames.Contains(variableName))
                    {
                        return(i);
                    }
                }
            }
            return(-1);
        }
Beispiel #9
0
        protected override bool UpdateValueCore(string name, string value)
        {
            if (name == "Code")
            {
                //Remove the UpdateValue's recording
                this.Workspace.UndoRecorder.PopFromUndoGroup();

                //Since an empty Code Block Node should not exist, this checks for such instances.
                // If an empty Code Block Node is found, it is deleted. Since the creation and deletion of
                // an empty Code Block Node should not be recorded, this method also checks and removes
                // any unwanted recordings
                value = CodeBlockUtils.FormatUserText(value);
                if (value == "")
                {
                    if (this.Code == "")
                    {
                        this.Workspace.UndoRecorder.PopFromUndoGroup();
                        Dynamo.Selection.DynamoSelection.Instance.Selection.Remove(this);
                        this.Workspace.Nodes.Remove(this);
                    }
                    else
                    {
                        this.Workspace.RecordAndDeleteModels(new System.Collections.Generic.List <ModelBase>()
                        {
                            this
                        });
                    }
                }
                else
                {
                    if (!value.Equals(this.Code))
                    {
                        Code = value;
                    }
                }
                return(true);
            }

            return(base.UpdateValueCore(name, value));
        }
Beispiel #10
0
        private void SetOutputPorts()
        {
            var allDefs = CodeBlockUtils.GetDefinitionLineIndexMap(codeStatements);

            if (allDefs.Any() == false)
            {
                return;
            }

            double prevPortBottom = 0.0;

            foreach (var def in allDefs)
            {
                var logicalIndex = def.Value - 1;

                string tooltip = def.Key;
                if (tempVariables.Contains(def.Key))
                {
                    tooltip = Formatting.TOOL_TIP_FOR_TEMP_VARIABLE;
                }

                double portCoordsY = Formatting.INITIAL_MARGIN;
                portCoordsY += logicalIndex * Configurations.CodeBlockPortHeightInPixels;

                OutPortData.Add(new PortData(string.Empty, tooltip)
                {
                    VerticalMargin = portCoordsY - prevPortBottom,
                    Height         = Configurations.CodeBlockPortHeightInPixels
                });

                // Since we compute the "delta" between the top of the current
                // port to the bottom of the previous port, we need to record
                // down the bottom coordinate value before proceeding to the next
                // port.
                //
                prevPortBottom = portCoordsY + Configurations.CodeBlockPortHeightInPixels;
            }
        }
Beispiel #11
0
        private void SetOutputPorts()
        {
            var allDefs = CodeBlockUtils.GetDefinitionLineIndexMap(codeStatements);

            if (allDefs.Any() == false)
            {
                return;
            }

            foreach (var def in allDefs)
            {
                string tooltip = def.Key;
                if (tempVariables.Contains(def.Key))
                {
                    tooltip = Formatting.TOOL_TIP_FOR_TEMP_VARIABLE;
                }

                OutPortData.Add(new PortData(string.Empty, tooltip)
                {
                    LineIndex = def.Value - 1, // Logical line index.
                    Height    = Configurations.CodeBlockPortHeightInPixels
                });
            }
        }
Beispiel #12
0
        private void SetOutputPorts()
        {
            // Get all defined variables and their locations
            var definedVars = codeStatements.Select(s => new KeyValuePair <Variable, int>(s.FirstDefinedVariable, s.StartLine))
                              .Where(pair => pair.Key != null)
                              .Select(pair => new KeyValuePair <string, int>(pair.Key.Name, pair.Value))
                              .OrderBy(pair => pair.Key)
                              .GroupBy(pair => pair.Key);

            // Calc each variable's last location of definition
            var locationMap = new Dictionary <string, int>();

            foreach (var defs in definedVars)
            {
                var name = defs.FirstOrDefault().Key;
                var loc  = defs.Select(p => p.Value).Max <int>();
                locationMap[name] = loc;
            }

            // Create output ports
            var allDefs = locationMap.OrderBy(p => p.Value);

            if (allDefs.Any() == false)
            {
                return;
            }

            double prevPortBottom = 0.0;
            var    map            = CodeBlockUtils.MapLogicalToVisualLineIndices(code);

            foreach (var def in allDefs)
            {
                // Map the given logical line index to its corresponding visual
                // line index. Do note that "def.Value" here is the line number
                // supplied by the paser, which uses 1-based line indexing so we
                // have to remove one from the line index.
                //
                var logicalIndex = def.Value - 1;
                var visualIndex  = map.ElementAt(logicalIndex);

                string tooltip = def.Key;
                if (tempVariables.Contains(def.Key))
                {
                    tooltip = Formatting.TOOL_TIP_FOR_TEMP_VARIABLE;
                }

                double portCoordsY = Formatting.INITIAL_MARGIN;
                portCoordsY += visualIndex * Configurations.CodeBlockPortHeightInPixels;

                OutPortData.Add(new PortData(string.Empty, tooltip)
                {
                    VerticalMargin = portCoordsY - prevPortBottom,
                    Height         = Configurations.CodeBlockPortHeightInPixels
                });

                // Since we compute the "delta" between the top of the current
                // port to the bottom of the previous port, we need to record
                // down the bottom coordinate value before proceeding to the next
                // port.
                //
                prevPortBottom = portCoordsY + Configurations.CodeBlockPortHeightInPixels;
            }
        }
Beispiel #13
0
        private void ProcessCode(ref string errorMessage, ref string warningMessage)
        {
            code = CodeBlockUtils.FormatUserText(code);
            codeStatements.Clear();

            if (string.IsNullOrEmpty(Code))
            {
                previewVariable = null;
            }

            try
            {
                var parseParam = new ParseParam(GUID, code);
                if (CompilerUtils.PreCompileCodeBlock(libraryServices.LibraryManagementCore, ref parseParam))
                {
                    if (parseParam.ParsedNodes != null)
                    {
                        // Create an instance of statement for each code statement written by the user
                        foreach (var parsedNode in parseParam.ParsedNodes)
                        {
                            // Create a statement variable from the generated nodes
                            codeStatements.Add(Statement.CreateInstance(parsedNode));
                        }

                        SetPreviewVariable(parseParam.ParsedNodes);
                    }
                }

                if (parseParam.Errors != null && parseParam.Errors.Any())
                {
                    errorMessage = string.Join("\n", parseParam.Errors.Select(m => m.Message));
                    ProcessError();
                    CreateInputOutputPorts();
                    return;
                }

                if (parseParam.Warnings != null)
                {
                    // Unbound identifiers in CBN will have input slots.
                    //
                    // To check function redefinition, we need to check other
                    // CBN to find out if it has been defined yet. Now just
                    // skip this warning.
                    var warnings =
                        parseParam.Warnings.Where(
                            w =>
                            w.ID != WarningID.kIdUnboundIdentifier &&
                            w.ID != WarningID.kFunctionAlreadyDefined);

                    if (warnings.Any())
                    {
                        warningMessage = string.Join("\n", warnings.Select(m => m.Message));
                    }
                }

                if (parseParam.UnboundIdentifiers != null)
                {
                    inputIdentifiers = new List <string>(parseParam.UnboundIdentifiers);
                }
                else
                {
                    inputIdentifiers.Clear();
                }
            }
            catch (Exception e)
            {
                errorMessage    = e.Message;
                previewVariable = null;
                ProcessError();
                return;
            }

            // Set the input and output ports based on the statements
            CreateInputOutputPorts();
        }