Ejemplo n.º 1
0
        /// <summary>
        /// Pre-compiles DS code in code block node,
        /// checks for syntax, converts non-assignments to assignments,
        /// stores list of AST nodes, errors and warnings
        /// Evaluates and stores list of unbound identifiers
        /// </summary>
        /// <param name="priorNames"></param>
        /// <param name="parseParams"> container for compilation related parameters </param>
        /// <param name="elementResolver"> classname resolver </param>
        /// <returns> true if code compilation succeeds, false otherwise </returns>
        public static bool PreCompileCodeBlock(Core core, ref ParseParam parseParams, IDictionary <string, string> priorNames = null)
        {
            string postfixGuid = parseParams.PostfixGuid.ToString().Replace("-", "_");

            // Parse code to generate AST and add temporaries to non-assignment nodes
            List <AssociativeNode> astNodes;
            List <AssociativeNode> comments;

            ParseUserCode(core, parseParams.OriginalCode, postfixGuid, out astNodes, out comments);
            parseParams.AppendErrors(core.BuildStatus.Errors);
            if (parseParams.Errors.Count() > 0)
            {
                return(false);
            }

            // Catch the syntax errors and errors for unsupported
            // language constructs thrown by compile expression
            parseParams.AppendWarnings(core.BuildStatus.Warnings);
            var warnings = Check(astNodes);

            parseParams.AppendWarnings(warnings);

            parseParams.AppendParsedNodes(astNodes.Where(n => !n.skipMe));
            parseParams.AppendComments(comments);

            // Compile the code to get the resultant unboundidentifiers
            // and any errors or warnings that were caught by the compiler and cache them in parseParams
            return(CompileCodeBlockAST(core, parseParams, priorNames));
        }
Ejemplo n.º 2
0
        private static bool CompileCodeBlockAST(Core core, ParseParam parseParams)
        {
            Dictionary <int, List <VariableLine> > unboundIdentifiers = new Dictionary <int, List <VariableLine> >();
            IEnumerable <BuildData.WarningEntry>   warnings           = null;

            ProtoCore.BuildStatus buildStatus = null;
            try
            {
                int                    blockId   = ProtoCore.DSASM.Constants.kInvalidIndex;
                CodeBlockNode          codeblock = new CodeBlockNode();
                List <AssociativeNode> nodes     = new List <AssociativeNode>();
                foreach (var i in parseParams.ParsedNodes)
                {
                    AssociativeNode assocNode = i as AssociativeNode;

                    if (assocNode != null)
                    {
                        nodes.Add(NodeUtils.Clone(assocNode));
                    }
                }
                codeblock.Body.AddRange(nodes);

                bool parsingPreloadFlag = core.IsParsingPreloadedAssembly;
                bool parsingCbnFlag     = core.IsParsingPreloadedAssembly;
                core.IsParsingPreloadedAssembly = false;
                core.IsParsingCodeBlockNode     = true;

                core.ResetForPrecompilation();
                buildStatus = PreCompile(string.Empty, core, codeblock, out blockId);

                core.IsParsingCodeBlockNode     = parsingCbnFlag;
                core.IsParsingPreloadedAssembly = parsingPreloadFlag;

                parseParams.AppendErrors(buildStatus.Errors);
                parseParams.AppendWarnings(buildStatus.Warnings);

                if (buildStatus.ErrorCount > 0)
                {
                    return(false);
                }
                warnings = buildStatus.Warnings;

                // Get the unboundIdentifiers from the warnings
                GetInputLines(parseParams.ParsedNodes, warnings, unboundIdentifiers);
                foreach (KeyValuePair <int, List <VariableLine> > kvp in unboundIdentifiers)
                {
                    foreach (VariableLine vl in kvp.Value)
                    {
                        parseParams.AppendUnboundIdentifier(vl.variable);
                    }
                }

                return(true);
            }
            catch (Exception)
            {
                buildStatus = null;
                return(false);
            }
        }
Ejemplo n.º 3
0
        public void ReproMAGN3603()
        {

            string code = @"a = 1 + (2 * 3);
                            b = (1 + 2) * 3;
                            c = 1 + 2 * 3;";

            ElementResolver elementResolver = new ElementResolver();
            ParseParam parseParam = new ParseParam(Guid.NewGuid(), code, elementResolver);
            
            Assert.IsTrue(CompilerUtils.PreCompileCodeBlock(thisTest.CreateTestCore(), ref parseParam));
            Assert.IsTrue(parseParam.ParsedNodes != null && parseParam.ParsedNodes.Count() > 0);

            var parsedNode = parseParam.ParsedNodes.ElementAt(0);

            BinaryExpressionNode n = parsedNode as BinaryExpressionNode;
            FunctionCallNode funcCall = n.RightNode as FunctionCallNode;
            Assert.IsTrue(n != null && funcCall != null);
            IdentifierNode identNode = funcCall.Function as IdentifierNode;
            Assert.IsTrue(identNode != null && identNode.Value == "%add");
            var args = funcCall.FormalArguments;
            Assert.IsTrue(args.Count == 2);
            Assert.IsTrue(args[0] is IntNode);
            FunctionCallNode nestedFuncCall = args[1] as FunctionCallNode;
            Assert.IsTrue(nestedFuncCall != null && (nestedFuncCall.Function as IdentifierNode).Value == "%mul");

            parsedNode = parseParam.ParsedNodes.ElementAt(1);

            n = parsedNode as BinaryExpressionNode;
            funcCall = n.RightNode as FunctionCallNode;
            Assert.IsTrue(n != null && funcCall != null);
            identNode = funcCall.Function as IdentifierNode;
            Assert.IsTrue(identNode != null && identNode.Value == "%mul");
            args = funcCall.FormalArguments;
            Assert.IsTrue(args.Count == 2);
            Assert.IsTrue(args[1] is IntNode);
            nestedFuncCall = args[0] as FunctionCallNode;
            Assert.IsTrue(nestedFuncCall != null && (nestedFuncCall.Function as IdentifierNode).Value == "%add");

            parsedNode = parseParam.ParsedNodes.ElementAt(2);

            n = parsedNode as BinaryExpressionNode;
            funcCall = n.RightNode as FunctionCallNode;
            Assert.IsTrue(n != null && funcCall != null);
            identNode = funcCall.Function as IdentifierNode;
            Assert.IsTrue(identNode != null && identNode.Value == "%add");
            args = funcCall.FormalArguments;
            Assert.IsTrue(args.Count == 2);
            Assert.IsTrue(args[0] is IntNode);
            nestedFuncCall = args[1] as FunctionCallNode;
            Assert.IsTrue(nestedFuncCall != null && (nestedFuncCall.Function as IdentifierNode).Value == "%mul");
        }
Ejemplo n.º 4
0
        public void TestUnboundIdentifierInUnnamedSignedExpression()
        {
            string code = @"a*-1;";

            ElementResolver elementResolver = new ElementResolver();
            ParseParam parseParam = new ParseParam(Guid.NewGuid(), code, elementResolver);

            Assert.IsTrue(CompilerUtils.PreCompileCodeBlock(thisTest.CreateTestCore(), ref parseParam));
            Assert.IsTrue(parseParam.ParsedNodes != null && parseParam.ParsedNodes.Any());

            var inputIdentifier = parseParam.UnboundIdentifiers;
            Assert.AreEqual(1, inputIdentifier.Count);
            Assert.AreEqual("a", inputIdentifier.ElementAt(0).Value);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Pre-compiles DS code in code block node,
        /// checks for syntax, converts non-assignments to assignments,
        /// stores list of AST nodes, errors and warnings
        /// Evaluates and stores list of unbound identifiers
        /// </summary>
        /// <param name="parseParams"></param>
        /// <returns></returns>
        public static bool PreCompileCodeBlock(Core core, ref ParseParam parseParams)
        {
            string postfixGuid = parseParams.PostfixGuid.ToString().Replace("-", "_");

            // Parse code to generate AST and add temporaries to non-assignment nodes
            IEnumerable <ProtoCore.AST.Node> astNodes = ParseUserCode(core, parseParams.OriginalCode, postfixGuid);

            // Catch the syntax errors and errors for unsupported
            // language constructs thrown by compile expression
            if (core.BuildStatus.ErrorCount > 0)
            {
                parseParams.AppendErrors(core.BuildStatus.Errors);
                parseParams.AppendWarnings(core.BuildStatus.Warnings);
                return(false);
            }
            parseParams.AppendParsedNodes(astNodes);

            // Compile the code to get the resultant unboundidentifiers
            // and any errors or warnings that were caught by the compiler and cache them in parseParams
            return(CompileCodeBlockAST(core, parseParams));
        }
Ejemplo n.º 6
0
        private void ProcessCode(ref string errorMessage, ref string warningMessage, 
            ElementResolver workspaceElementResolver = null)
        {
            code = CodeBlockUtils.FormatUserText(code);
            codeStatements.Clear();

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

            try
            {
                // During loading of CBN from file, the elementResolver from the workspace is unavailable
                // in which case, a local copy of the ER obtained from the CBN is used
                var resolver = workspaceElementResolver ?? this.ElementResolver;
                var parseParam = new ParseParam(GUID, code, resolver);

                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>();
                    inputPortNames = new List<string>();
                    foreach (var kvp in parseParam.UnboundIdentifiers)
                    {
                        inputIdentifiers.Add(kvp.Value);
                        inputPortNames.Add(kvp.Key);
                    }
                }
                else
                {
                    inputIdentifiers.Clear();
                    inputPortNames.Clear();                    
                }
            }
            catch (Exception e)
            {
                errorMessage = e.Message;
                previewVariable = null;
                ProcessError();
                return;
            }

            // Set the input and output ports based on the statements
            CreateInputOutputPorts();
        }
Ejemplo n.º 7
0
        private static bool CompileCodeBlockAST(Core core, ParseParam parseParams, IDictionary <string, string> priorNames)
        {
            var unboundIdentifiers = new Dictionary <int, List <VariableLine> >();

            ProtoCore.BuildStatus buildStatus = null;
            try
            {
                int blockId = ProtoCore.DSASM.Constants.kInvalidIndex;


                bool parsingPreloadFlag = core.IsParsingPreloadedAssembly;
                bool parsingCbnFlag     = core.IsParsingPreloadedAssembly;
                core.IsParsingPreloadedAssembly = false;
                core.IsParsingCodeBlockNode     = true;

                core.ResetForPrecompilation();

                var astNodes = parseParams.ParsedNodes;

                // Lookup namespace resolution map in elementResolver to rewrite
                // partial classnames with their fully qualified names in ASTs
                // before passing them for pre-compilation. If partial class is not found in map,
                // update Resolution map in elementResolver with fully resolved name from compiler.
                var reWrittenNodes = ElementRewriter.RewriteElementNames(core.ClassTable,
                                                                         parseParams.ElementResolver, astNodes, core.BuildStatus.LogSymbolConflictWarning);

                if (priorNames != null)
                {
                    // Use migration rewriter to migrate old method names to new names based on priorNameHints from LibraryServices
                    reWrittenNodes = MigrationRewriter.MigrateMethodNames(reWrittenNodes, priorNames, core.BuildStatus.LogDeprecatedMethodWarning);
                }

                // Clone a disposable copy of AST nodes for PreCompile() as Codegen mutates AST's
                // while performing SSA transforms and we want to keep the original AST's
                var codeblock = new CodeBlockNode();
                var nodes     = reWrittenNodes.OfType <AssociativeNode>().Select(NodeUtils.Clone).ToList();
                codeblock.Body.AddRange(nodes);

                buildStatus = PreCompile(string.Empty, core, codeblock, out blockId);

                core.IsParsingCodeBlockNode     = parsingCbnFlag;
                core.IsParsingPreloadedAssembly = parsingPreloadFlag;

                parseParams.AppendErrors(buildStatus.Errors);
                parseParams.AppendWarnings(buildStatus.Warnings);

                if (buildStatus.ErrorCount > 0)
                {
                    return(false);
                }
                IEnumerable <BuildData.WarningEntry> warnings = buildStatus.Warnings;

                // Get the unboundIdentifiers from the warnings
                GetInputLines(parseParams.ParsedNodes, warnings, unboundIdentifiers);
                foreach (KeyValuePair <int, List <VariableLine> > kvp in unboundIdentifiers)
                {
                    foreach (VariableLine vl in kvp.Value)
                    {
                        parseParams.AppendUnboundIdentifier(vl.displayName, vl.variable);
                    }
                }

                return(true);
            }
            catch (Exception)
            {
                buildStatus = null;
                return(false);
            }
        }
Ejemplo n.º 8
0
        private static bool CompileCodeBlockAST(Core core, ParseParam parseParams)
        {
            var unboundIdentifiers = new Dictionary<int, List<VariableLine>>();

            ProtoCore.BuildStatus buildStatus = null;
            try
            {
                int blockId = ProtoCore.DSASM.Constants.kInvalidIndex;
                

                bool parsingPreloadFlag = core.IsParsingPreloadedAssembly;
                bool parsingCbnFlag = core.IsParsingPreloadedAssembly;
                core.IsParsingPreloadedAssembly = false;
                core.IsParsingCodeBlockNode = true;

                core.ResetForPrecompilation();

                var astNodes = parseParams.ParsedNodes;

                // Lookup namespace resolution map in elementResolver to rewrite 
                // partial classnames with their fully qualified names in ASTs
                // before passing them for pre-compilation. If partial class is not found in map, 
                // update Resolution map in elementResolver with fully resolved name from compiler.
                var reWrittenNodes = ElementRewriter.RewriteElementNames(core.ClassTable,  
                    parseParams.ElementResolver, astNodes, core.BuildStatus.LogSymbolConflictWarning);

                // Clone a disposable copy of AST nodes for PreCompile() as Codegen mutates AST's
                // while performing SSA transforms and we want to keep the original AST's
                var codeblock = new CodeBlockNode();
                var nodes = reWrittenNodes.OfType<AssociativeNode>().Select(NodeUtils.Clone).ToList();
                codeblock.Body.AddRange(nodes);

                buildStatus = PreCompile(string.Empty, core, codeblock, out blockId);

                core.IsParsingCodeBlockNode = parsingCbnFlag;
                core.IsParsingPreloadedAssembly = parsingPreloadFlag;

                parseParams.AppendErrors(buildStatus.Errors);
                parseParams.AppendWarnings(buildStatus.Warnings);

                if (buildStatus.ErrorCount > 0)
                {
                    return false;
                }
                IEnumerable<BuildData.WarningEntry> warnings = buildStatus.Warnings;

                // Get the unboundIdentifiers from the warnings
                GetInputLines(parseParams.ParsedNodes, warnings, unboundIdentifiers);
                foreach (KeyValuePair<int, List<VariableLine>> kvp in unboundIdentifiers)
                {
                    foreach (VariableLine vl in kvp.Value)
                        parseParams.AppendUnboundIdentifier(vl.displayName, vl.variable);
                }

                return true;
            }
            catch (Exception)
            {
                buildStatus = null;
                return false;
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Pre-compiles DS code in code block node, 
        /// checks for syntax, converts non-assignments to assignments,
        /// stores list of AST nodes, errors and warnings
        /// Evaluates and stores list of unbound identifiers
        /// </summary>
        /// <param name="parseParams"> container for compilation related parameters </param>
        /// <param name="elementResolver"> classname resolver </param>
        /// <returns> true if code compilation succeeds, false otherwise </returns>
        public static bool PreCompileCodeBlock(Core core, ref ParseParam parseParams)
        {
            string postfixGuid = parseParams.PostfixGuid.ToString().Replace("-", "_");

            // Parse code to generate AST and add temporaries to non-assignment nodes
            List<AssociativeNode> astNodes;
            List<AssociativeNode> comments;
            ParseUserCode(core, parseParams.OriginalCode, postfixGuid, out astNodes, out comments);

            // Catch the syntax errors and errors for unsupported 
            // language constructs thrown by compile expression
            if (core.BuildStatus.ErrorCount > 0)
            {
                parseParams.AppendErrors(core.BuildStatus.Errors);
                parseParams.AppendWarnings(core.BuildStatus.Warnings);
                return false;
            }
            parseParams.AppendParsedNodes(astNodes);
            parseParams.AppendComments(comments);

            // Compile the code to get the resultant unboundidentifiers  
            // and any errors or warnings that were caught by the compiler and cache them in parseParams
            return CompileCodeBlockAST(core, parseParams);
        }
Ejemplo n.º 10
0
 /// <summary>
 /// Pre-compiles Design script code in code block node.
 /// </summary>
 /// <param name="parseParams">Container for compilation related parameters</param>
 /// <returns>true if code compilation succeeds, false otherwise</returns>
 public bool PreCompileCodeBlock(ref ParseParam parseParams)
 {
     return CompilerUtils.PreCompileCodeBlock(compilationCore, ref parseParams);
 }
Ejemplo n.º 11
0
 public bool TryParseCode(ref ParseParam parseParam)
 {
     return CompilerUtils.PreCompileCodeBlock(libraryCore, ref parseParam);
 }
Ejemplo n.º 12
0
        private static bool CompileCodeBlockAST(Core core, ParseParam parseParams)
        {
            Dictionary<int, List<VariableLine>> unboundIdentifiers = new Dictionary<int, List<VariableLine>>();
            IEnumerable<BuildData.WarningEntry> warnings = null;

            ProtoCore.BuildStatus buildStatus = null;
            try
            {
                int blockId = ProtoCore.DSASM.Constants.kInvalidIndex;
                CodeBlockNode codeblock = new CodeBlockNode();
                List<AssociativeNode> nodes = new List<AssociativeNode>();
                foreach (var i in parseParams.ParsedNodes)
                {
                    AssociativeNode assocNode = i as AssociativeNode;

                    if (assocNode != null)
                        nodes.Add(NodeUtils.Clone(assocNode));
                }
                codeblock.Body.AddRange(nodes);

                bool parsingPreloadFlag = core.IsParsingPreloadedAssembly;
                bool parsingCbnFlag = core.IsParsingPreloadedAssembly;
                core.IsParsingPreloadedAssembly = false;
                core.IsParsingCodeBlockNode = true;

                core.ResetForPrecompilation();
                buildStatus = PreCompile(string.Empty, core, codeblock, out blockId);

                core.IsParsingCodeBlockNode = parsingCbnFlag;
                core.IsParsingPreloadedAssembly = parsingPreloadFlag;

                parseParams.AppendErrors(buildStatus.Errors);
                parseParams.AppendWarnings(buildStatus.Warnings);

                if (buildStatus.ErrorCount > 0)
                {
                    return false;
                }
                warnings = buildStatus.Warnings;

                // Get the unboundIdentifiers from the warnings
                GetInputLines(parseParams.ParsedNodes, warnings, unboundIdentifiers);
                foreach (KeyValuePair<int, List<VariableLine>> kvp in unboundIdentifiers)
                {
                    foreach (VariableLine vl in kvp.Value)
                        parseParams.AppendUnboundIdentifier(vl.variable);
                }

                return true;
            }
            catch (Exception)
            {
                buildStatus = null;
                return false;
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Pre-compiles DS code in code block node,
 /// checks for syntax, converts non-assignments to assignments,
 /// stores list of AST nodes, errors and warnings
 /// Evaluates and stores list of unbound identifiers
 /// </summary>
 /// <param name="core"></param>
 /// <param name="parseParams"> container for compilation related parameters </param>
 /// <param name="priorNames"></param>
 /// <returns> true if code compilation succeeds, false otherwise </returns>
 public static bool PreCompileCodeBlock(Core core, ref ParseParam parseParams, IDictionary <string, string> priorNames = null)
 {
     return(PreCompileCodeBlock(core, parseParams, priorNames));
 }
Ejemplo n.º 14
0
        private void ProcessCode(ref string errorMessage, ref string warningMessage)
        {
            code = CodeBlockUtils.FormatUserText(code);
            codeStatements.Clear();

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

            try
            {
                ParseParam parseParam = new ParseParam(this.GUID, code);
                if (Workspace.DynamoModel.EngineController.TryParseCode(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) =>
                    {
                        return 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();
        }