/// <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)); }
/// <summary> /// Turn a query model into code. /// </summary> /// <param name="queryModel"></param> private void VisitQueryModelNoCache(QueryModel queryModel) { // Cache the referenced query expressions and restore them at the end. var cachedReferencedQS = _codeContext.GetAndResetQuerySourceLookups(); // Protect against all returns... try { // // If the query model is something that is trivial, then // perhaps there is a short-cut we can take? // if (queryModel.IsIdentityQuery() && queryModel.ResultOperators.Count == 1) { var ro = queryModel.ResultOperators[0]; var processor = _operators.FindScalarROProcessor(ro.GetType()); if (processor != null) { var result = processor.ProcessIdentityQuery(ro, queryModel, _codeEnv, _codeContext, MEFContainer); if (result != null && result.Item1) { Debug.WriteLine("Identity Query being processed"); _codeEnv.SetResult(result.Item2); return; } } } // Have we seen this query model before? If so, perhaps we can just short-circuit this? var cachedResult = _codeContext.GetReplacement(queryModel); if (cachedResult != null) { var context = _codeEnv.FirstAllInScopeFromNow(FindDeclarableParameters.FindAll(cachedResult)); if (context != null) { _codeEnv.SetResult(cachedResult); return; } } // If we drop through here, then let the full machinery parse the thing base.VisitQueryModel(queryModel); } finally { _codeContext.RestoreQuerySourceLookups(cachedReferencedQS); } }
/// <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); }
/// <summary> /// Do the lookup for the expression, and recursivly resolve it, incease there are further /// parameters in it. /// </summary> /// <param name="exprName"></param> /// <returns></returns> private Expression ResolveExpressionReplacement(string exprName) { var replaceit = _context.GetReplacement(exprName); return(Visit(replaceit)); }