<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using LinqExpressions = System.Linq.Expressions;
using LinqExpression = System.Linq.Expressions.Expression;

namespace SyMath
{
    /// <summary>
    /// Exception class for compiler errors.
    /// </summary>
    public class CompileException : Exception
    {
        public CompileException(string Message, Exception Inner) : base(Message, Inner) { }
    }

    /// <summary>
    /// Visitor to translate Expression to System.Linq.Expressions.Expression.
    /// </summary>
    class CompileVisitor : ExpressionVisitor<LinqExpression>
    {
        protected Dictionary<Expression, LinqExpression> compiled = new Dictionary<Expression,LinqExpression>();
        protected List<Type> libraries;

        public CompileVisitor(IDictionary<Expression, LinqExpression> Map, IEnumerable<Type> Libraries)
        {
            if (Map != null)
                foreach (KeyValuePair<Expression, LinqExpression> i in Map)
                    compiled[i.Key] = i.Value;

            if (Libraries != null)
                libraries = Libraries.ToList();
            else
                libraries = new List<Type>();
        }

        public override LinqExpression Visit(Expression E)
        {
            // If this expression has already been compiled, re-use it.
            LinqExpression e = null;
            if (compiled.TryGetValue(E, out e))
                return e;

            // Compile and store the expression.
            e = base.Visit(E);
            compiled[E] = e;
            return e;
        }

        protected override LinqExpression VisitConstant(Constant C) 
        { 
            return LinqExpression.Constant((double)C); 
        }

        protected override LinqExpression VisitAdd(Add A)
        {
            LinqExpression add = Visit(A.Terms.First());
            foreach (Expression i in A.Terms.Skip(1))
            {
                if (IsNegative(i))
                    add = LinqExpression.Subtract(add, Visit(-i));
                else
                    add = LinqExpression.Add(add, Visit(i));
            }
            return add;
        }

        protected override LinqExpression VisitMultiply(Multiply M)
        {
            LinqExpression multiply = Visit(M.Terms.First());
            foreach (Expression i in M.Terms.Skip(1))
                multiply = LinqExpression.Multiply(multiply, Visit(i));
            return multiply;
        }

        protected override LinqExpression VisitUnary(Unary U)
        {
            LinqExpression o = Visit(U.Operand);
            switch (U.Operator)
            {
                case Operator.Negate: return LinqExpression.Negate(o);
                case Operator.Inverse: return LinqExpression.Divide(LinqExpression.Constant(1.0), o);
                case Operator.Not: return LinqExpression.Not(o);

                default: throw new NotImplementedException("Unsupported unary operator");
            }
        }

        protected override LinqExpression VisitBinary(Binary B)
        {
            LinqExpression l = Visit(B.Left);
            LinqExpression r = Visit(B.Right);
            switch (B.Operator)
            {
                case Operator.Add: return LinqExpression.Add(l, r);
                case Operator.Subtract: return LinqExpression.Subtract(l, r);
                case Operator.Multiply: return LinqExpression.Multiply(l, r);
                case Operator.Divide: return LinqExpression.Divide(l, r);
                case Operator.Power: return LinqExpression.Power(l, r);

                case Operator.And: return LinqExpression.And(l, r);
                case Operator.Or: return LinqExpression.Or(l, r);

                case Operator.Equal: return LinqExpression.Equal(l, r);
                case Operator.NotEqual: return LinqExpression.NotEqual(l, r);
                case Operator.Greater: return LinqExpression.GreaterThan(l, r);
                case Operator.GreaterEqual: return LinqExpression.GreaterThanOrEqual(l, r);
                case Operator.Less: return LinqExpression.LessThan(l, r);
                case Operator.LessEqual: return LinqExpression.LessThanOrEqual(l, r);

                default: throw new NotImplementedException("Unsupported binary operator.");
            }
        }

        protected override LinqExpression VisitPower(Power P)
        {
            LinqExpression l = Visit(P.Left);
            if (P.Right.Equals(Constant.New(2)))
                return LinqExpression.Multiply(l, l);

            LinqExpression r = Visit(P.Right);
            return LinqExpression.Power(l, r);
        }

        protected override LinqExpression VisitCall(Call F)
        {
            if (F.Target.CanCall(F.Arguments))
                return F.Target.CompileCall(F.Arguments.Select(i => Visit(i)), libraries);
            else
                throw new InvalidOperationException("Call to '" + F.Target.ToString() + "' cannot be resolved.");
        }

        protected override LinqExpression VisitVariable(Variable V)
        {
            throw new InvalidOperationException("Unmapped variable in compiled expression.");
        }

        protected override LinqExpression VisitUnknown(Expression E)
        {
            throw new NotImplementedException("Unsupported expression type.");
        }

        private static bool IsNegative(Expression x)
        {
            Constant C = Multiply.TermsOf(x).FirstOrDefault(i => i is Constant) as Constant;
            if (C != null)
                return C.Value < 0;
            return false;
        }
    }
    
    public static class CompileExtension
    {
        /// <summary>
        /// Compile an expression to a LinqExpression.
        /// </summary>
        /// <param name="This"></param>
        /// <param name="Map"></param>
        /// <returns></returns>
        public static LinqExpression Compile(this Expression This, IDictionary<Expression, LinqExpression> Map, IEnumerable<Type> Libraries)
        {
            if (Libraries == null)
                Libraries = new Type[] { typeof(StandardMath) };

            try
            {
                return new CompileVisitor(Map, Libraries).Visit(This);
            }
            catch (System.Exception Ex)
            {
                throw new CompileException("Exception compiling expression", Ex);
            }
        }

        public static LinqExpression Compile(this Expression This, IDictionary<Expression, LinqExpression> Map)
        {
            return Compile(This, Map, null);
        }
    }

    /// <summary><commit_msg>Removed stupid exception type change<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using LinqExpressions = System.Linq.Expressions;
using LinqExpression = System.Linq.Expressions.Expression;

namespace SyMath
{
    /// <summary>
    /// Exception class for compiler errors.
    /// </summary>
    public class CompileException : Exception
    {
        public CompileException(string Message, Exception Inner) : base(Message, Inner) { }
    }

    /// <summary>
    /// Visitor to translate Expression to System.Linq.Expressions.Expression.
    /// </summary>
    class CompileVisitor : ExpressionVisitor<LinqExpression>
    {
        protected Dictionary<Expression, LinqExpression> compiled = new Dictionary<Expression,LinqExpression>();
        protected List<Type> libraries;

        public CompileVisitor(IDictionary<Expression, LinqExpression> Map, IEnumerable<Type> Libraries)
        {
            if (Map != null)
                foreach (KeyValuePair<Expression, LinqExpression> i in Map)
                    compiled[i.Key] = i.Value;

            if (Libraries != null)
                libraries = Libraries.ToList();
            else
                libraries = new List<Type>();
        }

        public override LinqExpression Visit(Expression E)
        {
            // If this expression has already been compiled, re-use it.
            LinqExpression e = null;
            if (compiled.TryGetValue(E, out e))
                return e;

            // Compile and store the expression.
            e = base.Visit(E);
            compiled[E] = e;
            return e;
        }

        protected override LinqExpression VisitConstant(Constant C) 
        { 
            return LinqExpression.Constant((double)C); 
        }

        protected override LinqExpression VisitAdd(Add A)
        {
            LinqExpression add = Visit(A.Terms.First());
            foreach (Expression i in A.Terms.Skip(1))
            {
                if (IsNegative(i))
                    add = LinqExpression.Subtract(add, Visit(-i));
                else
                    add = LinqExpression.Add(add, Visit(i));
            }
            return add;
        }

        protected override LinqExpression VisitMultiply(Multiply M)
        {
            LinqExpression multiply = Visit(M.Terms.First());
            foreach (Expression i in M.Terms.Skip(1))
                multiply = LinqExpression.Multiply(multiply, Visit(i));
            return multiply;
        }

        protected override LinqExpression VisitUnary(Unary U)
        {
            LinqExpression o = Visit(U.Operand);
            switch (U.Operator)
            {
                case Operator.Negate: return LinqExpression.Negate(o);
                case Operator.Inverse: return LinqExpression.Divide(LinqExpression.Constant(1.0), o);
                case Operator.Not: return LinqExpression.Not(o);

                default: throw new NotImplementedException("Unsupported unary operator");
            }
        }

        protected override LinqExpression VisitBinary(Binary B)
        {
            LinqExpression l = Visit(B.Left);
            LinqExpression r = Visit(B.Right);
            switch (B.Operator)
            {
                case Operator.Add: return LinqExpression.Add(l, r);
                case Operator.Subtract: return LinqExpression.Subtract(l, r);
                case Operator.Multiply: return LinqExpression.Multiply(l, r);
                case Operator.Divide: return LinqExpression.Divide(l, r);
                case Operator.Power: return LinqExpression.Power(l, r);

                case Operator.And: return LinqExpression.And(l, r);
                case Operator.Or: return LinqExpression.Or(l, r);

                case Operator.Equal: return LinqExpression.Equal(l, r);
                case Operator.NotEqual: return LinqExpression.NotEqual(l, r);
                case Operator.Greater: return LinqExpression.GreaterThan(l, r);
                case Operator.GreaterEqual: return LinqExpression.GreaterThanOrEqual(l, r);
                case Operator.Less: return LinqExpression.LessThan(l, r);
                case Operator.LessEqual: return LinqExpression.LessThanOrEqual(l, r);

                default: throw new NotImplementedException("Unsupported binary operator.");
            }
        }

        protected override LinqExpression VisitPower(Power P)
        {
            LinqExpression l = Visit(P.Left);
            if (P.Right.Equals(Constant.New(2)))
                return LinqExpression.Multiply(l, l);

            LinqExpression r = Visit(P.Right);
            return LinqExpression.Power(l, r);
        }

        protected override LinqExpression VisitCall(Call F)
        {
            if (F.Target.CanCall(F.Arguments))
                return F.Target.CompileCall(F.Arguments.Select(i => Visit(i)), libraries);
            else
                throw new InvalidOperationException("Call to '" + F.Target.ToString() + "' cannot be resolved.");
        }

        protected override LinqExpression VisitVariable(Variable V)
        {
            throw new InvalidOperationException("Unmapped variable in compiled expression.");
        }

        protected override LinqExpression VisitUnknown(Expression E)
        {
            throw new NotImplementedException("Unsupported expression type.");
        }

        private static bool IsNegative(Expression x)
        {
            Constant C = Multiply.TermsOf(x).FirstOrDefault(i => i is Constant) as Constant;
            if (C != null)
                return C.Value < 0;
            return false;
        }
    }
    
    public static class CompileExtension
    {
        /// <summary>
        /// Compile an expression to a LinqExpression.
        /// </summary>
        /// <param name="This"></param>
        /// <param name="Map"></param>
        /// <returns></returns>
        public static LinqExpression Compile(this Expression This, IDictionary<Expression, LinqExpression> Map, IEnumerable<Type> Libraries)
        {
            if (Libraries == null)
                Libraries = new Type[] { typeof(StandardMath) };

            return new CompileVisitor(Map, Libraries).Visit(This);
        }

        public static LinqExpression Compile(this Expression This, IDictionary<Expression, LinqExpression> Map)
        {
            return Compile(This, Map, null);
        }
    }

    /// <summary>
{'fraction_non_alphanumeric': 0.0935676945223123, 'fraction_numerical': 0.0009091597848321843, 'mean_word_length': 1.9151943462897527, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 55, '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': '4597809', 'n_tokens_mistral': 3428, 'n_tokens_neox': 3248, 'n_words': 845}