// ToDo: Remove workaround; use executed lines in PythonStatementSemantic
        public Tuple <IEnumerable <bool>, IEnumerable <double>, double, string, List <PythonStatementSemantic> > EvaluateAndTraceProgram(PythonProcess pythonProcess, string program, string input, string output, IEnumerable <int> indices, string header, string footer, ISymbolicExpressionTree tree, double timeout = 1)
        {
            string traceProgram = traceCodeWithVariables
                                  + program;

            traceProgram += traceCodeWithVariables == String.Empty
                    ? String.Empty
                    : traceTableReduceEntries;

            EvaluationScript es = pythonProcess.CreateEvaluationScript(traceProgram, input, output, timeout);

            es.Variables.Add("traceTable");
            es.Variables.Add("traceTableBefore");
            es.Variables.Add("executedLines");

            JObject json       = pythonProcess.SendAndEvaluateProgram(es);
            var     baseResult = pythonProcess.GetVariablesFromJson(json, indices.Count());

            if (json["traceTable"] == null)
            {
                return(new Tuple <IEnumerable <bool>, IEnumerable <double>, double, string, List <PythonStatementSemantic> >(baseResult.Item1, baseResult.Item2, baseResult.Item3, baseResult.Item4, new List <PythonStatementSemantic>()));
            }

            var traceTable       = json["traceTable"].ToObject <IDictionary <int, IDictionary <string, IList> > >();
            var traceTableBefore = json["traceTableBefore"].ToObject <IDictionary <int, IDictionary <string, IList> > >();
            var executedLines    = json["executedLines"].ToObject <IDictionary <int, List <int> > >();

            List <PythonStatementSemantic> semantics = new List <PythonStatementSemantic>();
            ISymbolicExpressionTreeNode    root      = tree.Root;

            var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(root.Grammar);

            // calculate the correct line the semantic evaluation starts from
            var code    = CFGSymbolicExpressionTreeStringFormatter.StaticFormat(tree);
            int curline = es.Script.Count(c => c == '\n') - code.Count(c => c == '\n') - footer.Count(c => c == '\n') - traceTableReduceEntries.Count(c => c == '\n');

            var symbolToLineDict = FindStatementSymbolsInTree(root, statementProductionNames, ref curline);

            #region workaround: empty line problem with while, can't fix, otherwise FindStatementSymbolsInTree won't work
            string[] sciptLines       = es.Script.Split('\n');
            var      beginLineNumbers = symbolToLineDict.Values.Select(x => x[0]).Distinct().ToList();
            var      moveLines        = new Dictionary <int, int>(beginLineNumbers.Count);
            foreach (var l in beginLineNumbers)
            {
                // decrease by one, as sciptLines is an array and start from zero, where lineNumbers started counting from 1
                if (String.IsNullOrWhiteSpace(sciptLines[l - 1]) || sciptLines[l - 1].TrimStart().StartsWith("#"))
                {
                    // empty line or comment
                    var i = l + 1;
                    while (i - 1 < sciptLines.Length && (String.IsNullOrWhiteSpace(sciptLines[i - 1]) || sciptLines[i - 1].TrimStart().StartsWith("#")))
                    {
                        i++;
                    }
                    moveLines.Add(l, i);
                }
                else
                {
                    moveLines.Add(l, l);
                }
            }
            foreach (var symbolLine in symbolToLineDict)
            {
                symbolLine.Value[0] = moveLines[symbolLine.Value[0]];
            }
            #endregion
            #region fix Before line for <predefined> to have all variables initialised
            // not a great way to do it, but the python interpreter does not stop at e.g. 'while False:'
            int newMinBefore = traceTableBefore.OrderBy(x => x.Key).First(x => x.Value.ContainsKey("res0") && !x.Value["res0"].Contains(null)).Key; // first line that changes res0
            foreach (var symbolToLine in symbolToLineDict)
            {
                symbolToLine.Value.Add(symbolToLine.Value[0]); // original beginning at [2], which is needed for executed lines
                if (symbolToLine.Value[0] < newMinBefore)
                {
                    symbolToLine.Value[0] = newMinBefore;
                }
            }
            #endregion

            var prefixTreeNodes = tree.IterateNodesPrefix().ToList();

            foreach (var symbolLine in symbolToLineDict)
            {
                // Before
                Dictionary <string, IList> before = new Dictionary <string, IList>();
                foreach (var traceChange in traceTableBefore.Where(x => x.Key <= symbolLine.Value[0]).OrderByDescending(x => x.Key))
                {
                    foreach (var variableChange in traceChange.Value)
                    {
                        if (!before.ContainsKey(variableChange.Key))
                        {
                            before.Add(variableChange.Key, variableChange.Value);
                        }
                    }
                }
                // After
                Dictionary <string, IList> after = new Dictionary <string, IList>();
                foreach (var traceChange in traceTable.Where(x => x.Key >= symbolLine.Value[0] && x.Key <= symbolLine.Value[1]).OrderByDescending(x => x.Key))
                {
                    foreach (var variableChange in traceChange.Value)
                    {
                        if (!after.ContainsKey(variableChange.Key))
                        {
                            after.Add(variableChange.Key, variableChange.Value);
                        }
                    }
                }
                // clean after with before
                foreach (var key in after.Keys.ToList())
                {
                    if (PythonSemanticComparer.CompareSequence(after[key], before[key]))
                    {
                        after.Remove(key);
                    }
                }
                // add semantics
                var executedLinesWithinStatement = executedLines.Where(x => x.Key >= symbolLine.Value[2] && x.Key <= symbolLine.Value[1]);
                semantics.Add(new PythonStatementSemantic()
                {
                    TreeNodePrefixPos = prefixTreeNodes.IndexOf(symbolLine.Key),
                    ExecutedCases     = executedLinesWithinStatement.Any() ? executedLinesWithinStatement.OrderByDescending(x => x.Value.Count).First().Value : new List <int>(),
                    Before            = before,
                    After             = after,
                });
            }

            return(new Tuple <IEnumerable <bool>, IEnumerable <double>, double, string, List <PythonStatementSemantic> >(baseResult.Item1, baseResult.Item2, baseResult.Item3, baseResult.Item4, semantics));
        }
Esempio n. 2
0
        public Tuple <IEnumerable <bool>, IEnumerable <double>, double, string, List <PythonStatementSemantic> > EvaluateAndTraceProgram(PythonProcess pythonProcess, string program, string input, string output, IEnumerable <int> indices, string header, string footer, ISymbolicExpressionTree tree, double timeout = 1)
        {
            string traceProgram = traceCodeWithVariables
                                  + program;

            traceProgram += traceCodeWithVariables == String.Empty
                    ? String.Empty
                    : traceTableReduceEntries;

            EvaluationScript es = pythonProcess.CreateEvaluationScript(traceProgram, input, output, timeout);

            es.Variables.Add("traceTable");
            es.Variables.Add("traceTableBefore");
            es.Variables.Add("executedLines");

            JObject json       = pythonProcess.SendAndEvaluateProgram(es);
            var     baseResult = pythonProcess.GetVariablesFromJson(json, indices.Count());

            if (json["traceTable"] == null || json["traceTableBefore"] == null)
            {
                return(new Tuple <IEnumerable <bool>, IEnumerable <double>, double, string, List <PythonStatementSemantic> >(baseResult.Item1, baseResult.Item2, baseResult.Item3, baseResult.Item4, new List <PythonStatementSemantic>()));
            }

            var traceTable       = JsonConvert.DeserializeObject <IDictionary <int, IDictionary <string, IList> > >(json["traceTable"].ToString());
            var traceTableBefore = JsonConvert.DeserializeObject <IDictionary <int, IDictionary <string, IList> > >(json["traceTableBefore"].ToString());
            var executedLinesNew = JsonConvert.DeserializeObject <IDictionary <int, List <int> > >(json["executedLines"].ToString());
            var executedLines    = executedLinesNew.Keys.ToList();

            executedLines.Sort();

            IList <int> traceChanges       = traceTable.Keys.OrderBy(x => x).ToList();
            IList <int> traceBeforeChanges = traceTableBefore.Keys.OrderBy(x => x).ToList();

            List <PythonStatementSemantic> semantics = new List <PythonStatementSemantic>();
            ISymbolicExpressionTreeNode    root      = tree.Root;

            var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(root.Grammar);

            // calculate the correct line the semantic evaluation starts from
            var code    = CFGSymbolicExpressionTreeStringFormatter.StaticFormat(tree);
            int curline = es.Script.Count(c => c == '\n') - code.Count(c => c == '\n') - footer.Count(c => c == '\n') - traceTableReduceEntries.Count(c => c == '\n');

            var symbolToLineDict = FindStatementSymbolsInTree(root, statementProductionNames, ref curline);
            var prefixTreeNodes  = tree.IterateNodesPrefix().ToList();

            foreach (var symbolLine in symbolToLineDict)
            {
                // Before
                Dictionary <string, IList> before = new Dictionary <string, IList>();
                foreach (var traceChange in traceTableBefore.Where(x => x.Key <= symbolLine.Value[0]).OrderByDescending(x => x.Key))
                {
                    foreach (var variableChange in traceChange.Value)
                    {
                        if (!before.ContainsKey(variableChange.Key))
                        {
                            before.Add(variableChange.Key, variableChange.Value);
                        }
                    }
                }
                // After
                Dictionary <string, IList> after = new Dictionary <string, IList>();
                foreach (var traceChange in traceTable.Where(x => x.Key >= symbolLine.Value[0] && x.Key <= symbolLine.Value[1]).OrderByDescending(x => x.Key))
                {
                    foreach (var variableChange in traceChange.Value)
                    {
                        if (!after.ContainsKey(variableChange.Key))
                        {
                            after.Add(variableChange.Key, variableChange.Value);
                        }
                    }
                }

                // clean after with before
                foreach (var key in after.Keys.ToList())
                {
                    if (CompareSequence(after[key], before[key]))
                    {
                        after.Remove(key);
                    }
                }

                semantics.Add(new PythonStatementSemantic()
                {
                    TreeNodePrefixPos = prefixTreeNodes.IndexOf(symbolLine.Key),
                    Before            = before,
                    After             = after,
                });
            }

            return(new Tuple <IEnumerable <bool>, IEnumerable <double>, double, string, List <PythonStatementSemantic> >(baseResult.Item1, baseResult.Item2, baseResult.Item3, baseResult.Item4, semantics));
        }