<commit_before>﻿using QRest.Compiler.Standard.Assembler;
using QRest.Core.Contracts;
using QRest.Core.Terms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace QRest.Compiler.Standard
{
    public partial class StandardCompiler : ICompiler
    {
        public bool UseCompilerCache { get; set; } = true;
        private static readonly ConstantsCollector _constantsCollector = new ConstantsCollector();
        private static readonly Dictionary<string, ConstantExpression> _cache = new Dictionary<string, ConstantExpression>();

        public Func<TRoot, object> Compile<TRoot>(LambdaTerm sequence)
        {
            var exp = Assemble<TRoot>(sequence);
            var compiled = exp.Compile();
            return (TRoot root) => compiled(root);
        }

        public Expression<Func<TRoot, object>> Assemble<TRoot>(LambdaTerm lambdaterm)
        {
            ConstantExpression compiled = null;
            IReadOnlyList<ConstantExpression> constants = null;

            var root = Expression.Parameter(typeof(TRoot), "r");

            if (UseCompilerCache && _cache.TryGetValue(lambdaterm.KeyView, out var @delegate))
            {
                compiled = @delegate;
                constants = _constantsCollector.Collect(lambdaterm);
            }
            else
            {
                var ctx = new StandardAssembler(this);
                var (lambda, consts) = ctx.Assemble(lambdaterm, root, typeof(object));

                constants = consts;
                compiled = Expression.Constant(lambda.Compile());

                if (UseCompilerCache)
                    _cache[lambdaterm.KeyView] = compiled;
            }

            var resultInvokeParams = new Expression[] { root }.Concat(constants).ToArray();

            var topLambda = Expression.Lambda<Func<TRoot, object>>(Expression.Invoke(compiled, resultInvokeParams), root);

            return topLambda;
        }
    }
}<commit_msg>improved cache robust<commit_after>﻿using QRest.Compiler.Standard.Assembler;
using QRest.Core.Contracts;
using QRest.Core.Terms;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace QRest.Compiler.Standard
{
    public partial class StandardCompiler : ICompiler
    {
        public bool UseCompilerCache { get; set; } = true;
        private static readonly ConstantsCollector _constantsCollector = new ConstantsCollector();
        private static readonly ConcurrentDictionary<string, ConstantExpression> _cache = new ConcurrentDictionary<string, ConstantExpression>();

        public Func<TRoot, object> Compile<TRoot>(LambdaTerm sequence)
        {
            var exp = Assemble<TRoot>(sequence);
            var compiled = exp.Compile();
            return (TRoot root) => compiled(root);
        }

        public Expression<Func<TRoot, object>> Assemble<TRoot>(LambdaTerm lambdaterm)
        {
            ConstantExpression compiled = null;
            IReadOnlyList<ConstantExpression> constants = null;

            var rootType = typeof(TRoot);

            var root = Expression.Parameter(rootType, "r");
            var cacheKey = $"{rootType.ToString()}++{lambdaterm.KeyView}";

            if (UseCompilerCache && _cache.TryGetValue(cacheKey, out var @delegate))
            {
                compiled = @delegate;
                constants = _constantsCollector.Collect(lambdaterm);
            }
            else
            {
                var ctx = new StandardAssembler(this);
                var (lambda, consts) = ctx.Assemble(lambdaterm, root, typeof(object));

                constants = consts;
                compiled = Expression.Constant(lambda.Compile());

                if (UseCompilerCache)
                    _cache[cacheKey] = compiled;
            }

            var resultInvokeParams = new Expression[] { root }.Concat(constants).ToArray();

            var topLambda = Expression.Lambda<Func<TRoot, object>>(Expression.Invoke(compiled, resultInvokeParams), root);

            return topLambda;
        }
    }
}
{'fraction_non_alphanumeric': 0.0945945945945946, 'fraction_numerical': 0.0, 'mean_word_length': 2.4369817578772803, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '246475', 'n_tokens_mistral': 1069, 'n_tokens_neox': 1040, 'n_words': 242}