<commit_before>﻿using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Ogam {
    public class OgamSerializer {
        private static readonly Dictionary<Type, Func<object, Pair>> Serializers =
            new Dictionary<Type, Func<object, Pair>>();

        private static readonly Dictionary<Type, Func<Pair, object>> Deserializers =
            new Dictionary<Type, Func<Pair, object>>();

        private static readonly List<string> RequiredNamespaces = new List<string>();

        static OgamSerializer() {
            RequiredNamespaces.Add("System");
            RequiredNamespaces.Add("System.Collections.Generic");
            RequiredNamespaces.Add("System.Collections");
            RequiredNamespaces.Add("System.Linq");
            RequiredNamespaces.Add("Ogam");
        }

        public static Pair Serialize(object data, Type t) {
            if (data == null)
                return new Pair();

            if (IsBaseType(t))
                throw new ArgumentException(
                    "This method should not be used with base types (Primitive, Decimal, String, DateTime)");

            if (!Serializers.ContainsKey(t)) {
                var res = GetCompiledResult(t, true);
                Serializers.Add(t, res.GetResult() as Func<object, Pair>);
            }
            return Serializers[t](data);
        }

        public static string Serialize(object data) {
            if (data == null)
                return "#nil";

            var t = data.GetType();

            if (IsBaseType(t)) {
                return Pair.O2String(data);
            }

            return "'" + Serialize(data, t);
        }

        public static object Deserialize(Pair data, Type t) {
            if (data == null)
                return null;

            if (IsBaseType(t))
                throw new ArgumentException(
                    "This method should not be used with base types (Primitive, Decimal, String, DateTime)");

            if (!Deserializers.ContainsKey(t)) {
                var res = GetCompiledResult(t, false);
                Deserializers.Add(t, res.GetResult() as Func<Pair, object>);
            }
            return Deserializers[t](data);
        }

        private static IResult GetCompiledResult(Type target, bool forward) {
            var provider = CodeDomProvider.CreateProvider("CSharp");
            var DOMref =
                AppDomain.CurrentDomain.GetAssemblies()
                    .Where(obj => !obj.IsDynamic)
                    .Select(obj => obj.Location)
                    .ToList();

            var currentAssembly = Assembly.GetExecutingAssembly();
            DOMref.Add(currentAssembly.Location);

            var cp = new CompilerParameters(DOMref.ToArray());
            cp.GenerateInMemory = true;

            var className = "SerializerFactory";
            var outputType = (forward ? "Func<object, Pair>" : "Func<Pair, object>");
            var arg = "data";

            var srcBuilder = new StringBuilder();

            // REQUIRED ANYWAY
            foreach (var nmsp in RequiredNamespaces) {
                srcBuilder.AppendLine($"using {nmsp};");
            }

            // ADDITIONAL FOR CONCRETE TYPE
            foreach (var nmsp in GetTypeNamespaces(target).Where(t => !RequiredNamespaces.Contains(t))) {
                srcBuilder.AppendLine($"using {nmsp};");
            }

            srcBuilder.AppendLine("namespace Ogam {");
            srcBuilder.AppendLine($"public partial class {className} : IResult {{");

            #region IResult.GetResult

            srcBuilder.AppendLine("public Delegate GetResult() {");
            srcBuilder.AppendLine($"return new {outputType}(({arg})=>{{");
            srcBuilder.AppendLine(GenerateTypeDef(target, forward, arg));
            srcBuilder.AppendLine("});");
            srcBuilder.AppendLine("}");

            #endregion

            srcBuilder.AppendLine("} // cls");
            srcBuilder.AppendLine("} // ns");

            // COMPILATION
            var src = srcBuilder.ToString();
            var cr = provider.CompileAssemblyFromSource(cp, src);

            if (cr.Errors.Count > 0) {
                var e = new Exception("Error in OgamSerializer dynamic compile module. See details in data property...");
                foreach (CompilerError ce in cr.Errors) {
                    e.Data[ce.ErrorNumber] = $"{target.Assembly}|{target.Name}  {ce.ToString()}";
                }
                throw e;
            } else {
                var type = cr.CompiledAssembly.GetType("Ogam." + className);
                var obj = (IResult)Activator.CreateInstance(type);
                return obj;
            }
            return null;
        }

        private static ICollection<string> GetTypeNamespaces(Type t) {
            var res = new List<string> { t.Namespace };

            if (t.IsGenericType) {
                Array.ForEach<Type>(t.GetGenericArguments(), tt => res.AddRange(GetTypeNamespaces(tt)));
            }

            foreach (var mb in t.GetMembers(BindingFlags.Instance | BindingFlags.Public)) {
                if (mb is FieldInfo) {
                    var f = (FieldInfo)mb;
                    res.AddRange(GetTypeNamespaces(f.FieldType));
                } else if (mb is PropertyInfo) {
                    var p = (PropertyInfo)mb;
                    res.AddRange(GetTypeNamespaces(p.PropertyType));
                }
            }<commit_msg>Fix overflow logic<commit_after>﻿using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Ogam {
    public class OgamSerializer {
        private static readonly Dictionary<Type, Func<object, Pair>> Serializers =
            new Dictionary<Type, Func<object, Pair>>();

        private static readonly Dictionary<Type, Func<Pair, object>> Deserializers =
            new Dictionary<Type, Func<Pair, object>>();

        private static readonly List<string> RequiredNamespaces = new List<string>();

        static OgamSerializer() {
            RequiredNamespaces.Add("System");
            RequiredNamespaces.Add("System.Collections.Generic");
            RequiredNamespaces.Add("System.Collections");
            RequiredNamespaces.Add("System.Linq");
            RequiredNamespaces.Add("Ogam");
        }

        public static Pair Serialize(object data, Type t) {
            if (data == null)
                return new Pair();

            if (IsBaseType(t))
                throw new ArgumentException(
                    "This method should not be used with base types (Primitive, Decimal, String, DateTime)");

            if (!Serializers.ContainsKey(t)) {
                var res = GetCompiledResult(t, true);
                Serializers.Add(t, res.GetResult() as Func<object, Pair>);
            }
            return Serializers[t](data);
        }

        public static string Serialize(object data) {
            if (data == null)
                return "#nil";

            var t = data.GetType();

            if (IsBaseType(t)) {
                return Pair.O2String(data);
            }

            return "'" + Serialize(data, t);
        }

        public static object Deserialize(Pair data, Type t) {
            if (data == null)
                return null;

            if (IsBaseType(t))
                throw new ArgumentException(
                    "This method should not be used with base types (Primitive, Decimal, String, DateTime)");

            if (!Deserializers.ContainsKey(t)) {
                var res = GetCompiledResult(t, false);
                Deserializers.Add(t, res.GetResult() as Func<Pair, object>);
            }
            return Deserializers[t](data);
        }

        private static IResult GetCompiledResult(Type target, bool forward) {
            var provider = CodeDomProvider.CreateProvider("CSharp");
            var DOMref =
                AppDomain.CurrentDomain.GetAssemblies()
                    .Where(obj => !obj.IsDynamic)
                    .Select(obj => obj.Location)
                    .ToList();

            var currentAssembly = Assembly.GetExecutingAssembly();
            DOMref.Add(currentAssembly.Location);

            var cp = new CompilerParameters(DOMref.ToArray());
            cp.GenerateInMemory = true;

            var className = "SerializerFactory";
            var outputType = (forward ? "Func<object, Pair>" : "Func<Pair, object>");
            var arg = "data";

            var srcBuilder = new StringBuilder();

            // REQUIRED ANYWAY
            foreach (var nmsp in RequiredNamespaces) {
                srcBuilder.AppendLine($"using {nmsp};");
            }

            // ADDITIONAL FOR CONCRETE TYPE
            foreach (var nmsp in GetTypeNamespaces(target).Where(t => !RequiredNamespaces.Contains(t))) {
                srcBuilder.AppendLine($"using {nmsp};");
            }

            srcBuilder.AppendLine("namespace Ogam {");
            srcBuilder.AppendLine($"public partial class {className} : IResult {{");

            #region IResult.GetResult

            srcBuilder.AppendLine("public Delegate GetResult() {");
            srcBuilder.AppendLine($"return new {outputType}(({arg})=>{{");
            srcBuilder.AppendLine(GenerateTypeDef(target, forward, arg));
            srcBuilder.AppendLine("});");
            srcBuilder.AppendLine("}");

            #endregion

            srcBuilder.AppendLine("} // cls");
            srcBuilder.AppendLine("} // ns");

            // COMPILATION
            var src = srcBuilder.ToString();
            var cr = provider.CompileAssemblyFromSource(cp, src);

            if (cr.Errors.Count > 0) {
                var e = new Exception("Error in OgamSerializer dynamic compile module. See details in data property...");
                foreach (CompilerError ce in cr.Errors) {
                    e.Data[ce.ErrorNumber] = $"{target.Assembly}|{target.Name}  {ce.ToString()}";
                }
                throw e;
            } else {
                var type = cr.CompiledAssembly.GetType("Ogam." + className);
                var obj = (IResult)Activator.CreateInstance(type);
                return obj;
            }
            return null;
        }

        private static ICollection<string> GetTypeNamespaces(Type t) {
            var res = new List<string> { t.Namespace };

            if (t.IsGenericType) {
                Array.ForEach<Type>(t.GetGenericArguments(), tt => res.AddRange(GetTypeNamespaces(tt)));
            }

            foreach (var mb in t.GetMembers(BindingFlags.Instance | BindingFlags.Public)) {
                if (mb is FieldInfo) {
                    var f = (FieldInfo)mb;
                    if (IsBaseType(f.FieldType))
                        continue;
                    res.AddRange(GetTypeNamespaces(f.FieldType));
                } else if (mb is PropertyInfo) {
                    var p = (PropertyInfo)mb;
                    if (IsBaseType(p.PropertyType))
                        continue;
                    res.AddRange(GetTypeNamespaces(p.PropertyType));
                }
            }
{'fraction_non_alphanumeric': 0.1085584005612066, 'fraction_numerical': 0.00035075412136092597, 'mean_word_length': 1.8056580565805658, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 49, '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': '6162849', 'n_tokens_mistral': 2945, 'n_tokens_neox': 2805, 'n_words': 688}