Пример #1
0
        // Returns a dynamic InvokeMember or Invoke expression, depending on the
        // Function expression.
        //
        public static DynamicExpression AnalyzeFunCallExpr(
            SymplFunCallExpr expr, AnalysisScope scope)
        {
            if (expr.Function is SymplDottedExpr)
            {
                SymplDottedExpr dottedExpr = (SymplDottedExpr)expr.Function;
                Expression      objExpr;
                int             length = dottedExpr.Exprs.Length;
                if (length > 1)
                {
                    objExpr = AnalyzeDottedExpr(
                        // create a new dot expression for the object that doesn't
                        // include the last part
                        new SymplDottedExpr(
                            dottedExpr.ObjectExpr,
                            RuntimeHelpers.RemoveLast(dottedExpr.Exprs)),
                        scope
                        );
                }
                else
                {
                    objExpr = AnalyzeExpr(dottedExpr.ObjectExpr, scope);
                }
                List <Expression> args = new List <Expression>();
                args.Add(objExpr);
                args.AddRange(expr.Arguments.Select(a => AnalyzeExpr(a, scope)));

                // last expr must be an id
                var lastExpr = (SymplIdExpr)(dottedExpr.Exprs.Last());
                return(Expression.Dynamic(
                           scope.GetRuntime().GetInvokeMemberBinder(
                               new InvokeMemberBinderKey(
                                   lastExpr.IdToken.Name,
                                   new CallInfo(expr.Arguments.Length))),
                           typeof(object),
                           args
                           ));
            }
            else
            {
                var fun = AnalyzeExpr(expr.Function, scope);
                List <Expression> args = new List <Expression>();
                args.Add(fun);
                args.AddRange(expr.Arguments.Select(a => AnalyzeExpr(a, scope)));
                // Use DynExpr so that I don't always have to have a delegate to call,
                // such as what happens with IPy interop.
                return(Expression.Dynamic(
                           scope.GetRuntime()
                           .GetInvokeBinder(new CallInfo(expr.Arguments.Length)),
                           typeof(object),
                           args
                           ));
            }
        }
Пример #2
0
        // Returns a chain of GetMember and InvokeMember dynamic expressions for
        // the dotted expr.
        //
        public static Expression AnalyzeDottedExpr(SymplDottedExpr expr,
                                                   AnalysisScope scope)
        {
            var curExpr = AnalyzeExpr(expr.ObjectExpr, scope);

            foreach (var e in expr.Exprs)
            {
                if (e is SymplIdExpr)
                {
                    curExpr = Expression.Dynamic(
                        scope.GetRuntime()
                        .GetGetMemberBinder(((SymplIdExpr)e).IdToken.Name),
                        typeof(object),
                        curExpr
                        );
                }
                else if (e is SymplFunCallExpr)
                {
                    var call = (SymplFunCallExpr)e;
                    List <Expression> args = new List <Expression>();
                    args.Add(curExpr);
                    args.AddRange(call.Arguments.Select(a => AnalyzeExpr(a, scope)));

                    curExpr = Expression.Dynamic(
                        // Dotted exprs must be simple invoke members, a.b.(c ...)
                        scope.GetRuntime().GetInvokeMemberBinder(
                            new InvokeMemberBinderKey(
                                ((SymplIdExpr)call.Function).IdToken.Name,
                                new CallInfo(call.Arguments.Length))),
                        typeof(object),
                        args
                        );
                }
                else
                {
                    throw new InvalidOperationException(
                              "Internal: dotted must be IDs or Funs.");
                }
            }
            return(curExpr);
        }
Пример #3
0
        // first sub form must be expr resulting in callable, but if it is dotted expr,
        // then eval the first N-1 dotted exprs and use invoke member or get member
        // on last of dotted exprs so that the 2..N sub forms are the arguments to
        // the invoke member.  It's as if the call breaks into a block of a temp
        // assigned to the N-1 dotted exprs followed by an invoke member (or a get
        // member and call, which the runtime binder decides).  The non-dotted expr
        // simply evals to an object that better be callable with the supplied args,
        // which may be none.
        //
        private SymplFunCallExpr ParseFunctionCall(Lexer lexer)
        {
            // First sub expr is callable object or invoke member expr.
            var fun = ParseExprAux(lexer);

            if (fun is SymplDottedExpr)
            {
                SymplDottedExpr dottedExpr = (SymplDottedExpr)fun;
                // Keywords ok as members.
                if (!(dottedExpr.Exprs.Last() is SymplIdExpr))
                {
                    throw new SymplParseException(
                              "Function call with dotted expression for function must " +
                              "end with ID Expr, not member invoke." +
                              dottedExpr.Exprs.Last().ToString());
                }
            }
            // Tail exprs are args.
            var args = ParseBody(lexer, "Unexpected EOF in arg list for " +
                                 fun.ToString());

            return(new SymplFunCallExpr(fun, args));
        }