Esempio n. 1
0
        /// <summary>
        /// Mezcla dos matches, devuelve null si los matches tienen parametros con valores diferentes entre sí.
        /// Si alguno de los dos es null, devuelve null
        /// </summary>
        public static PartialMatch Merge(PartialMatch a, PartialMatch b)
        {
            var argDic  = MergeDic(a?.Args, b?.Args, CompareExpr.ExprEquals);
            var typeDic = MergeDic(a?.Types, b?.Types, CompareExpr.TypeEquals);

            if (argDic == null || typeDic == null)
            {
                return(null);
            }

            return(new PartialMatch(typeDic, argDic));
        }
Esempio n. 2
0
        /// <summary>
        /// Un partial match de un parámetro, devuelve un match si el parametro tiene un tipo AnyType o si el tipo de la expresión es igual al tipo del parametro.
        /// Si el tipo del parametro no encaja devuelve null
        /// </summary>
        public static PartialMatch FromParam(ParameterExpression param, Expression expr)
        {
            var paramType = param.Type;
            var argDic    = new Dictionary <ParameterExpression, Expression>
            {
                { param, expr }
            };
            var valueMatch = new PartialMatch(EmptyTypes, argDic);
            var typeMatch  = FromType(param.Type, expr.Type);

            var ret = Merge(valueMatch, typeMatch);

            return(ret);
        }
Esempio n. 3
0
        /// <summary>
        /// Convierte un PartialMatch a un Match. Devuelve null si el PartialMatch no esta completo
        /// </summary>
        public static Match ToFullMatch(PartialMatch match, IEnumerable <ParameterExpression> parameters)
        {
            if (match == null)
            {
                return(null);
            }

            var ret = parameters.Select(x =>
            {
                if (match.Args.TryGetValue(x, out Expression value))
                {
                    return(value);
                }
                return(null);
            }).ToList();

            if (ret.Any(x => x == null))
            {
                return(null);
            }

            return(new Match(match.Types, ret.ToList()));
        }
Esempio n. 4
0
        /// <summary>
        /// Devuelve el resultado de aplicar una regla al niver superior de la expresión o la expresión original si la regla no se pudo aplicar a la expresión
        /// </summary>
        public static Expression GlobalApplyRule(Expression expr, RewriteRule rule, Func <Expression, Expression> visit)
        {
            if (rule.DebugName == "convertFromParam" || rule.DebugName == "fromParam")
            {
                ;
            }
            var          parameters = rule.Find.Parameters;
            var          pattBody   = rule.Find.Body;
            PartialMatch partialMatch;

            try
            {
                partialMatch = GlobalMatch(expr, parameters, pattBody);
            }
            catch (Exception ex)
            {
                throw new ApplyRuleException("Error al obtener el match", rule.DebugName, expr, ex);
            }
            var match = PartialMatch.ToFullMatch(partialMatch, parameters);

            if (match == null)
            {
                return(expr);
            }

            if (rule.Condition != null && !rule.Condition(match, expr))
            {
                return(expr);
            }

            //Sustituir la expresión:
            var ret           = expr;
            var replaceLambda = rule.Replace;

            if (replaceLambda != null)
            {
                var subDic = replaceLambda.Parameters
                             .Select((x, i) => (par: x, value: match.Args[i]))
                             .ToDictionary(x => (Expression)x.par, x => x.value)
                ;

                Expression repRet;
                try
                {
                    repRet = ReplaceVisitor.Replace(replaceLambda.Body, subDic, match.Types, x => false);
                }
                catch (Exception ex)
                {
                    throw new ApplyRuleException("Error al reemplazar", rule.DebugName, expr, ex);
                }

                ret = repRet;
            }

            //Aplicar los transforms:
            {
                Expression nextRet;

                try
                {
                    nextRet = ReplaceVisitor.Replace(ret, ex =>
                    {
                        if (ex is MethodCallExpression call && call.Method.DeclaringType == typeof(RewriteSpecial) && call.Method.Name == nameof(RewriteSpecial.Transform))
                        {
                            //Aplica el transform a la expresión:
                            var arg     = call.Arguments[0];
                            var func    = ExprEval.EvalExpr <Func <Expression, Expression> >(call.Arguments[1]);
                            var tResult = func.Value(arg);
                            return(tResult);
                        }
                        return(ex);
                    });
                }