<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jil.Common;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;

namespace Jil.DeserializeDynamic
{
    sealed partial class JsonObject : IDynamicMetaObjectProvider
    {
        public DynamicMetaObject GetMetaObject(Expression exp)
        {
            return new JsonMetaObject(this, exp);
        }

        sealed class JsonMetaObject : DynamicMetaObject
        {
            public JsonObject Outer { get { return (JsonObject)Value; } }

            public JsonMetaObject(JsonObject outer, Expression exp) : base(exp, BindingRestrictions.Empty, outer) { }

            static ConstructorInfo InvalidCastExceptionCons = typeof(InvalidCastException).GetConstructor(new[] { typeof(string) });
            static MethodInfo StringConcat = typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object), typeof(object) });
            static MethodInfo StringConcatArray = typeof(string).GetMethod("Concat", new[] { typeof(object[]) });
            static MethodInfo StringJoin = typeof(string).GetMethod("Join", new[] { typeof(string), typeof(object[]) });

            static ParameterExpression ThisEvaled = Expression.Variable(typeof(JsonObject));
            static ParameterExpression Res = Expression.Variable(typeof(object));
            static ParameterExpression ArgRef = Expression.Variable(typeof(object));
            static ConstantExpression UnableToConvertDynamic = Expression.Constant("Unable to convert dynamic [");
            static ConstantExpression CommaSpace = Expression.Constant(", ");
            static ConstantExpression CloseSquareBracket = Expression.Constant("]");
            static ParameterExpression IndexesRef = Expression.Variable(typeof(object[]));
            static ConstantExpression UnableToGetDynamicIndex = Expression.Constant("Unable to get dynamic index (");
            static ConstantExpression CloseBraceOpenSquareBracket = Expression.Constant(") on [");

            public override DynamicMetaObject BindConvert(ConvertBinder binder)
            {
                /*
                 * Effectively, this returns an expression of the following code:
                 * {
                 *      JsonObject thisEvaled = (JsonObject)<Expression>;
                 *      ReturnType finalResult;
                 *      object res;
                 *      if(!Value.InnerTryConvert(ReturnType, out res))
                 *      {
                 *          throw new InvalidCastException("Unable to convert dynamic ["+thisEvaled+"] to "+ReturnType.FullName");
                 *      }
                 *      finalResult = (ReturnType)res;
                 * }
                 * 
                 * Unlike C#, block expression in LINQ do produce a value when evaluated.  It's the last expression executed.
                 */

                var thisRef = Expression.Type != typeof(JsonObject) ? Expression.Convert(Expression, typeof(JsonObject)) : Expression;
                var thisEvaled = ThisEvaled;
                var thisAssigned = Expression.Assign(thisEvaled, thisRef);
                var finalResult = Expression.Variable(binder.ReturnType);
                var res = Res;
                var tryConvertCall = Expression.Call(thisEvaled, InnerTryConvertMtd, Expression.Constant(binder.ReturnType), res);
                var throwExc =
                    Expression.Throw(
                        Expression.New(
                            InvalidCastExceptionCons,
                            Expression.Call(
                                StringConcat,
                                UnableToConvertDynamic,
                                // TODO: Figure out how to make this work... write now it's infinite recursion
                                //thisEvaled,
                                Expression.Constant("--foo--"),
                                Expression.Constant("] to [" + binder.ReturnType.FullName + "]")
                            )
                        )
                    );

                var notIf = 
                    Expression.IfThen(
                        Expression.Not(tryConvertCall),
                        throwExc
                    );<commit_msg>todone<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jil.Common;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;

namespace Jil.DeserializeDynamic
{
    sealed partial class JsonObject : IDynamicMetaObjectProvider
    {
        public DynamicMetaObject GetMetaObject(Expression exp)
        {
            return new JsonMetaObject(this, exp);
        }

        sealed class JsonMetaObject : DynamicMetaObject
        {
            public JsonObject Outer { get { return (JsonObject)Value; } }

            public JsonMetaObject(JsonObject outer, Expression exp) : base(exp, BindingRestrictions.Empty, outer) { }

            static ConstructorInfo InvalidCastExceptionCons = typeof(InvalidCastException).GetConstructor(new[] { typeof(string) });
            static MethodInfo StringConcat = typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object), typeof(object) });
            static MethodInfo StringConcatArray = typeof(string).GetMethod("Concat", new[] { typeof(object[]) });
            static MethodInfo StringJoin = typeof(string).GetMethod("Join", new[] { typeof(string), typeof(object[]) });

            static ParameterExpression ThisEvaled = Expression.Variable(typeof(JsonObject));
            static ParameterExpression Res = Expression.Variable(typeof(object));
            static ParameterExpression ArgRef = Expression.Variable(typeof(object));
            static ConstantExpression UnableToConvertDynamic = Expression.Constant("Unable to convert dynamic [");
            static ConstantExpression CommaSpace = Expression.Constant(", ");
            static ConstantExpression CloseSquareBracket = Expression.Constant("]");
            static ParameterExpression IndexesRef = Expression.Variable(typeof(object[]));
            static ConstantExpression UnableToGetDynamicIndex = Expression.Constant("Unable to get dynamic index (");
            static ConstantExpression CloseBraceOpenSquareBracket = Expression.Constant(") on [");

            public override DynamicMetaObject BindConvert(ConvertBinder binder)
            {
                /*
                 * Effectively, this returns an expression of the following code:
                 * {
                 *      JsonObject thisEvaled = (JsonObject)<Expression>;
                 *      ReturnType finalResult;
                 *      object res;
                 *      if(!Value.InnerTryConvert(ReturnType, out res))
                 *      {
                 *          throw new InvalidCastException("Unable to convert dynamic ["+thisEvaled+"] to "+ReturnType.FullName");
                 *      }
                 *      finalResult = (ReturnType)res;
                 * }
                 * 
                 * Unlike C#, block expression in LINQ do produce a value when evaluated.  It's the last expression executed.
                 */

                var thisRef = Expression.Type != typeof(JsonObject) ? Expression.Convert(Expression, typeof(JsonObject)) : Expression;
                var thisEvaled = ThisEvaled;
                var thisAssigned = Expression.Assign(thisEvaled, thisRef);
                var finalResult = Expression.Variable(binder.ReturnType);
                var res = Res;
                var tryConvertCall = Expression.Call(thisEvaled, InnerTryConvertMtd, Expression.Constant(binder.ReturnType), res);
                var throwExc =
                    Expression.Throw(
                        Expression.New(
                            InvalidCastExceptionCons,
                            Expression.Call(
                                StringConcat,
                                UnableToConvertDynamic,
                                Expression.Constant(Outer.Type.ToString()),
                                Expression.Constant("] to [" + binder.ReturnType.FullName + "]")
                            )
                        )
                    );

                var notIf = 
                    Expression.IfThen(
                        Expression.Not(tryConvertCall),
                        throwExc
                    );
{'fraction_non_alphanumeric': 0.08407494145199063, 'fraction_numerical': 0.0, 'mean_word_length': 1.88644812436634, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2640346', 'n_tokens_mistral': 1902, 'n_tokens_neox': 1821, 'n_words': 446}