Пример #1
0
        /// <summary>
        /// Actually try and process this! The count consisits of a count integer and something to increment it
        /// at its current spot.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="codeEnv"></param>
        /// <returns></returns>
        public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            if (gc == null)
                throw new ArgumentNullException("CodeEnv must not be null!");

            var c = resultOperator as CountResultOperator;
            if (c == null)
                throw new ArgumentNullException("resultOperator can only be a CountResultOperator and must not be null");

            //
            // The accumulator where we will store the result.
            //

            var accumulator = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            accumulator.SetInitialValue("0");

            //
            // Use the Aggregate infrasturcutre to do the adding. This
            // has the advantage that it will correctly combine with
            // similar statements during query optimization.
            //

            var add = Expression.Add(accumulator, Expression.Constant((int)1));
            var addResolved = ExpressionToCPP.GetExpression(add, gc, cc, container);

            gc.Add(new StatementAggregate(accumulator, addResolved));
            return accumulator;
        }
Пример #2
0
		static string GeneratePartialClassContextStub(ICodeContext context)
		{
			var member = context.CurrentMember;
			if (member == null)
				return "";
			var builder = new TypeSystemAstBuilder();
			MethodDeclaration decl;
			if (member is IMethod) {
				// If it's a method, convert it directly (including parameters + type parameters)
				decl = (MethodDeclaration)builder.ConvertEntity(member);
			} else {
				// Otherwise, create a method anyways, and copy the parameters
				decl = new MethodDeclaration();
				if (member is IParameterizedMember) {
					foreach (var p in ((IParameterizedMember)member).Parameters) {
						decl.Parameters.Add(builder.ConvertParameter(p));
					}
				}
			}
			decl.Name = "__DebuggerStub__";
			decl.ReturnType = builder.ConvertType(member.ReturnType);
			decl.Modifiers = member.IsStatic ? Modifiers.Static : Modifiers.None;
			// Make the method look like an explicit interface implementation so that it doesn't appear in CC
			decl.PrivateImplementationType = new SimpleType("__DummyType__");
			decl.Body = GenerateBodyFromContext(builder, context.LocalVariables.ToArray());
			return WrapInType(context.CurrentTypeDefinition, decl).ToString();
		}
Пример #3
0
        /// <summary>
        /// Generate the code that we will use to access this array. Loop symantics in this framework are basically "foreach" rather than "for" - so
        /// we return an object that can be used to reference each array element.
        /// </summary>
        /// <param name="env"></param>
        /// <param name="context"></param>
        /// <param name="indexName"></param>
        /// <param name="popVariableContext"></param>
        /// <returns></returns>
        public Tuple<Expression, IDeclaredParameter> AddLoop(IGeneratedQueryCode env, ICodeContext context, CompositionContainer container)
        {
            ///
            /// First, we will need to know the length of this array
            /// 

            var lenExpression = Expression.ArrayLength(_arrayExpression);
            var lenTranslation = ExpressionToCPP.GetExpression(lenExpression, env, context, container);

            ///
            /// Next, generate the expression that forms the basis of the index lookup. We don't
            /// translate this - that only gets to happen when one is actually looking at a final result.
            /// 

            var loopVariable = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var indexExpression = Expression.MakeBinary(ExpressionType.ArrayIndex, _arrayExpression, loopVariable);

            ///
            /// Now the for loop statement!
            /// 

            env.Add(new StatementForLoop(loopVariable, lenTranslation));

            ///
            /// Return the index expression - the thing that can be used to replace all expressions and
            /// reference the item we are looping over.
            /// 

            return Tuple.Create<Expression, IDeclaredParameter>(indexExpression, loopVariable);
        }
Пример #4
0
        public static Expression Resolve(this Expression source, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            if (cc == null)
            {
                cc = new CodeContext();
            }

            // It does happen that we are asked to translate a null expression. This could be a static method call, for example.

            if (source == null)
                return null;

            try
            {
                Debug.WriteLine("Expression Resolver: Resolving {0}{1}", source.ToString(), "");
                Debug.Indent();
                var r = ResolveToExpression.Translate(source, gc, cc, container);
                Debug.WriteLine("Expression Resolver: Result: {0}{1}", r == null ? "<null>" : r.ToString(), "");
                return r;
            }
            finally
            {
                Debug.Unindent();
            }
        }
Пример #5
0
        /// <summary>
        /// Implement the skipping. We have a main limitation: we currently know only how to implement integer skipping.
        /// We implement with "if" statements to support composability, even if it means running longer in the end...
        /// We actually return nothing when goes - we aren't really a final result the way "Count" is.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <returns></returns>
        public void ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode codeEnv, ICodeContext codeContext, CompositionContainer container)
        {
            ///
            /// Quick checks to make sure
            /// 

            if (codeEnv == null)
                throw new ArgumentNullException("codeEnv cannot be null");

            var take = resultOperator as TakeResultOperator;
            var skip = resultOperator as SkipResultOperator;

            if (take == null && skip == null)
            {
                throw new ArgumentNullException("resultOperator must not be null and must represent either a take or a skip operation!");
            }

            if (take != null && take.Count.Type != typeof(int))
                throw new ArgumentException("Take operator count must be an integer!");
            if (skip != null && skip.Count.Type != typeof(int))
                throw new ArgumentException("Skip operator count must be an integer!");

            // If this is a "global" take, then we need to declare the variable a bit specially.
            // Global: we have a limit on the number of objects that goes across events. We test this by seeing if this
            // is a sub-query that is registered (or not).
            var isGlobalTake = codeContext.IsInTopLevelQueryModel(queryModel);

            // Now, we create a count variable and that is how we will tell if we are still skipping or
            // taking. It must be declared in the current block, before our current code! :-)

            var counter = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int), otherDependencies: codeContext.LoopIndexVariable.Return<IDeclaredParameter>());
            if (isGlobalTake)
            {
                counter.DeclareAsStatic = true;
                codeEnv.Add(counter);
            } else
            {
                codeEnv.AddOutsideLoop(counter);
            }

            var comparison = StatementIfOnCount.ComparisonOperator.LessThanEqual;
            IValue limit = null;
            if (skip != null)
            {
                comparison = StatementIfOnCount.ComparisonOperator.GreaterThan;
                limit = ExpressionToCPP.GetExpression(skip.Count, codeEnv, codeContext, container);
            }
            else
            {
                limit = ExpressionToCPP.GetExpression(take.Count, codeEnv, codeContext, container);
            }

            codeEnv.Add(new StatementIfOnCount(counter, limit, comparison));

            ///
            /// We are particularly fortunate here. We don't have to update the Loop variable - whatever it is, is
            /// still the right one! Normally we'd have to futz with the LoopVariable in code context because we
            /// were iterating over something new. :-) Easy!
            /// 
        }
Пример #6
0
        /// <summary>
        /// Run the method call against the expressoins we know.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <returns></returns>
        public Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, CompositionContainer container)
        {
            if (expr == (MethodCallExpression)null)
                throw new ArgumentNullException("expr");

            var h = FindHandler(expr.Method.DeclaringType);
            return h.ProcessMethodCall(expr, gc, context, container);
        }
Пример #7
0
        /// <summary>
        /// Create a new visitor and add our code to the current spot we are in the "code".
        /// </summary>
        /// <param name="code"></param>
        public QueryVisitor(IGeneratedQueryCode code, ICodeContext context, CompositionContainer container)
        {
            _codeEnv = code;
            _codeContext = context;
            MEFContainer = container;

            if (_codeContext == null)
                _codeContext = new CodeContext();
        }
Пример #8
0
 public IVariable TestProcessResultOperator([PexAssumeUnderTest]ROSum target,
     SumResultOperator sumro,
     QueryModel qm,
     IGeneratedQueryCode gc,
     ICodeContext cc)
 {
     var result = target.ProcessResultOperator(sumro, qm, gc, cc, MEFUtilities.MEFContainer);
     return result;
 }
Пример #9
0
            /// <summary>
            /// Translate an expression.
            /// </summary>
            /// <param name="expr"></param>
            /// <param name="cc"></param>
            /// <returns></returns>
            public static Expression Translate(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
            {
                var tr = new ResolveToExpression() { CodeContext = cc, GeneratedCode = gc, MEFContainer = container };
                if (container != null)
                {
                    container.SatisfyImportsOnce(tr);
                }

                return tr.Visit(expr);
            }
Пример #10
0
		public override ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, ICodeContext context)
		{
			if (context == null)
				throw new ArgumentNullException("context");
			string content = GeneratePartialClassContextStub(context);
			const string caretPoint = "$__Caret_Point__$;";
			int caretOffset = content.IndexOf(caretPoint, StringComparison.Ordinal) + expressionToComplete.Length;
			SD.Log.DebugFormatted("context used for dot completion: {0}", content.Replace(caretPoint, "$" + expressionToComplete + "|$"));
			var doc = new ReadOnlyDocument(content.Replace(caretPoint, expressionToComplete));
			return new CSharpCompletionBinding(context, doc.GetLocation(caretOffset), doc.CreateSnapshot());
		}
 internal Expression ProcessMethodCall(
     [PexAssumeUnderTest]TypeHandlerHelpers target,
     MethodCallExpression expr,
     IGeneratedQueryCode gc,
     ICodeContext context
 )
 {
     Expression result01 = target.ProcessMethodCall(expr, gc, context, null);
     return result01;
     // TODO: add assertions to method TypeHandlerHelpersTest.ProcessMethodCall(TypeHandlerHelpers, MethodCallExpression, IValue&, IGeneratedCode, ICodeContext)
 }
 /// <summary>Test stub for ProcessMethodCall(MethodCallExpression, IValue&amp;, IGeneratedCode, ICodeContext)</summary>
 ///[PexMethod]
 public Expression ProcessMethodCall(
     TypeHandlerReplacementCall target,
     MethodCallExpression expr,
     IGeneratedQueryCode gc,
     ICodeContext context
 )
 {
     Expression result01 = target.ProcessMethodCall(expr, gc, context, MEFUtilities.MEFContainer);
     return result01;
     // TODO: add assertions to method TypeHandlerReplacementCallTest.ProcessMethodCall(TypeHandlerReplacementCall, MethodCallExpression, IValue&, IGeneratedCode, ICodeContext)
 }
Пример #13
0
        /// <summary>
        /// Try to do a fast count. Basically, what we are dealing with here is the fact that we have
        /// a simple array, we need only take its length, and return that.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public Tuple<bool, Expression> ProcessIdentityQuery(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode _codeEnv, ICodeContext _codeContext, CompositionContainer container)
        {
            //
            // We just need to return a length expression. We are low enough level we need to do some basic resolution.
            //

            if (!queryModel.MainFromClause.FromExpression.Type.IsArray)
                return Tuple.Create(false, null as Expression);

            var lengthExpr = Expression.ArrayLength(queryModel.MainFromClause.FromExpression).Resolve(_codeEnv, _codeContext, container);
            return Tuple.Create(true, lengthExpr as Expression);
        }
Пример #14
0
        /// <summary>
        /// Given array info, code a loop over it.
        /// </summary>
        /// <param name="query">The query this loop is associated with</param>
        /// <param name="arrayRef">The reference to the array</param>
        /// <remarks>Will add the query to the code context to forward to the variable that is being dealt with here.</remarks>
        public static IVariableScopeHolder CodeLoopOverArrayInfo(this IArrayInfo arrayRef, IQuerySource query, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            var indexVar = arrayRef.AddLoop(gc, cc, container);
            if (indexVar == null)
                return null;

            ///
            /// Next, make sure the index variable can be used for later references!
            /// 

            var result = cc.Add(query, indexVar.Item1);
            cc.SetLoopVariable(indexVar.Item1, indexVar.Item2);
            return result;
        }
Пример #15
0
 internal Expression ProcessResultOperator(
     [PexAssumeUnderTest]ROMinMax target,
     ResultOperatorBase resultOperator,
     QueryModel queryModel,
     IGeneratedQueryCode gc,
     ICodeContext cc,
     CompositionContainer container
 )
 {
     Expression result
        = target.ProcessResultOperator(resultOperator, queryModel, gc, cc, container);
     return result;
     // TODO: add assertions to method ROMinMaxTest.ProcessResultOperator(ROMinMax, ResultOperatorBase, QueryModel, IGeneratedQueryCode, ICodeContext, CompositionContainer)
 }
        /// <summary>
        /// Given an array expression return an array info that can be used
        /// for the various needed things. Throws if it can't figure out how to do
        /// a loop. It might return null, in which case the array index context has
        /// just been "setup".
        /// </summary>
        /// <param name="expr"></param>
        /// <returns>null, if no further setup is required to run the loop, and an IArrayInfo if further work is required.</returns>
        private IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            expr = NormalizeExpression(expr);

            //
            // See if we can find something that will handle the array.
            //

            var arInfo = (from h in _handlers
                          let r = h.GetIArrayInfo(expr, gc, cc, container, e => GetIArrayInfo(e, gc, cc, container))
                          where r != null
                          select r).FirstOrDefault();

            return arInfo;
        }
Пример #17
0
        /// <summary>
        /// Take the incoming stream of items, and send them along! :-)
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        public void ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            //
            // Some basic checks on the input.
            //

            if (cc == null)
                throw new ArgumentNullException("cc");
            if (gc == null)
                throw new ArgumentNullException("gc");
            if (cc.LoopVariable == null)
                throw new ArgumentNullException("No defined loop variable!");

            //
            // Get the indexer that is being used to access things. We will just push that onto a temp vector of int's. That will be
            // a list of the items that we want to come back and look at. That said, once done we need to pop-up one level in our
            // depth.
            //

            var arrayRecord = DeclarableParameter.CreateDeclarableParameterArrayExpression(typeof(int));
            gc.AddOutsideLoop(arrayRecord);

            var recordIndexStatement = new Statements.StatementRecordIndicies(ExpressionToCPP.GetExpression(cc.LoopIndexVariable.AsExpression(), gc, cc, container), arrayRecord);
            gc.Add(recordIndexStatement);

            gc.Pop();

            //
            // Now, we go down one loop and run over the pairs with a special loop.
            //

            var index1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var index2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var indexIterator = new Statements.StatementPairLoop(arrayRecord, index1, index2);
            gc.Add(indexIterator);

            //
            // Finally, build the resulting loop variable. For now it is just a tuple, which is basically the formed expression we started with,
            // but with the other index properties. Other bits will have to do the translation for us. :-)
            //

            var item1 = cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), index1);
            var item2 = cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), index2);

            var tupleType = typeof(Tuple<,>).MakeGenericType(cc.LoopVariable.Type, cc.LoopVariable.Type);
            var newTuple = Expression.New(tupleType.GetConstructor(new Type[] { cc.LoopVariable.Type, cc.LoopVariable.Type }), item1, item2);
            cc.SetLoopVariable(newTuple, null);
        }
Пример #18
0
        /// <summary>
        /// If one of the helper functions needs to be parsed, we end up here.
        /// Note: this is a bit tricky, and, worse, this is not tested (too complex :-)).
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public System.Linq.Expressions.Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, CompositionContainer container)
        {
            if (expr == null)
                throw new ArgumentNullException("expr");

            if (expr.Method.Name == "ApplyReturnFirst")
            {
                ///
                /// Load out the parameter names we are looking at so we cna do the translation.
                /// 

                var parameters = expr.Method.GetParameters();
                var action = RaiseLambda(expr.Arguments[2]);

                var methodGenericArguments = expr.Method.GetGenericArguments();
                var actionType = typeof(Action<,>).MakeGenericType(new Type[] { methodGenericArguments[0], methodGenericArguments[1] });
                var expressionGeneric = typeof(Expression<>).MakeGenericType(new Type[] { actionType });
                var parameterSpec = expressionGeneric.GetProperty("Parameters");
                var lambdaParameters = (parameterSpec.GetValue(action, null) as IEnumerable<ParameterExpression>).ToArray();

                ///
                /// Next, do the lambda expression. Order of p1 and p2 is b/c we should make sure that it happens
                /// before any parameters are replaced! Note we parse the body of the lambda here! Parameters are defined and should
                /// correctly deal with any substitution in process.
                /// 

                var p2 = context.Add(lambdaParameters[1].Name, expr.Arguments[1]);
                var p1 = context.Add(lambdaParameters[0].Name, expr.Arguments[0]);

                var statementBody = ExpressionToCPP.GetExpression(action.Body.Resolve(gc, context, container), gc, context, container);

                p1.Pop();
                p2.Pop();

                gc.Add(new Statements.StatementSimpleStatement(statementBody.RawValue, resultVars: new string[0] { }, dependentVars: statementBody.Dependants.Select(i => i.RawValue).ToArray()));

                ///
                /// Finally, what we will return if this is the last thing we are doing!
                /// 

                return expr.Arguments[0];
            }
            else
            {
                throw new NotImplementedException("Helpers." + expr.Method.Name + " is not handled!");
            }
        }
Пример #19
0
        /// <summary>
        /// We want to print the results out to a file.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// We can handle several types of streams here:
        /// 1) a stream of double's - this is just one column.
        /// 2) A stream of Tuples
        /// 3) A stream of custom objects
        /// </remarks>
        public override Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            // Argument checking
            var asTTree = resultOperator as AsTTreeResultOperator;
            if (asTTree == null)
                throw new ArgumentException("resultOperaton");

            // Declare the includes.
            gc.AddIncludeFile("<map>");
            gc.AddIncludeFile("TSystem.h");
            gc.AddIncludeFile("TFile.h");
            gc.AddIncludeFile("TTree.h");

            // If we were left to our own devices generating an output file, then make one up based on the tree name.
            var outputFile = asTTree.OutputFile != null
                ? asTTree.OutputFile
                : new FileInfo($"{asTTree.TreeName}.root");

            // Declare the TTree and the file we will be using!
            // Initialization is not important as we will over-write this directly.
            var stream = DeclarableParameter.CreateDeclarableParameterExpression(typeof(OutputTTreeFileType));
            stream.InitialValue = new OutputTTreeFileType(outputFile);

            // Generate a real filename. We are going to key the file by the cache key. Unfortunately, at this
            // point in the generation the cache key isn't known. So we have to have a 'promise' that can be used
            // for later when the code is actually generated.
            var outputFilePromise = GenerateUniqueFile(outputFile, cc);

            // Open the file and declare the tree
            gc.AddInitalizationStatement(new StatementSimpleStatement(() => $"{stream.RawValue}.first = new TFile(\"{outputFilePromise().FullName.AddCPPEscapeCharacters()}\",\"RECREATE\")", dependentVars: new string[0], resultVars: new string[] { stream.RawValue }));
            gc.AddInitalizationStatement(new StatementSimpleStatement($"{stream.RawValue}.second = new TTree(\"{asTTree.TreeName}\", \"{asTTree.TreeTitle}\")", dependentVars: new string[0],  resultVars: new string[] { stream.RawValue }));

            // Get the list of item values we are going to need here.
            List<Expression> itemValues = ExtractItemValueExpressions(queryModel);

            // We are just going to print out the line with the item in it.
            var itemAsValues = itemValues.Select(iv => ExpressionToCPP.GetExpression(iv, gc, cc, container)).ToArray();
            var pstatement = new StatementFillTree(stream, itemAsValues.Zip(asTTree.HeaderColumns, (i, h) => Tuple.Create(i, h)).ToArray());

            gc.Add(pstatement);

            // The return is a file path in the C# world. But here in C++, what should be returned?
            // We will use a string.
            return stream;
        }
		public static CSharpCompletionContext Get(ITextEditor editor, ICodeContext context, TextLocation currentLocation, ITextSource fileContent)
		{
			IDocument document = new ReadOnlyDocument(fileContent);
			
			var projectContent = context.Compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
			if (projectContent == null)
				return null;
			
			CSharpParser parser = new CSharpParser();
			parser.GenerateTypeSystemMode = false;
			
			SyntaxTree cu = parser.Parse(fileContent, Path.GetRandomFileName() + ".cs");
			cu.Freeze();
			
			CSharpUnresolvedFile unresolvedFile = cu.ToTypeSystem();
			ICompilation compilation = projectContent.AddOrUpdateFiles(unresolvedFile).CreateCompilation(SD.ParserService.GetCurrentSolutionSnapshot());
			
			return new CSharpCompletionContext(editor, EmptyList<string>.Instance, compilation, projectContent, document, unresolvedFile, currentLocation);
		}
        /// <summary>
        /// Parse an array expression, and turn it into a loop. Use indexName as the loop variable. Bomb if we can't do it. If you hand in null we will make up our own.
        /// </summary>
        /// <param name="query">The query that this loop is associated with.</param>
        /// <param name="expr">The expression that evaluates to an array.</param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        public static IVariableScopeHolder ParseArrayExpression(IQuerySource query, Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            if (_parser == null)
            {
                _parser = new ArrayExpressionParser();
                container.SatisfyImportsOnce(_parser);
            }

            var result = _parser.GetIArrayInfo(expr, gc, cc, container);

            if (result == null)
                throw new InvalidOperationException($"Can't figure out how to loop over this array: '{expr.ToString()}' (expression: '{expr.NodeType}', type: '{expr.Type.FullyQualifiedName()}')");

            //
            // Turn it into code - any code that we need.
            //

            return result.CodeLoopOverArrayInfo(query, gc, cc, container);
        }
Пример #22
0
        /// <summary>
        /// We want to print the results out to a file.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// We can handle several types of streams here:
        /// 1) a stream of double's - this is just one column.
        /// 2) A stream of Tuples
        /// 3) A stream of custom objects
        /// </remarks>
        public override Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            // Argument checking
            var asCSV = resultOperator as AsCSVResultOperator;
            if (asCSV == null)
                throw new ArgumentException("resultOperaton");

            // Declare the includes.
            gc.AddIncludeFile("<fstream>");
            gc.AddIncludeFile("<iostream>");

            // The output filename. How we do this is a little funny because we need the hash from the completely
            // done query, which isn't ready just yet.
            var outputFile = GenerateUniqueFile(asCSV.OutputFile, cc);
            var stream = DeclarableParameter.CreateDeclarableParameterExpression(typeof(OutputCSVTextFileType));
            stream.InitialValue = new OutputCSVTextFileType(outputFile);

            var headerline = new StringBuilder();
            bool first = true;
            foreach (var h in asCSV.HeaderColumns)
            {
                if (!first)
                {
                    headerline.Append(", ");
                }
                headerline.Append(h);
                first = false;
            }
            gc.AddInitalizationStatement(new Statements.StatementSimpleStatement($"{stream.RawValue} << \"{headerline.ToString()}\" << std::endl;", dependentVars: new string[0], resultVars: new string[] { stream.RawValue }));

            // Get the list of item values we are going to need here.
            List<Expression> itemValues = ExtractItemValueExpressions(queryModel);

            // We are just going to print out the line with the item in it.
            var itemAsValues = itemValues.Select(iv => ExpressionToCPP.GetExpression(iv, gc, cc, container));
            var pstatement = new StatementCSVDump(stream, itemAsValues.ToArray());
            gc.Add(pstatement);

            // The return is a file path in the C# world. But here in C++, what should be returned?
            // We will use a string.
            return stream;
        }
 /// <summary>
 /// This will be handled later on, by the general infrastructure.
 /// </summary>
 /// <param name="expr"></param>
 /// <param name="gc"></param>
 /// <param name="cc"></param>
 /// <param name="container"></param>
 /// <returns></returns>
 public IValue ProcessMemberReference(MemberExpression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
 {
     return(null);
 }
Пример #24
0
		public CSharpCompletionBinding(ICodeContext context, TextLocation currentLocation, ITextSource fileContent)
		{
			this.context = context;
			this.currentLocation = currentLocation;
			this.fileContent = fileContent;
		}
 /// <summary>
 /// No member lookup is possible (though it might be eventually!).
 /// </summary>
 /// <param name="expr"></param>
 /// <param name="gc"></param>
 /// <param name="cc"></param>
 /// <param name="container"></param>
 /// <returns></returns>
 public IValue ProcessMemberReference(MemberExpression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
 {
     throw new NotImplementedException();
 }
Пример #26
0
        /// <summary>
        /// Code up the min/max result operators. We run the loop out, and then
        /// we return the result whatever it is. We only work when the type is
        /// something simple we can deal with!
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            ///
            /// Some argument checking
            ///

            if (cc == null)
            {
                throw new ArgumentNullException("cc");
            }

            if (gc == null)
            {
                throw new ArgumentNullException("gc");
            }

            if (gc.Depth == 1)
            {
                throw new ArgumentException("The Max/Min operators can't be used as result operators for a query - they can only be used in a sub-query");
            }

            ///
            /// Is it min or max?
            ///

            var minOperator = resultOperator as MinResultOperator;
            var maxOperator = resultOperator as MaxResultOperator;

            if (minOperator == null && maxOperator == null)
            {
                throw new InvalidOperationException("Should always have min or max operator!");
            }

            bool doMax = maxOperator != null;

            bool returnDefaultValue = false;

            if (doMax)
            {
                returnDefaultValue = maxOperator.ReturnDefaultWhenEmpty;
            }
            else
            {
                returnDefaultValue = minOperator.ReturnDefaultWhenEmpty;
            }

            ///
            /// Next, look at the type of the current result that is running.
            ///

            var valueExpr = queryModel.SelectClause.Selector;

            if (!TimeCanBeCompared(valueExpr.Type))
            {
                throw new ArgumentException(string.Format("I don't know how to fix the min or max of a sequence of '{0}'s", cc.LoopVariable.Type.Name));
            }

            ///
            /// Now, declare two variables, one bool which gets set when we get the first value,
            /// and the other to hold the min/max value! Note that we initalize the variable to
            /// the proper type. We don't declare minmax holder - as it may end up be used
            /// externally.
            ///

            var vIsFilled = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));

            vIsFilled.InitialValue = new ValSimple("false", typeof(bool), null);
            var vMaxMin = DeclarableParameter.CreateDeclarableParameterExpression(valueExpr.Type);

            vMaxMin.InitialValue = new ValSimple("0", typeof(int), null);

            gc.AddOutsideLoop(vIsFilled);

            ///
            /// The expression we want to mimize or maximize
            ///

            var exprToMinOrMaximize = ExpressionToCPP.GetExpression(valueExpr, gc, cc, container);

            ///
            /// Now, we just have to put the x-checks in there.
            ///

            var ifStatement = new Statements.StatementMinMaxTest(vIsFilled, vMaxMin, exprToMinOrMaximize, doMax);

            gc.Add(ifStatement);

            return(vMaxMin);
        }
Пример #27
0
 public IValue ProcessMemberReference(MemberExpression expr, IGeneratedQueryCode gc, ICodeContext cc, System.ComponentModel.Composition.Hosting.CompositionContainer container)
 {
     return(null);
 }
 public Expression ProcessResultOperator(Remotion.Linq.Clauses.ResultOperatorBase resultOperator, Remotion.Linq.QueryModel queryModel, IGeneratedQueryCode _codeEnv, ICodeContext codeContext, CompositionContainer container)
 {
     throw new NotImplementedException();
 }
Пример #29
0
        /// <summary>
        /// Performs all expression subsitutions known by the code context on the input. It does not
        /// touch the input - but returns a new IValue. Types are not tracked.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="cc"></param>
        /// <returns></returns>
        /// <remarks>
        /// This exists because sometimes you need to do this sort of replacement when dealing with complex
        /// expressions that don't translated to C# easily. In partiuclar, for example, the iterator expressions
        /// that are used to move through maps in the Group By operators. Otherwise, the regular GetExpression would
        /// do this just fine.
        /// </remarks>
        public static IValue PerformAllSubstitutions(this IValue input, ICodeContext cc)
        {
            var vFinder = new Regex(@"\b(?<vname>[\w]*)\b");
            string v = input.RawValue;
            bool subDone = true;
            int count = 0;
            while (subDone)
            {
                count++;
                if (count > 100)
                    throw new InvalidOperationException(string.Format("Unable to translate '{0}' due to too many sutstitutions.", input.RawValue));

                subDone = false;
                foreach (Match match in vFinder.Matches(v))
                {
                    var vname = match.Groups["vname"].Value;
                    var r = cc.GetReplacement(vname);
                    if (r != null)
                    {
                        v = Regex.Replace(v, string.Format(@"\b{0}\b", vname), r.ParameterName());
                        subDone = true;
                    }
                }
            }

            if (count == 1)
                return input;

            return new ValSimple(v, input.Type, input.Dependants);
        }
Пример #30
0
 public Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, System.ComponentModel.Composition.Hosting.CompositionContainer container)
 {
     return(expr);
 }
 public Tuple<Expression, IDeclaredParameter> AddLoop(IGeneratedQueryCode env, ICodeContext context, CompositionContainer container)
 {
     return null;
 }
Пример #32
0
 ICodeCompletionBinding ILanguageBinding.CreateCompletionBinding(string expressionToComplete, ICodeContext context)
 {
     return null;
 }
Пример #33
0
 public Tuple<bool, Expression> ProcessIdentityQuery(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode _codeEnv, ICodeContext _codeContext, CompositionContainer container)
 {
     return null;
 }
 public Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, CompositionContainer container)
 {
     throw new NotImplementedException();
 }
Пример #35
0
        /// <summary>
        /// Code up the min/max result operators. We run the loop out, and then
        /// we return the result whatever it is. We only work when the type is
        /// something simple we can deal with!
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            ///
            /// Some argument checking
            /// 

            if (cc == null)
                throw new ArgumentNullException("cc");

            if (gc == null)
                throw new ArgumentNullException("gc");

            if (gc.Depth == 1)
                throw new ArgumentException("The Max/Min operators can't be used as result operators for a query - they can only be used in a sub-query");

            ///
            /// Is it min or max?
            /// 

            var minOperator = resultOperator as MinResultOperator;
            var maxOperator = resultOperator as MaxResultOperator;

            if (minOperator == null && maxOperator == null)
                throw new InvalidOperationException("Should always have min or max operator!");

            bool doMax = maxOperator != null;

            bool returnDefaultValue = false;
            if (doMax)
                returnDefaultValue = maxOperator.ReturnDefaultWhenEmpty;
            else
                returnDefaultValue = minOperator.ReturnDefaultWhenEmpty;

            ///
            /// Next, look at the type of the current result that is running.
            /// 

            var valueExpr = queryModel.SelectClause.Selector;
            if (!TimeCanBeCompared(valueExpr.Type))
                throw new ArgumentException(string.Format("I don't know how to fix the min or max of a sequence of '{0}'s", cc.LoopVariable.Type.Name));

            ///
            /// Now, declare two variables, one bool which gets set when we get the first value,
            /// and the other to hold the min/max value! Note that we initalize the variable to
            /// the proper type. We don't declare minmax holder - as it may end up be used
            /// externally.
            /// 

            var vIsFilled = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));
            vIsFilled.InitialValue = new ValSimple("false", typeof(bool), null);
            var vMaxMin = DeclarableParameter.CreateDeclarableParameterExpression(valueExpr.Type);
            vMaxMin.InitialValue = new ValSimple("0", typeof(int), null);

            gc.AddOutsideLoop(vIsFilled);

            ///
            /// The expression we want to mimize or maximize
            /// 

            var exprToMinOrMaximize = ExpressionToCPP.GetExpression(valueExpr, gc, cc, container);

            ///
            /// Now, we just have to put the x-checks in there.
            /// 

            var ifStatement = new Statements.StatementMinMaxTest(vIsFilled, vMaxMin, exprToMinOrMaximize, doMax);
            gc.Add(ifStatement);

            return vMaxMin;
        }
Пример #36
0
 /// <summary>
 /// The AsQueriable, for us, is a no-op. We will just pass things along.
 /// </summary>
 /// <param name="resultOperator"></param>
 /// <param name="queryModel"></param>
 /// <param name="_codeEnv"></param>
 /// <param name="_codeContext"></param>
 /// <param name="container"></param>
 public void ProcessResultOperator(ResultOperatorBase resultOperator,
                                   QueryModel queryModel,
                                   IGeneratedQueryCode _codeEnv, ICodeContext _codeContext, CompositionContainer container)
 {
 }
 /// <summary>
 /// A method call is our bread and butter. However, there is no internal translation to be done, so we can wait
 /// until the end of the translation process when it is time to turn it into real IValue.
 /// </summary>
 /// <param name="expr"></param>
 /// <param name="gc"></param>
 /// <param name="context"></param>
 /// <param name="container"></param>
 /// <returns></returns>
 public Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, CompositionContainer container)
 {
     return expr;
 }
Пример #38
0
 public IValue ProcessMemberReference(MemberExpression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
 {
     throw new NotImplementedException();
 }
Пример #39
0
 public Tuple <bool, Expression> ProcessIdentityQuery(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode _codeEnv, ICodeContext _codeContext, CompositionContainer container)
 {
     return(null);
 }