xronos /System.Xronos/Language/FunctionHelper.cs

Language C# Lines 62
MD5 Hash aaba6ceb9dafe47166df2e7b20401522 Estimated Cost $1,261 (why?)
Repository https://bitbucket.org/stefanrusek/xronos View Raw File
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Runtime.CompilerServices;
using System.Xronos.Scripting.Binders;
using Microsoft.Linq.Expressions;

namespace System.Xronos.Language
{
    public static class FunctionHelper
    {
        public static T Invoke<T>(object func, ISequence args)
        {
            var newArgs = new List<object>();
            while (args != null)
            {
                newArgs.Add(args.first());
                args = args.rest();
            }
            return Invoke<T>(func, newArgs.ToArray());
        }

        static List<Func<object, object[], object>> cache = new List<Func<object, object[], object>>();
        public static T Invoke<T>(object func, params object[] args)
        {
            var c = args.Length;
            Func<object, object[], object> functor;
            if (cache.Count <= c || (functor = cache[c]) == null)
            {
                while (cache.Count <= c)
                    cache.Add(null);
                functor = cache[c] = Build(c);
            }
            return (T)functor(func, args);
        }

        private static Func<object, object[], object> Build(int argCount)
        {
            var ps = new ParameterExpression[2];
            ps[0] = Expression.Parameter(typeof(object));
            ps[1] = Expression.Parameter(typeof(object[]));

            var args = new List<Expression>();
            args.Add(ps[0]);
            for (int i = 0; i < argCount; i++)
                args.Add(Expression.ArrayIndex(ps[1], Expression.Constant(i)));

            var lambda = Expression.Lambda<Func<object, object[], object>>(
                Expression.Dynamic(BinderFactory.CachedInvoke(argCount), typeof(object), args),
                ps);

            return lambda.Compile();
        }

        public static object ThrowArity(object o)
        {
            throw new ArgumentException("Wrong number of args passed to: " + o.GetType().Name);
        }
    }
}
Back to Top