<commit_before>using System;
using System.Linq;
using System.Reflection;

namespace jQueryTmpl.Templates
{
    public class ExpressionEvaluator
    {
        private readonly TemplateItem _item;

        public ExpressionEvaluator(TemplateItem item)
        {
            _item = item;
        }

        public EvaluatedExpression Evaluate(Expression expression)
        {
            var value = EvaluateValue(expression);
            return new EvaluatedExpression(_item, value);
        }

        private object EvaluateValue(Expression expression)
        {
            var value = _item.Data;
            while(expression != null && value != null)
            {
                if(expression.Dollar)
                    value = _item;

                var memberInfo = FindMember(expression.Member, value);

                if(memberInfo.Length == 0 && value is TemplateItem)
                    memberInfo = FindMember(expression.Member,  value = ((TemplateItem)value).Options);

                if(memberInfo.Length == 0)
                    return EvaluateLiteral(expression);

                value = InvokeBestMatch(memberInfo, expression, value);
                expression = expression.Next;
            }

            return value;
        }

        private object EvaluateLiteral(Expression expression)
        {
            if(expression.Arguments.Length == 0 && expression.Indices.Length == 0 && expression.Next == null && expression.Dollar == false)
            {
                long number;
                if(Int64.TryParse(expression.Member, out number))
                    return number;

                if((expression.Member.StartsWith("\"") && expression.Member.EndsWith("\"")) || 
                   (expression.Member.StartsWith("'") && expression.Member.EndsWith("'")))
                    return expression.Member.Trim('"', '\'');
                
                if(_item.ValueParameter != null && _item.ValueParameter.Matches(expression.Member))
                    return _item.Value;

                if(_item.IndexParameter != null && _item.IndexParameter.Matches(expression.Member))
                    return _item.Index;
            }

            return null;
        }

        private object InvokeBestMatch(MemberInfo[] candidates, Expression expression, object target)
        {
            if(expression.Member == null)
                return null;

            foreach(var memberInfo in candidates)
            {
                var propertyInfo = memberInfo as PropertyInfo;
                if(propertyInfo != null)
                {
                    var value = propertyInfo.GetValue(target, null);

                    if(expression.Arguments.Length > 0 && value is Delegate)
                    {
                        var func = (Delegate)value;
                        var paramValues = expression.Arguments.Select(EvaluateValue).ToArray();
                        return func.DynamicInvoke(paramValues);
                    }

                    if(expression.Indices.Length > 0)
                    {
                        if(value is Array)
                        {
                            var subIndices = expression.Indices.Select(EvaluateValue).Cast<long>().ToArray();
                            value = ((Array)value).GetValue(subIndices);
                        }

                        else if(value != null)
                        {
                            var indexer = value.GetType().GetProperty("Item") ?? value.GetType().GetProperty("Chars");
                            if(indexer != null)
                            {
                                var subIndices = expression.Indices.Select(EvaluateValue).ToArray();
                                value = indexer.GetValue(value, subIndices);
                            }
                        }
                    }
<commit_msg>Assume Int32 rather than Int64 for numbers<commit_after>using System;
using System.Linq;
using System.Reflection;

namespace jQueryTmpl.Templates
{
    public class ExpressionEvaluator
    {
        private readonly TemplateItem _item;

        public ExpressionEvaluator(TemplateItem item)
        {
            _item = item;
        }

        public EvaluatedExpression Evaluate(Expression expression)
        {
            var value = EvaluateValue(expression);
            return new EvaluatedExpression(_item, value);
        }

        private object EvaluateValue(Expression expression)
        {
            var value = _item.Data;
            while(expression != null && value != null)
            {
                if(expression.Dollar)
                    value = _item;

                var memberInfo = FindMember(expression.Member, value);

                if(memberInfo.Length == 0 && value is TemplateItem)
                    memberInfo = FindMember(expression.Member,  value = ((TemplateItem)value).Options);

                if(memberInfo.Length == 0)
                    return EvaluateLiteral(expression);

                value = InvokeBestMatch(memberInfo, expression, value);
                expression = expression.Next;
            }

            return value;
        }

        private object EvaluateLiteral(Expression expression)
        {
            if(expression.Arguments.Length == 0 && expression.Indices.Length == 0 && expression.Next == null && expression.Dollar == false)
            {
                int number;
                if(Int32.TryParse(expression.Member, out number))
                    return number;

                if((expression.Member.StartsWith("\"") && expression.Member.EndsWith("\"")) || 
                   (expression.Member.StartsWith("'") && expression.Member.EndsWith("'")))
                    return expression.Member.Trim('"', '\'');
                
                if(_item.ValueParameter != null && _item.ValueParameter.Matches(expression.Member))
                    return _item.Value;

                if(_item.IndexParameter != null && _item.IndexParameter.Matches(expression.Member))
                    return _item.Index;
            }

            return null;
        }

        private object InvokeBestMatch(MemberInfo[] candidates, Expression expression, object target)
        {
            if(expression.Member == null)
                return null;

            foreach(var memberInfo in candidates)
            {
                var propertyInfo = memberInfo as PropertyInfo;
                if(propertyInfo != null)
                {
                    var value = propertyInfo.GetValue(target, null);

                    if(expression.Arguments.Length > 0 && value is Delegate)
                    {
                        var func = (Delegate)value;
                        var paramValues = expression.Arguments.Select(EvaluateValue).ToArray();
                        return func.DynamicInvoke(paramValues);
                    }

                    if(expression.Indices.Length > 0)
                    {
                        if(value is Array)
                        {
                            var subIndices = expression.Indices.Select(EvaluateValue).Cast<int>().ToArray();
                            value = ((Array)value).GetValue(subIndices);
                        }

                        else if(value != null)
                        {
                            var indexer = value.GetType().GetProperty("Item") ?? value.GetType().GetProperty("Chars");
                            if(indexer != null)
                            {
                                var subIndices = expression.Indices.Select(EvaluateValue).ToArray();
                                value = indexer.GetValue(value, subIndices);
                            }
                        }
                    }

{'fraction_non_alphanumeric': 0.09040708873763965, 'fraction_numerical': 0.0025683832027738537, 'mean_word_length': 1.3650167020953539, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5385079', 'n_tokens_mistral': 1798, 'n_tokens_neox': 1672, 'n_words': 350}