protected override Expression LookupOther(string id, Type type, Type funcType)
        {
            if (!externalFunctions.TryGetValue(id, out var expr))
            {
                return(base.LookupOther(id, type, funcType));
            }

            var typeMap     = funcType.UnifyExact(expr.Type);
            var substitutor = new TypeSubstitutionExpressionVisitor(typeMap);
            var unifiedExpr = substitutor.Visit(expr);

            return(unifiedExpr);
        }
Пример #2
0
        public void Evaluate(Expression expression)
        {
            var subst = new TypeSubstitutionExpressionVisitor(new Dictionary <Type, Type>
            {
                { typeof(IQubjectFactory <>), typeof(ISubjectFactory <>) },
                { typeof(IQubject <>), typeof(ISubject <>) },
                { typeof(IQbservable <>), typeof(IObservable <>) },
                { typeof(IQbserver <>), typeof(IObserver <>) },
                { typeof(IQubscription), typeof(IDisposable) },
            });

            var expr = subst.Visit(expression);

            var fvs = FreeVariableScanner.Scan(expr);

            var map = new Dictionary <ParameterExpression, Expression>();

            foreach (var fv in fvs)
            {
                if (_registry.TryGetValue(fv.Name, out var res))
                {
                    if (res is Expression e)
                    {
                        var u = e.Type.UnifyExact(fv.Type);
                        var f = new TypeSubstitutionExpressionVisitor(u).Visit(e);
                        map.Add(fv, f);
                        continue;
                    }
                    else
                    {
                        e = Expression.Constant(res, fv.Type);
                        map.Add(fv, e);
                        continue;
                    }
                }

                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Could not bind '{0}'.", fv.Name));
            }

            var bound = new Binder(map).Bind(expr);

            if (bound.Type == typeof(void))
            {
                // TODO: Evaluate method could be more forgiving for void-returning delegates (no automatic coercion to object)
                bound = Expression.Block(bound, Expression.Default(typeof(object)));
            }

            bound.Evaluate();
        }
 /// <summary>
 /// Visits and substitutes types of an expression which is the body of a lambda abstraction.
 /// </summary>
 /// <param name="body">The expression to visit.</param>
 /// <returns>Result of visiting the expression.</returns>
 protected override LambdaExpression VisitLambdaAbstractionBody(LambdaExpression body)
 {
     return((LambdaExpression)_lambdaBodyConverter.Visit(body));
 }