// 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 )); } }
// _parseDottedExpr gathers infix dotted member access expressions. The // object expression can be anything and is passed in via expr. Successive // member accesses must be dotted identifier expressions or member invokes -- // a.b.(c 3).d. The member invokes cannot have dotted expressions for the // member name such as a.(b.c 3). // private SymplDottedExpr ParseDottedExpr(Lexer lexer, SymplExpr objExpr) { Token token = lexer.GetToken(); if (token != SyntaxToken.Dot) { throw new SymplParseException( "Internal: parsing dotted expressions?"); } List <SymplExpr> exprs = new List <SymplExpr>(); token = lexer.GetToken(); while (token is IdOrKeywordToken || token == SyntaxToken.Paren) { // Needs to be fun call or IDs SymplExpr expr; if (token is IdOrKeywordToken) { // Keywords are ok as member names. expr = new SymplIdExpr((IdOrKeywordToken)token); } else { lexer.PutToken(token); expr = ParseForm(lexer); SymplFunCallExpr funCall = expr as SymplFunCallExpr; if (funCall != null || !(funCall.Function is SymplIdExpr)) { throw new SymplParseException( "Dotted expressions must be identifiers or " + "function calls with identiers as the function " + "value -- " + expr.ToString()); } } exprs.Add(expr); token = lexer.GetToken(); if (token != SyntaxToken.Dot) { break; } token = lexer.GetToken(); } lexer.PutToken(token); return(new SymplDottedExpr(objExpr, exprs.ToArray())); }