private void BuildClientExecuteCode(CodeExpression continuationExpression, CodeExpressionWithFreeVariables generatedCode) { var freeVariableValues = this.ClientQueryFreeVariableAssignmentsExtractingVisitor.ExtractFreeVariableAssignments(this.QueryExpression); // find the number of possible values for all free variables in the expression var maxValueCount = 0; if (generatedCode.FreeVariables.Any()) { maxValueCount = generatedCode.FreeVariables.Max(fv => fv.PossibleValues.Count); } var freeVariableAssignments = new Dictionary <string, QueryExpression>(); // declare free variables and assign their first values foreach (var free in generatedCode.FreeVariables) { this.CodeBuilder.Add(Code.DeclareVariable(free.VariableType, free.Name, free.PossibleValues.First())); freeVariableAssignments[free.Name] = freeVariableValues[free.Name][0]; } // var expression = ... generatedQuery var queryVariable = this.CodeBuilder.Declare("query", generatedCode.Expression); // simple case with 0 or 1 values for free variables if (maxValueCount <= 1) { this.CodeBuilder.Add(this.BuildQueryExecuteCallAndVariables(continuationExpression, queryVariable, freeVariableAssignments)); } else { // create actionList variable which will hold all verification calls // since verification is asynchronous this will let us serialize the calls by doing RunActionSequence if (this.IsAsync) { this.BuildExecuteAndCompareAsyncCall(freeVariableValues, continuationExpression, generatedCode, maxValueCount, freeVariableAssignments, queryVariable); } else { this.BuildExecuteAndCompareSync(freeVariableValues, continuationExpression, generatedCode, maxValueCount, freeVariableAssignments, queryVariable); } } }
private void BuildExecuteAndCompareSync(Dictionary <string, ReadOnlyCollection <QueryExpression> > freeVariableValues, CodeExpression continuationExpression, CodeExpressionWithFreeVariables generatedCode, int maxValueCount, Dictionary <string, QueryExpression> freeVariableAssignments, CodeExpression queryVariable) { for (int j = 0; j < maxValueCount; ++j) { foreach (var free in generatedCode.FreeVariables) { freeVariableAssignments[free.Name] = freeVariableValues[free.Name][j % freeVariableValues[free.Name].Count]; } this.CodeBuilder.Add(this.BuildQueryExecuteCallAndVariables(continuationExpression, queryVariable, freeVariableAssignments)); } }
private void BuildExecuteAndCompareAsyncCall(Dictionary <string, ReadOnlyCollection <QueryExpression> > freeVariableValues, CodeExpression continuationExpression, CodeExpressionWithFreeVariables generatedCode, int maxValueCount, Dictionary <string, QueryExpression> freeVariableAssignments, CodeExpression queryVariable) { var listVariable = this.CodeBuilder.Declare( "actionList", Code.New(Code.TypeRef <List <Action <IAsyncContinuation> > >())); for (int j = 0; j < maxValueCount; ++j) { if (j > 0) { // for anything but the first value, set the new value of each free variable var lambda = Code.Lambda().WithParameter("c"); this.CodeBuilder.BeginLambda(lambda); foreach (var freeVar in generatedCode.FreeVariables) { this.CodeBuilder.Add(Code.Variable(freeVar.Name).Assign(freeVar.PossibleValues[j % freeVar.PossibleValues.Count])); } this.CodeBuilder.Add(Code.Argument("c").Call("Continue")); this.CodeBuilder.EndLambda(); this.CodeBuilder.Add(listVariable.Call("Add", lambda)); } foreach (var free in generatedCode.FreeVariables) { freeVariableAssignments[free.Name] = freeVariableValues[free.Name][j % freeVariableValues[free.Name].Count]; } var lambdaBody = this.BuildQueryExecuteCallAndVariables(Code.Argument("c"), queryVariable, freeVariableAssignments); // add the lambda body to the list this.CodeBuilder.Add(listVariable.Call("Add", Code.Lambda().WithParameter("c").WithBody(lambdaBody))); } // add code to run all lambdas accumulated so far this.CodeBuilder.Add(Code.Type(typeof(AsyncHelpers).Name).Call("RunActionSequence", continuationExpression, listVariable)); }