public static Func <ResultT> Prepare <ResultT>(Expression body, ReadOnlyCollection <ParameterExpression> parameters = null)
        {
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }

            var collector = new ConstantsCollector();

            collector.Visit(body);

            var constExpressions     = collector.Constants.ToArray();
            var parameterExpressions = Constants.EmptyParameters;
            var compiledBody         = Compile(body, constExpressions, parameterExpressions);
            var constants            = Array.ConvertAll(constExpressions, c => c.Value);

            return(() =>
            {
                var locals = new object[] { null, null, null };
                var closure = new Closure(constants, locals);

                var result = (ResultT)compiledBody.Run(closure);
                Array.Clear(locals, 0, locals.Length);
                return result;
            });
        }
        public static Func <Arg1T, Arg2T, Arg3T, ResultT> PrepareFunc <Arg1T, Arg2T, Arg3T, ResultT>(Expression body, ReadOnlyCollection <ParameterExpression> parameters)
        {
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            var collector = new ConstantsCollector();

            collector.Visit(body);

            var constExpressions     = collector.Constants.ToArray();
            var parameterExpressions = parameters.ToArray();
            var compiledBody         = Compile(body, constExpressions, parameterExpressions);
            var constants            = ArrayUtils.ConvertAll(constExpressions, c => c.Value);

            return((arg1, arg2, arg3) =>
            {
                var locals = new object[] { null, null, null, arg1, arg2, arg3 };
                var closure = new Closure(constants, locals);

                var result = closure.Unbox <ResultT>(compiledBody.Run(closure));
                Array.Clear(locals, 0, locals.Length);
                return result;
            });
        }