public static object Execute(CodeContext context, ActionBinder binder, DynamicAction action, params object[] args)
        {
            switch (args.Length)
            {
            case 1:
                return(binder.ExecuteRule <DynamicSiteTarget <object, object> >(context, action, args));

            case 2:
                return(binder.ExecuteRule <DynamicSiteTarget <object, object, object> >(context, action, args));

            case 3:
                return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object> >(context, action, args));

            case 4:
                return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object, object> >(context, action, args));

            case 5:
                return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object, object, object> >(context, action, args));

            case 6:
                return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object, object, object, object> >(context, action, args));

            default:
                //TODO: use CompilerHelpers.GetTypes(args) instead?
                Type       tupleType  = Tuple.MakeTupleType(CompilerHelpers.MakeRepeatedArray <Type>(typeof(object), args.Length));
                Type       targetType = typeof(BigDynamicSiteTarget <,>).MakeGenericType(tupleType, typeof(object));
                Type       ruleType   = typeof(StandardRule <>).MakeGenericType(targetType);
                MethodInfo getRule    = typeof(ActionBinder).GetMethod("GetRule").MakeGenericMethod(targetType);
                while (true)
                {
                    object         ruleN     = getRule.Invoke(binder, new object[] { context, action, args });
                    Ast.Expression test      = (Ast.Expression)ruleType.GetProperty("Test").GetValue(ruleN, null);
                    Ast.Statement  target    = (Ast.Statement)ruleType.GetProperty("Target").GetValue(ruleN, null);
                    Ast.Variable[] paramVars = (Ast.Variable[])ruleType.GetProperty("ParamVariables",
                                                                                    BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ruleN, null);
                    Ast.Variable[] tempVars = (Ast.Variable[])ruleType.GetProperty("TemporaryVariables",
                                                                                   BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ruleN, null);


                    Tuple       t      = Tuple.MakeTuple(tupleType, args);
                    object[]    tupArg = new object[] { t };
                    CodeContext tmpCtx = context.Scope.GetTemporaryVariableContext(context, paramVars, tupArg);
                    try {
                        bool result = (bool)test.Evaluate(tmpCtx);
                        if (!result)
                        {
                            // The test may evaluate as false if:
                            // 1. The rule was generated as invalid. In this case, the language binder should be fixed to avoid
                            //    generating invalid rules.
                            // 2. The rule was invalidated in the small window between calling GetRule and Evaluate. This is a
                            //    valid scenario. In such a case, we need to call Evaluate again to ensure that all expected
                            //    side-effects are visible to Execute below.
                            // This assert is not valid in the face to #2 above. However, it is left here until all issues in
                            // the interpreter and the language binders are flushed out
                            Debug.Assert(result);
                            continue;
                        }

                        return(target.Execute(tmpCtx));
                    } finally {
                        tmpCtx.Scope.TemporaryStorage.Clear();
                    }
                }
            }
        }