示例#1
0
        public override void ProcessClosures(Context ctx)
        {
            if(LeftOperand is LambdaNode)
                LeftOperand.ProcessClosures(ctx);

            if (RightOperand is LambdaNode)
                RightOperand.ProcessClosures(ctx);

            var leftType = LeftOperand.GetExpressionType(ctx);

            var rightGetter = RightOperand as GetMemberNode;
            if (!IsLeft && leftType.IsCallableType() && rightGetter != null)
            {
                if (rightGetter.TypeHints.IsEmpty())
                {
                    var returnType = ctx.ResolveMethod(leftType, "Invoke").ReturnType;
                    rightGetter.TypeHints = new List<TypeSignature> {TypeSignature.Parse(returnType.FullName)};
                }
            }

            var rightType = RightOperand.GetExpressionType(ctx);

            if (rightGetter != null)
                rightGetter.TypeHints.Clear();

            if (!IsLeft && leftType.IsCallableType() && rightType.IsCallableType())
            {
                if (!ctx.CanCombineDelegates(leftType, rightType))
                    Error(Translations.CompilerMessages.DelegatesNotCombinable, leftType, rightType);

                var argTypes = ctx.WrapDelegate(leftType).ArgumentTypes;
                var argGetters = argTypes.Select((a, id) => Expr.GetArg(id)).Cast<NodeBase>().ToArray();

                if (LeftOperand is GetMemberNode)
                    (LeftOperand as GetMemberNode).TypeHints.Clear();

                _Method = ctx.CurrentScope.CreateClosureMethod(ctx, argTypes, ctx.WrapDelegate(rightType).ReturnType);
                _Method.Body =
                    Expr.Block(
                        Expr.Invoke(
                            RightOperand,
                            Expr.Invoke(
                                LeftOperand,
                                argGetters
                            )
                        )
                    );

                var methodBackup = ctx.CurrentMethod;
                ctx.CurrentMethod = _Method;

                var scope = _Method.Scope;
                scope.InitializeScope(ctx);

                _Method.Body.ProcessClosures(ctx);
                _Method.PrepareSelf();

                scope.FinalizeScope(ctx);

                ctx.CurrentMethod = methodBackup;
            }
        }