// 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 )); } }