public static void Optimize(IExecutableCode code)
 {
     foreach (var block in code.QueryCode())
     {
         VisitCodeBlock(block);
     }
 }
 public static void Optimize(IExecutableCode code)
 {
     foreach (var block in code.QueryCode())
     {
         VisitCodeBlock(block);
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Dump out info from a executable code dude.
        /// </summary>
        /// <param name="code"></param>
        public static IEnumerable <string> DumpCode(this IExecutableCode code)
        {
            Console.WriteLine("There are {0} Query Blocks:", code.QueryCode().Count());
            foreach (var qb in code.QueryCode())
            {
                yield return("Query Block:");

                foreach (var line in qb.DumpCode("  "))
                {
                    yield return(line);
                }
                ;
            }

            foreach (var f in code.Functions)
            {
                yield return(string.Format("Function: {0}", f.Name));

                yield return(string.Format("  {0} {1} ()", f.ResultType.Name, f.Name));

                if (f.StatementBlock != null)
                {
                    foreach (var line in f.StatementBlock.DumpCode())
                    {
                        yield return(string.Format("  {0}", line));
                    }
                }
                else
                {
                    yield return("  ** No statements ever set");
                }
            }

            if (code.ResultValues == null)
            {
                yield return("Result Variable: <not set (null)>");
            }
            else
            {
                yield return(string.Format("There are {0} result variables.", code.ResultValues.Count()));

                foreach (var rv in code.ResultValues)
                {
                    yield return(string.Format("  Result Variable: {0}", rv.RawValue));
                }
            }
        }
        /// <summary>
        /// Wherever the oldfname is referenced we need to rename it to be the new one.
        /// </summary>
        /// <param name="code"></param>
        /// <param name="oldfname"></param>
        /// <param name="newfname"></param>
        private void RenameFunction(IExecutableCode code, string oldfname, string newfname)
        {
            foreach (var qb in code.QueryCode())
            {
                qb.RenameVariable(oldfname, newfname);
            }

            foreach (var f in code.Functions)
            {
                f.RenameFunctionReference(oldfname, newfname);
            }
        }
Exemplo n.º 5
0
 /// <summary>
 /// Look through a code block, make sure all the data structures are in order.
 /// </summary>
 /// <param name="code"></param>
 /// <returns></returns>
 public static bool CheckCodeBlock(this IExecutableCode code)
 {
     // Check parent
     foreach (var block in code.QueryCode())
     {
         var r = CheckQueryCodeBlock(block, null);
         if (!r)
         {
             return(r);
         }
     }
     return(true);
 }
Exemplo n.º 6
0
        /// <summary>
        /// Do the code translation itself.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public Dictionary <string, object> TranslateGeneratedCode(IExecutableCode code)
        {
            if (code == null)
            {
                throw new ArgumentNullException("code");
            }

            ///
            /// Get the variables that we are going to be shipping back and forth.
            ///

            Dictionary <string, object> result = new Dictionary <string, object>();

            result["ResultVariables"] = TranslateVariable(code.ResultValues, code);

            ///
            /// The actual code. This is just a sequence of loops. It would be, under normal circumstances, just that. However,
            /// there is a limitation in the code generator that means you can't have more than 250 loops in one function. If we aren't
            /// combining loops it is easy to have more than 250 plots. So we split this up into functions of about 100 outter loops
            /// per function. We then call these functions from the main loop. Fortunately, there are no local variables. :-)
            /// We cache the codeing blocks here b/c we have to access them several times.
            ///

            const int queriesPerFunction = 100;
            var       queryBlocks        = code.QueryCode().ToArray();
            int       numberOfBlocks     = 1 + queryBlocks.Length / queriesPerFunction;

            result["NumberOfQueryFunctions"]   = numberOfBlocks;
            result["QueryFunctionBlocks"]      = TranslateQueryBlocks(queryBlocks, queriesPerFunction, numberOfBlocks);
            result["SlaveTerminateStatements"] = TranslateFinalizingVariables(code.ResultValues, code);
            result["InitStatements"]           = code.InitalizationStatements.SelectMany(s => s.CodeItUp());

            // Functions have to be written out too.
            result["QueryMemberFunctions"] = code.Functions.SelectMany(f => f.CodeItUp());
            result["QueryCacheBools"]      = code.Functions.Select(f => f.CacheVariableGood.RawValue);

            ///
            /// Next, go through everything and extract the include files
            ///

            AddIncludeFiles(code);

            return(result);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Do the code translation itself.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public Dictionary<string, object> TranslateGeneratedCode(IExecutableCode code)
        {
            if (code == null)
                throw new ArgumentNullException("code");

            ///
            /// Get the variables that we are going to be shipping back and forth.
            /// 

            Dictionary<string, object> result = new Dictionary<string, object>();
            result["ResultVariables"] = TranslateVariable(code.ResultValues, code);

            ///
            /// The actual code. This is just a sequence of loops. It would be, under normal circumstances, just that. However,
            /// there is a limitation in the code generator that means you can't have more than 250 loops in one function. If we aren't
            /// combining loops it is easy to have more than 250 plots. So we split this up into functions of about 100 outter loops
            /// per function. We then call these functions from the main loop. Fortunately, there are no local variables. :-)
            /// We cache the codeing blocks here b/c we have to access them several times.
            /// 

            const int queriesPerFunction = 100;
            var queryBlocks = code.QueryCode().ToArray();
            int numberOfBlocks = 1 + queryBlocks.Length / queriesPerFunction;
            result["NumberOfQueryFunctions"] = numberOfBlocks;
            result["QueryFunctionBlocks"] = TranslateQueryBlocks(queryBlocks, queriesPerFunction, numberOfBlocks);
            result["SlaveTerminateStatements"] = TranslateFinalizingVariables(code.ResultValues, code);
            result["InitStatements"] = code.InitalizationStatements.SelectMany(s => s.CodeItUp());

            // Functions have to be written out too.
            result["QueryMemberFunctions"] = code.Functions.SelectMany(f => f.CodeItUp());
            result["QueryCacheBools"] = code.Functions.Select(f => f.CacheVariableGood.RawValue);

            ///
            /// Next, go through everything and extract the include files
            /// 

            AddIncludeFiles(code);

            return result;
        }
        /// <summary>
        /// Add one of the query's to our list of queries we are tracking here.
        /// </summary>
        /// <param name="code"></param>
        public void AddGeneratedCode(IExecutableCode code)
        {
            ///
            /// We have some pretty stiff requirements on code
            /// 

            if (code == null)
                throw new ArgumentNullException("code cannot be null");
            if (code == this)
                throw new ArgumentException("Can't add code to itself!");

            var varsToTrans = code.VariablesToTransfer;
            if (varsToTrans == null)
                throw new ArgumentNullException("Generated Code Varaibles to Transfer can't be null");

            var includeFiles = code.IncludeFiles;
            if (includeFiles == null)
                throw new ArgumentNullException("Generated code Include Files can't be null");

            var resultValues = code.ResultValues;
            if (resultValues == null)
                throw new ArgumentNullException("Generated code Result Values can't be null");

            var codeItems = code.QueryCode().ToArray();

            // Functions can be combined, as long as we rewrite their names. A very nice thing
            // about this is that the query text is basically all that is required for doing
            // matching: no code analysis. Further, no messing with the code.

            // Only take functions that were actually populated by us!
            var goodFunctions = code.Functions.Where(f => f.StatementBlock != null);
            if (_functions.Count == 0)
            {
                _functions.AddRange(goodFunctions);
            }
            else
            {
                var matchedFunctions =
                    from newFunc in goodFunctions
                    let oldFunc = _functions.Where(f => f.Matches(newFunc)).FirstOrDefault()
                    group Tuple.Create(oldFunc, newFunc) by oldFunc != null;

                // No match means we add it to our list of functions directly.
                // Those that don't have to have the renaming propagated through out!
                foreach (var fgroup in matchedFunctions)
                {
                    if (fgroup.Key)
                    {
                        // Match. Rename, don't add.
                        foreach (var fpair in fgroup)
                        {
                            // Note, this is the new code and we want it to look like the old code.
                            RenameFunction(code, fpair.Item2.Name, fpair.Item1.Name);
                        }
                    }
                    else
                    {
                        // Not matched. So add it.
                        foreach (var fpair in fgroup)
                        {
                            _functions.Add(fpair.Item2);
                        }
                    }
                }
            }

            ///
            /// Variables that we need to queue for transfer
            /// 

            foreach (var v in varsToTrans)
            {
                QueueVariableForTransfer(v);
            }

            // Initialization code. No combination should be required here.
            foreach (var s in code.InitalizationStatements)
            {
                _initStatements.Add(s);
            }

            ///
            /// Include Files - only add if we don't have them on the list already.
            /// 

            foreach (var inc in includeFiles)
            {
                AddIncludeFile(inc);
            }

            ///
            /// Result values - killer if they are named the same thing!
            /// 

            foreach (var item in resultValues)
            {
                AddResult(item);
            }

            //
            // Add the referenced leaf names
            //

            foreach (var leaf in code.ReferencedLeafNames)
            {
                AddReferencedLeaf(leaf);
            }

            ///
            /// Finally, we need to combine the query code. Now, there is a limitation (by design) in the C++ compiler:
            /// http://connect.microsoft.com/VisualStudio/feedback/details/100734/c-function-with-many-unnested-loops-generates-error-fatal-error-c1061-compiler-limit-blocks-nested-too-deeply
            /// 
            /// So - if we want to generate more than 250 plots in one run, and we are doing no loop combining, then we will be in trouble. To get around this
            /// Anything that can't folded into itself has to be kept "seperate". Sucks, but what can you do?
            /// 

            AddQueryBlocks(codeItems);
        }
        /// <summary>
        /// Wherever the oldfname is referenced we need to rename it to be the new one.
        /// </summary>
        /// <param name="code"></param>
        /// <param name="oldfname"></param>
        /// <param name="newfname"></param>
        private void RenameFunction(IExecutableCode code, string oldfname, string newfname)
        {
            foreach (var qb in code.QueryCode())
            {
                qb.RenameVariable(oldfname, newfname);
            }

            foreach (var f in code.Functions)
            {
                f.RenameFunctionReference(oldfname, newfname);
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Add one of the query's to our list of queries we are tracking here.
        /// </summary>
        /// <param name="code"></param>
        public void AddGeneratedCode(IExecutableCode code)
        {
            ///
            /// We have some pretty stiff requirements on code
            ///

            if (code == null)
            {
                throw new ArgumentNullException("code cannot be null");
            }
            if (code == this)
            {
                throw new ArgumentException("Can't add code to itself!");
            }

            var varsToTrans = code.VariablesToTransfer;

            if (varsToTrans == null)
            {
                throw new ArgumentNullException("Generated Code Varaibles to Transfer can't be null");
            }

            var includeFiles = code.IncludeFiles;

            if (includeFiles == null)
            {
                throw new ArgumentNullException("Generated code Include Files can't be null");
            }

            var resultValues = code.ResultValues;

            if (resultValues == null)
            {
                throw new ArgumentNullException("Generated code Result Values can't be null");
            }

            var codeItems = code.QueryCode().ToArray();

            // Functions can be combined, as long as we rewrite their names. A very nice thing
            // about this is that the query text is basically all that is required for doing
            // matching: no code analysis. Further, no messing with the code.

            // Only take functions that were actually populated by us!
            var goodFunctions = code.Functions.Where(f => f.StatementBlock != null);

            if (_functions.Count == 0)
            {
                _functions.AddRange(goodFunctions);
            }
            else
            {
                var matchedFunctions =
                    from newFunc in goodFunctions
                    let oldFunc = _functions.Where(f => f.Matches(newFunc)).FirstOrDefault()
                                  group Tuple.Create(oldFunc, newFunc) by oldFunc != null;

                // No match means we add it to our list of functions directly.
                // Those that don't have to have the renaming propagated through out!
                foreach (var fgroup in matchedFunctions)
                {
                    if (fgroup.Key)
                    {
                        // Match. Rename, don't add.
                        foreach (var fpair in fgroup)
                        {
                            // Note, this is the new code and we want it to look like the old code.
                            RenameFunction(code, fpair.Item2.Name, fpair.Item1.Name);
                        }
                    }
                    else
                    {
                        // Not matched. So add it.
                        foreach (var fpair in fgroup)
                        {
                            _functions.Add(fpair.Item2);
                        }
                    }
                }
            }

            ///
            /// Variables that we need to queue for transfer
            ///

            foreach (var v in varsToTrans)
            {
                QueueVariableForTransfer(v);
            }

            // Initialization code. No combination should be required here.
            foreach (var s in code.InitalizationStatements)
            {
                _initStatements.Add(s);
            }

            ///
            /// Include Files - only add if we don't have them on the list already.
            ///

            foreach (var inc in includeFiles)
            {
                AddIncludeFile(inc);
            }

            ///
            /// Result values - killer if they are named the same thing!
            ///

            foreach (var item in resultValues)
            {
                AddResult(item);
            }

            //
            // Add the referenced leaf names
            //

            foreach (var leaf in code.ReferencedLeafNames)
            {
                AddReferencedLeaf(leaf);
            }

            ///
            /// Finally, we need to combine the query code. Now, there is a limitation (by design) in the C++ compiler:
            /// http://connect.microsoft.com/VisualStudio/feedback/details/100734/c-function-with-many-unnested-loops-generates-error-fatal-error-c1061-compiler-limit-blocks-nested-too-deeply
            ///
            /// So - if we want to generate more than 250 plots in one run, and we are doing no loop combining, then we will be in trouble. To get around this
            /// Anything that can't folded into itself has to be kept "seperate". Sucks, but what can you do?
            ///

            AddQueryBlocks(codeItems);
        }