static IEnumerable <FuncDef> DefineProjectionFuncsImpl(CallExpr ce, Generator.Ctx ctx, bool acceptVector) { var inpParams = ((IList)OPs.GetConstant(ctx, ce.args[0])).Cast <object>().Select(Convert.ToString).ToArray(); var inpParamsParts = inpParams.Select(s => s.Split('_')).ToArray(); var inpParamsMasks = inpParamsParts.Where(parts => parts.Any(string.IsNullOrEmpty)).ToArray(); var outParams = ((IList)OPs.GetConstant(ctx, ce.args[1])).Cast <object>().Select(Convert.ToString).ToArray(); var outParamsMasks = outParams.Select(s => Convert.ToString(s).Split('_')).ToArray(); var newFuncName = "@projfunc:" + ce.args[ce.args.Count - 1].ToString().Replace('(', '_').Replace(')', '_').Replace('"', '_').Replace('\'', '_'); #region Collect suitable parameters from all functions outputs var suitableParams = new Dictionary <string, string[]>(StringComparer.OrdinalIgnoreCase); foreach (var f in ctx.GetFunc(null, 0)) { foreach (var prm in f.resultsInfo) { var prmParts = prm.Parts(); for (int i = 0; i < inpParamsMasks.Length; i++) { var maskParts = inpParamsMasks[i]; var details = GetDetailsIfMatched(prmParts, maskParts); if (details == null) { continue; } if (!suitableParams.TryGetValue(details, out var suitables)) { suitables = new string[inpParamsMasks.Length]; suitableParams.Add(details, suitables); } suitables[i] = details; } } } #endregion #region Return FuncDef for each suitable params set foreach (var suitable in suitableParams.Where(prms => prms.Value.All(s => s != null))) { var details = suitable.Key; var inps = new string[inpParamsParts.Length]; for (int i = 0; i < inpParamsParts.Length; i++) { var ip = inpParamsParts[i]; if (ip.Any(string.IsNullOrEmpty)) { // one or more parts masked inps[i] = ParamFromMaskAndDetails(details, ip); } else { inps[i] = inpParams[i]; } } var outs = new string[outParams.Length]; for (int i = 0; i < outParamsMasks.Length; i++) { outs[i] = ParamFromMaskAndDetails(details, outParamsMasks[i]); } yield return(FuncDefs_Core.macroFuncImpl( context: ctx, nameForNewFunc: new ConstExpr(newFuncName + details), inpsDescriptors: new ArrayExpr(inps.Select(ReferenceExpr.Create).Cast <Expr>().ToList()), outsDescriptors: new ArrayExpr(outs.Select(ReferenceExpr.Create).Cast <Expr>().ToList()), funcBody: ce.args[ce.args.Count - 1], inputParameterToSubstitute: (ce.args.Count > 3) ? ce.args[2] : null, funcAcceptVector: acceptVector )); } #endregion }