Skip to content
Snippets Groups Projects
SOMDocManager.cs 38.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System.Collections.Generic;
    
    using Newtonsoft.Json;
    
    using JsonSubTypes;
    
    using System.Linq.Expressions;
    using System;
    using System.Linq;
    
    using MoreLinq;
    using UnityEngine;
    
    using static Scroll;
    
    MaZiFAU's avatar
    MaZiFAU committed
    using UnityEngine.Purchasing;
    
            public static readonly string Point = "http://mathhub.info/MitM/core/geometry?3DGeometry?point";
            public static readonly string Tuple = "http://gl.mathhub.info/MMT/LFX/Sigma?Symbols?Tuple";
            public static readonly string LineType = "http://mathhub.info/MitM/core/geometry?Geometry/Common?line_type";
            public static readonly string LineOf = "http://mathhub.info/MitM/core/geometry?Geometry/Common?lineOf";
    
            public static readonly string OnLine = "http://mathhub.info/MitM/core/geometry?Geometry/Common?onLine";
            public static readonly string Ded = "http://mathhub.info/MitM/Foundation?Logic?ded";
            public static readonly string Eq = "http://mathhub.info/MitM/Foundation?Logic?eq";
            public static readonly string Metric = "http://mathhub.info/MitM/core/geometry?Geometry/Common?metric";
            public static readonly string Angle = "http://mathhub.info/MitM/core/geometry?Geometry/Common?angle_between";
            public static readonly string Sketch = "http://mathhub.info/MitM/Foundation?InformalProofs?proofsketch";
            public static readonly string RealLit = "http://mathhub.info/MitM/Foundation?RealLiterals?real_lit";
    
            public static readonly string ParallelLine = "http://mathhub.info/MitM/core/geometry?Geometry/Common?parallelLine";
            //public static readonly string RectangleFact = "http://mathhub.info/FrameIT/frameworld?FrameITRectangles?rectangleType";
            //public static readonly string RectangleFactmk = "http://mathhub.info/FrameIT/frameworld?FrameITRectangles?mkRectangle";
    
            public static readonly string CircleType3d = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?circleType3D";
            public static readonly string MkCircle3d = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?circle3D";
            public static readonly string TriangleMiddlePoint = "http://mathhub.info/FrameIT/frameworld?FrameITTriangles?triangleMidPointWrapper";
            public static readonly string RadiusCircleMetric = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?circleRadius";
    
            public static readonly string AreaCircle = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?areaCircle";
            public static readonly string VolumeCone = "http://mathhub.info/FrameIT/frameworld?FrameITCone?volumeCone";
            public static readonly string ConeOfCircleApex = "http://mathhub.info/FrameIT/frameworld?FrameITCone?circleConeOf";
    
            public static readonly string ParametrizedPlane = "http://mathhub.info/MitM/core/geometry?Planes?ParametrizedPlane";
            public static readonly string pointNormalPlane = "http://mathhub.info/MitM/core/geometry?Planes?pointNormalPlane";
            public static readonly string OnCircle = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?pointOnCircle";
            public static readonly string AnglePlaneLine = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?angleCircleLine";
            public static readonly string OrthoCircleLine = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?orthogonalCircleLine";
    
            public static readonly string TruncatedVolumeCone = "http://mathhub.info/FrameIT/frameworld?FrameITCone?truncatedConeVolume";
            public static readonly string CylinderVolume = "http://mathhub.info/FrameIT/frameworld?FrameITCylinder?cylinderVolume";
            public static readonly string EqualityCircles = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?equalityCircles";
            public static readonly string UnEqualityCircles = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?unequalityCircles";
    
            public static readonly string ParallelCircles = "http://mathhub.info/FrameIT/frameworld?FrameITCone?parallelCircles";
            public static readonly string RightAngle = "http://mathhub.info/FrameIT/frameworld?FrameITBasics?rightAngle";
    
            public static readonly string TestType = "http://mathhub.info/FrameIT/frameworld?FrameITCircle?xcircleType3D";
    
    MaZiFAU's avatar
    MaZiFAU committed
            public static readonly string ListType = "http://gl.mathhub.info/MMT/LFX/Datatypes?ListSymbols?ListType";
            public static readonly string ListLiteral = "http://gl.mathhub.info/MMT/LFX/Datatypes?ListSymbols?cons";
            public static readonly string ListEnd = "http://gl.mathhub.info/MMT/LFX/Datatypes?ListSymbols?nil_constant";
    
    
            public static readonly string Sin = "Sin";
            public static readonly string Cos = "Cos";
            public static readonly string Add = "Add";
            public static readonly string Divide = "Divide";
            public static readonly string Multiply = "Multiply";
            public static readonly string Subtract = "Subtract";
            public static readonly string SquareRoot = "SquareRoot";
    
    MaZiFAU's avatar
    MaZiFAU committed
            //public static readonly string MakeUnityEngineVector3 = "UnityEngine.Vector3";
    
    MaZiFAU's avatar
    MaZiFAU committed
            public static readonly string MakeObjectArray = "MakeObjectArray";
    
    
    
            public const string ScrollOppositeLen = "http://mathhub.info/FrameIT/frameworld?OppositeLen";
            public const string ScrollSupplementaryAngles = "http://mathhub.info/FrameIT/frameworld?SupplementaryAngles";
            public const string ScrollAngleSum = "http://mathhub.info/FrameIT/frameworld?AngleSum";
            public const string ScrollPythagoras = "http://mathhub.info/FrameIT/frameworld?Pythagoras";
            public const string ScrollCylinderVolumeScroll = "http://mathhub.info/FrameIT/frameworld?CylinderVolumeScroll";
            public const string ScrollCircleLineAngleToAngleScroll = "http://mathhub.info/FrameIT/frameworld?CircleLineAngleToAngleScroll";
            public const string ScrollMidpoint = "http://mathhub.info/FrameIT/frameworld?Midpoint";
            public const string ScrollCircleScroll = "http://mathhub.info/FrameIT/frameworld?CircleScroll";
            public const string ScrollCircleLineAngleScroll = "http://mathhub.info/FrameIT/frameworld?CircleLineAngleScroll";
            public const string ScrollCircleAreaScroll = "http://mathhub.info/FrameIT/frameworld?CircleAreaScroll";
            public const string ScrollConeVolumeScroll = "http://mathhub.info/FrameIT/frameworld?ConeVolumeScroll";
            public const string ScrollTruncatedConeVolumeScroll = "http://mathhub.info/FrameIT/frameworld?TruncatedConeVolumeScroll";
    
    MaZiFAU's avatar
    MaZiFAU committed
            public const string ScrollCannonBall = "CannonBall";
    
            public static readonly IReadOnlyDictionary<Type, string> TYPE_TO_OMS;
            public static readonly IReadOnlyDictionary<string, Type> OMS_TO_TYPE = new Dictionary<string, Type>()
            {
                { Point,
                    typeof(PointFact) },
                { Metric,
                    typeof(LineFact) },
                { Angle,
                    typeof(AngleFact) },
                { Eq,
                    typeof(AngleFact) },
                { RightAngle,
                    typeof(RightAngleFact) },
                { LineType,
                    typeof(RayFact) },
                { LineOf,
                    typeof(RayFact) },
                { OnLine,
                    typeof(OnLineFact) },
                { ParallelLine,
                    typeof(ParallelLineFact) },
                { CircleType3d,
                    typeof(CircleFact) },
                { OnCircle,
                    typeof(OnCircleFact) },
                { AnglePlaneLine,
                    typeof(AngleCircleLineFact) },
                { RadiusCircleMetric,
                    typeof(RadiusFact) },
                { AreaCircle,
                    typeof(AreaCircleFact) },
                { OrthoCircleLine,
                    typeof(OrthogonalCircleLineFact) },
                { VolumeCone,
                    typeof(ConeVolumeFact) },
                { TruncatedVolumeCone,
                    typeof(TruncatedConeVolumeFact) },
                { CylinderVolume,
                    typeof(CylinderVolumeFact) },
                { TestType,
                    typeof(TestFact) },
                { EqualityCircles,
                    typeof(EqualCirclesFact) },
                { UnEqualityCircles,
                    typeof(UnEqualCirclesFact) },
    
                { RealLit,
                    typeof(float) },
                { Tuple,
                    typeof(Vector3) },
                { ListType,
                    typeof(List<>) },
    
                { MkCircle3d, null }, //typeof(CircleFact) },
                { ConeOfCircleApex, null }, //typeof(ConeVolumeFact) },
    
                { Ded, null },
                { Sketch, null },
                { TriangleMiddlePoint, null },
                { ParametrizedPlane, null },
                { pointNormalPlane, null },
                { ParallelCircles, null },
    
                { "R",
                    typeof(float) },
                { typeof(float).ToString(),
                    typeof(float) },
                { typeof(double).ToString(),
                    typeof(double) },
                { typeof(string).ToString(),
                    typeof(string) },
                { typeof(Vector3).ToString(),
                    typeof(Vector3) },
            };
    
            static MMT_OMS_URI()
            {
                Dictionary<Type, string> _TYPE_TO_OMS = new();
                foreach (KeyValuePair<string, Type> KeyVal in OMS_TO_TYPE)
                    if (KeyVal.Value != null)
                        _TYPE_TO_OMS.TryAdd(KeyVal.Value, KeyVal.Key);
    
                TYPE_TO_OMS = _TYPE_TO_OMS;
            }
    
        public static class SOMDoctoLambdaExpression<T>
    
        {
            // TODO: Populate Dictionaries
            #region ExpressionDictionaries
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            delegate LambdaExpression CustomFunction(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params);
    
            private static readonly Dictionary<string, CustomFunction> MMTtoLambdaMaker = new()
    
    MaZiFAU's avatar
    MaZiFAU committed
                    MakeSin },
    
    MaZiFAU's avatar
    MaZiFAU committed
                    MakeCos },
    
    MaZiFAU's avatar
    MaZiFAU committed
                    MakeCos },
    
    MaZiFAU's avatar
    MaZiFAU committed
                { MMT_OMS_URI.Tuple,
    
    MaZiFAU's avatar
    MaZiFAU committed
                    MakeUnityEngineVector3 },
    
    MaZiFAU's avatar
    MaZiFAU committed
                { MMT_OMS_URI.MakeObjectArray,
    
    MaZiFAU's avatar
    MaZiFAU committed
                    MakeArray },
                { "InstantList",
                    MakeInstantList },
                { MMT_OMS_URI.ListEnd,
                    MakeListEnd },
                { MMT_OMS_URI.ListLiteral,
                    InsertFrontListLiteral },
                { MMT_OMS_URI.ListType,
                    Identity0 },
    
            private static readonly Dictionary<string, ExpressionType> MMTtoBinaryExpressionType = new()
    
                    ExpressionType.Add},
    
                    ExpressionType.AddAssign},
    
                    ExpressionType.AddAssignChecked},
    
                    ExpressionType.AddChecked},
    
                    ExpressionType.And},
    
                    ExpressionType.AndAlso},
    
                    ExpressionType.AndAssign},
    
                    ExpressionType.Assign},
    
                    ExpressionType.Divide},
    
                    ExpressionType.DivideAssign},
    
                    ExpressionType.Equal},
    
                    ExpressionType.ExclusiveOr},
    
                    ExpressionType.ExclusiveOrAssign},
    
                    ExpressionType.GreaterThan},
    
                    ExpressionType.GreaterThanOrEqual},
    
                    ExpressionType.LeftShift},
    
                    ExpressionType.LeftShiftAssign},
    
                    ExpressionType.LessThan},
    
                    ExpressionType.LessThanOrEqual},
    
                    ExpressionType.Modulo},
    
                    ExpressionType.ModuloAssign},
    
                    ExpressionType.Multiply},
    
                    ExpressionType.MultiplyAssign},
    
                    ExpressionType.MultiplyAssignChecked},
    
                    ExpressionType.MultiplyChecked},
    
                    ExpressionType.NotEqual},
    
                    ExpressionType.Or},
    
                    ExpressionType.OrAssign},
    
                    ExpressionType.OrElse},
    
                    ExpressionType.Power},
    
                    ExpressionType.PowerAssign},
    
                    ExpressionType.RightShift},
    
                    ExpressionType.RightShiftAssign},
    
                    ExpressionType.Subtract},
    
                    ExpressionType.SubtractAssign},
    
                    ExpressionType.SubtractAssignChecked},
    
                    ExpressionType.SubtractChecked},
            };
    
    
            private static readonly Dictionary<string, ExpressionType> MMTtoUnaryExpressionType = new()
    
            {
                //{ "Constant", // Not Unary
                //    ExpressionType.Constant},
    
                    ExpressionType.Convert},
    
                    ExpressionType.ConvertChecked},
    
                    ExpressionType.Decrement},
    
                    ExpressionType.Increment},
    
                    ExpressionType.Negate},
    
                    ExpressionType.NegateChecked},
    
                    ExpressionType.Not},
    
                    ExpressionType.OnesComplement},
    
                    ExpressionType.PostDecrementAssign},
    
                    ExpressionType.PostIncrementAssign},
    
                    ExpressionType.PreDecrementAssign},
    
                    ExpressionType.PreIncrementAssign},
    
                    ExpressionType.UnaryPlus},
            };
    
            #endregion ExpressionDictionaries
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            //TODO: case ((f->x)->y) instead of  assumed (f->(x->y))
    
    MaZiFAU's avatar
    MaZiFAU committed
            public static LambdaExpression MakeLambdaExpression(string URI, LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                void ThrowArgumentException(ExpressionType expression_cast, int expected)
                {
                    throw new ArgumentException(string.Format(
                        "\"Wrong number of Arguments. Required: {2}. Supplied: {3}.\\n\\tFor URI:\\\"{0}\\\"\\n\\tmapped to:\\\"{1}\\\"\"",
    
    MaZiFAU's avatar
    MaZiFAU committed
                        URI, expression_cast, expected, lambda_applicant.Count()
    
    MaZiFAU's avatar
    MaZiFAU committed
                ParameterExpression[] lambda_params =
    
    MaZiFAU's avatar
    MaZiFAU committed
                    lambda_applicant
    
    MaZiFAU's avatar
    MaZiFAU committed
                    .SelectMany(l => l.Parameters)
                    .ToArray(); //PERF: .ToList().Sort() => .BinarySearch;
    
    MaZiFAU's avatar
    MaZiFAU committed
                ParameterExpression[] found_bound_params =
    
    MaZiFAU's avatar
    MaZiFAU committed
                    bound_params
                    .Where(p => lambda_params.Contains(p))
                    .ToArray();
    
    
                if (MMTtoUnaryExpressionType.TryGetValue(URI, out var unnary_type))
                {
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (found_bound_params.Count() < 1)
    
                        ThrowArgumentException(unnary_type, 1);
    
    
    MaZiFAU's avatar
    MaZiFAU committed
                    Type UnarySecondArgument = found_bound_params.Count() < 2 ? null : found_bound_params[1].Type;
    
    MaZiFAU's avatar
    MaZiFAU committed
                    return Expression.Lambda(Expression.MakeUnary(unnary_type, lambda_applicant[0].Body, UnarySecondArgument), found_bound_params);
    
    MaZiFAU's avatar
    MaZiFAU committed
                else
                if (MMTtoBinaryExpressionType.TryGetValue(URI, out var binary_type))
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (lambda_applicant.Count() != 2)
    
                        ThrowArgumentException(binary_type, 2);
    
    
    MaZiFAU's avatar
    MaZiFAU committed
                    return Expression.Lambda(Expression.MakeBinary(binary_type, lambda_applicant[0].Body, lambda_applicant[1].Body), found_bound_params);
    
    MaZiFAU's avatar
    MaZiFAU committed
                else
                if (MMTtoLambdaMaker.TryGetValue(URI, out var lamda_maker))
    
    MaZiFAU's avatar
    MaZiFAU committed
                    return lamda_maker(lambda_applicant, lambda_arguments, found_bound_params);
                }
                else
                if (MMT_OMS_URI.OMS_TO_TYPE.TryGetValue(URI, out Type type))
                {
                    return Expression.Lambda(Expression.Default(type), null);
    
                throw new NotImplementedException("Could not map URI: \"" + URI + "\"");
            }
    
    
            private static LambdaExpression ExpresionFuncToLambda(LambdaExpression func, string name, LambdaExpression[] args_lamda, ParameterExpression[] bound_params, uint nTargs_fallback)
                => Expression.Lambda(Expression.Invoke(func, args_lamda.Select(l => l.Body)), name, bound_params);
    
            private static LambdaExpression ParseFuncUUToExpression<U>(Func<U, U> func)
    
                => (Expression<Func<U, U>>)((U x) => func(x));
    
    MaZiFAU's avatar
    MaZiFAU committed
            private static LambdaExpression MakeSin(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                => ExpresionFuncToLambda(
                        default(T) switch // TODO? cleaner switch
                        {
    
                            float => ParseFuncUUToExpression<float>(MathF.Sin),
    
                            double => ParseFuncUUToExpression<double>(Math.Sin),
    
    MaZiFAU's avatar
    MaZiFAU committed
                            _ => throw new NotImplementedException("Sinus for " + nameof(T) + "=" + typeof(T))
    
    MaZiFAU's avatar
    MaZiFAU committed
                        "Sin", lambda_applicant, bound_params, 1
    
    MaZiFAU's avatar
    MaZiFAU committed
            private static LambdaExpression MakeCos(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                => ExpresionFuncToLambda(
                        default(T) switch // TODO? cleaner switch
                        {
    
                            float => ParseFuncUUToExpression<float>(MathF.Cos),
    
                            double => ParseFuncUUToExpression<double>(Math.Cos),
    
    MaZiFAU's avatar
    MaZiFAU committed
                            _ => throw new NotImplementedException("Cosinus for " + nameof(T) + "=" + typeof(T))
    
    MaZiFAU's avatar
    MaZiFAU committed
                        "Cos", lambda_applicant, bound_params, 1
    
    MaZiFAU's avatar
    MaZiFAU committed
            private static LambdaExpression MakeUnityEngineVector3(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                => ExpresionFuncToLambda(
                        (Expression<Func<float, float, float, Vector3>>)((x, y, z) => new Vector3(x, y, z)),
    
    MaZiFAU's avatar
    MaZiFAU committed
                        "UnityEngineVector3", lambda_applicant, bound_params, 3
    
    MaZiFAU's avatar
    MaZiFAU committed
            private static LambdaExpression MakeArray(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
    MaZiFAU's avatar
    MaZiFAU committed
                => Expression.Lambda(
                        Expression.NewArrayInit(
    
    MaZiFAU's avatar
    MaZiFAU committed
                            typeof(object),
                            lambda_applicant.Select(l => Expression.Convert(l.Body, typeof(object)))
    
    MaZiFAU's avatar
    MaZiFAU committed
                        ),
                        bound_params
                    );
    
    MaZiFAU's avatar
    MaZiFAU committed
    
            private static LambdaExpression MakeInstantList(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                => Expression.Lambda(
                        Expression.ListInit(
                            Expression.New(typeof(List<>).MakeGenericType(lambda_applicant[0].ReturnType)),
                            lambda_arguments.Select(l => l.Body) // Expression.Convert(l.Body, lambda_applicant[0].ReturnType))
                        ),
                        bound_params
                    );
    
            private static LambdaExpression InsertFrontListLiteral(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                => Expression.Lambda(
                        Expression.Call(
                            lambda_applicant[0].Body,
                            lambda_applicant[0].ReturnType.GetMethod("Insert"),
                            Expression.Constant(0, typeof(int)),
                            lambda_applicant[1].Body
                        ),
                        bound_params
                    );
    
            private static LambdaExpression MakeListEnd(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                => Expression.Lambda(
                        Expression.New(typeof(List<>).MakeGenericType(lambda_applicant[0].ReturnType)),
                        null
                    );
    
            private static LambdaExpression Identity0(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                => lambda_applicant[0];
    
    
        [JsonConverter(typeof(JsonSubtypes), "kind")]
    
        [JsonSubtypes.KnownSubType(typeof(OMA), "OMA")]
    
        [JsonSubtypes.KnownSubType(typeof(OMBINDC), "OMBINDC")]
    
        [JsonSubtypes.KnownSubType(typeof(OMS), "OMS")]
        [JsonSubtypes.KnownSubType(typeof(OMSTR), "OMSTR")]
        [JsonSubtypes.KnownSubType(typeof(OMF), "OMF")]
        [JsonSubtypes.KnownSubType(typeof(OMV), "OMV")]
    
    MaZiFAU's avatar
    MaZiFAU committed
        [JsonSubtypes.KnownSubType(typeof(RAW), "RAW")]
    
        //[JsonSubtypes.KnownSubType(typeof(OMC<T>), "OMC<" + typeof(T) + ">")]
        [JsonSubtypes.KnownSubType(typeof(OMC<Vector3>), "OMC<UnityEngine.Vector3>")]
        [JsonSubtypes.KnownSubType(typeof(OMC<float>), "OMC<System.Single>")]
        [JsonSubtypes.KnownSubType(typeof(OMC<double>), "OMC<System.Double>")]
    
    MaZiFAU's avatar
    MaZiFAU committed
        [JsonSubtypes.FallBackSubType(typeof(OMS))] // dirty fix for wrong formated ScrollApplicationCheckingError.fact
    
            public string kind;
    
            protected SOMDoc() { kind = this.GetType().Name; }
    
            public static bool Equivalent(SOMDoc sd1, SOMDoc sd2)
    
                => sd1.Equivalent(sd2);
    
            public abstract bool Equivalent(SOMDoc sd2);
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            public LambdaExpression PartialInvokeCastingLambdaExpression(out Type[] signature_args, object[] callArgs = null, bool[] useArgs = null)
    
    MaZiFAU's avatar
    MaZiFAU committed
                LambdaExpression lambda_orig = GetLambdaExpression();
    
    MaZiFAU's avatar
    MaZiFAU committed
    
                signature_args = new Type[lambda_orig.Parameters.Count + 1];
    
                ParameterExpression object_arr = Expression.Parameter(typeof(object[]), "PARAMS_Arr");
                Expression[] cast_new_to_signature = new Expression[lambda_orig.Parameters.Count];
    
                int n_params = 0;
                for (int i = 0; i < lambda_orig.Parameters.Count; i++)
                {
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (callArgs != null && callArgs.Length < i
    
    MaZiFAU's avatar
    MaZiFAU committed
                     && (useArgs == null || (useArgs.Length < i && useArgs[i])))
    
    MaZiFAU's avatar
    MaZiFAU committed
                    {
                        cast_new_to_signature[i] =
    
    MaZiFAU's avatar
    MaZiFAU committed
                            Expression.Constant(callArgs[i], lambda_orig.Parameters[i].Type);
    
    MaZiFAU's avatar
    MaZiFAU committed
                        continue;
                    }
    
    
                    signature_args[n_params++] = lambda_orig.Parameters[i].Type;
    
    MaZiFAU's avatar
    MaZiFAU committed
    
                    cast_new_to_signature[i] =
                        Expression.Convert(
                            Expression.ArrayIndex(
                                object_arr,
                                Expression.Constant(i)
                            ),
    
                            lambda_orig.Parameters[i].Type
    
    MaZiFAU's avatar
    MaZiFAU committed
                        );
                }
                signature_args[n_params] = lambda_orig.ReturnType;
                signature_args = signature_args.Slice(0, n_params + 1).ToArray();
    
                return Expression.Lambda(
                    typeof(Array).IsAssignableFrom(lambda_orig.ReturnType)
                        ? Expression.Convert(
                            Expression.Invoke(lambda_orig, cast_new_to_signature),
                            typeof(object[]))
                        : Expression.NewArrayInit(
                            typeof(object),
                            new Expression[] { Expression.Convert(Expression.Invoke(lambda_orig, cast_new_to_signature), typeof(object)) }),
    
            public LambdaExpression GetLambdaExpression()
    
    MaZiFAU's avatar
    MaZiFAU committed
                => GetLambdaExpression(new LambdaExpression[0], new LambdaExpression[0], new ParameterExpression[0]);
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal abstract LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params);
    
    
            public abstract override string ToString();
    
            public abstract SOMDoc MapURIs(Dictionary<string, string> old_to_new);
    
    MaZiFAU's avatar
    MaZiFAU committed
            public static OMA MakeUnityEngineVector3(Vector3 vec)
    
    MaZiFAU's avatar
    MaZiFAU committed
                    new OMS(MMT_OMS_URI.Tuple),
    
    MaZiFAU's avatar
    MaZiFAU committed
            public static OMA MakeList(string[] lids, Type type)
                => MakeList(lids, MMT_OMS_URI.TYPE_TO_OMS[type]);
    
            public static OMA MakeList(string[] lids, string typeURI)
            {
                List<SOMDoc> end_of_list = new() {
                    new OMA(
                        new OMS(MMT_OMS_URI.ListEnd),
                        new() {
                            new OMS(typeURI),
                }),};
    
                if (lids.Length > 0)
                    end_of_list.Add(new OMS(lids[^1]));
    
                SOMDoc defines = new OMA(
                    new OMS(MMT_OMS_URI.ListLiteral),
                    end_of_list
                );
    
                for (int i = lids.Length - 2; i >= 0; i--)
                {
                    defines = new OMA(
                        new OMS(MMT_OMS_URI.ListLiteral),
                        new() {
                            defines,
                            new OMS(lids[i]),
                    });
                }
    
                SOMDoc type = new OMA(
                    new OMS(MMT_OMS_URI.ListType),
                    new() { new OMS(typeURI), }
                );
    
                return new OMA(type, new() { defines });
            }
    
            #endregion MakeMMT_OMS_URItoSOMDoc
        }
    
        public abstract class SOMDocCRTP<T> : SOMDoc where T : SOMDocCRTP<T>
        {
    
    
            public override bool Equivalent(SOMDoc sd2)
                => this.GetType() == sd2.GetType() && (this as T).EquivalentWrapped(sd2 as T);
    
            protected abstract bool EquivalentWrapped(T sd2);
    
    
            public override SOMDoc MapURIs(Dictionary<string, string> old_to_new)
                => MapURIsWrapped(old_to_new);
    
            public abstract T MapURIsWrapped(Dictionary<string, string> old_to_new);
    
        public class OMBINDC : SOMDocCRTP<OMBINDC>
        {
    
            public new string kind = "OMBINDC";
    
    
            public string name;
    
            public SOMDoc lambdabody;
    
            /// <summary>@Type of this variable</summary>
            [JsonIgnore]
            public Type type;
    
            /// <summary>Enables (especially <see cref="JsonConverter"/>) to read and set <see cref="type"/> by its <c>string</c> representation.</summary>
            public string typeString
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                get => MMT_OMS_URI.TYPE_TO_OMS[type];
                set => type = MMT_OMS_URI.OMS_TO_TYPE[value];
    
            }
    
            [JsonConstructor]
            public OMBINDC(string name, string typeString, SOMDoc lambdabody) : base()
            {
                this.name = name;
                this.typeString = typeString;
                this.lambdabody = lambdabody;
            }
    
            public OMBINDC(string name, Type type, SOMDoc lambdabody) : base()
            {
                this.name = name;
                this.type = type;
                this.lambdabody = lambdabody;
            }
    
            protected override bool EquivalentWrapped(OMBINDC sd2)
    
    MaZiFAU's avatar
    MaZiFAU committed
                => this.type == sd2.type
    
    MaZiFAU's avatar
    MaZiFAU committed
                && this.name.Equals(sd2.name)
                && this.lambdabody.Equivalent(sd2.lambdabody);
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
            {
                ParameterExpression[] bind_me = bound_params.ShallowCloneAppend(
                    new[] { Expression.Parameter(type, name) }
                );
    
    
    MaZiFAU's avatar
    MaZiFAU committed
                return lambdabody.GetLambdaExpression(lambda_applicant, lambda_arguments, bind_me);
    
            }
    
            public override string ToString()
    
                => "OMBINDC(" + name + ", " + typeString + ")->";
    
    
            public override OMBINDC MapURIsWrapped(Dictionary<string, string> old_to_new)
                => new(name, type, lambdabody.MapURIs(old_to_new));
        }
    
    
            public new string kind = "OMA";
    
            public SOMDoc applicant;
            public List<SOMDoc> arguments;
    
            [JsonConstructor]
    
            public OMA(SOMDoc applicant, List<SOMDoc> arguments) : base()
    
            {
                this.applicant = applicant;
                this.arguments = arguments;
            }
    
            protected override bool EquivalentWrapped(OMA sd2)
                => Equivalent(this.applicant, sd2.applicant)
    
                && this.arguments
                    .Zip(sd2.arguments, (arg1, arg2) => Equivalent(arg1, arg2))
                    .All(b => b);
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant_paps, LambdaExpression[] lambda_applicant_grands, ParameterExpression[] bound_params)
    
                => applicant.GetLambdaExpression(
    
    MaZiFAU's avatar
    MaZiFAU committed
                    arguments.Select(arg => arg.GetLambdaExpression(new LambdaExpression[0], new LambdaExpression[0], bound_params)).ToArray(),
                    lambda_applicant_paps,
    
                    bound_params
                );
    
    
            public override string ToString()
    
                => applicant.ToString() + "(" + string.Join(", ", arguments.Select(a => a.ToString())) + ")";
    
    
            public override OMA MapURIsWrapped(Dictionary<string, string> old_to_new)
                => new OMA(
                    applicant.MapURIs(old_to_new),
                    arguments.Select(arg => arg.MapURIs(old_to_new)).ToList()
                );
    
            public new string kind = "OMS";
    
            public string uri;
    
            [JsonConstructor]
    
            protected override bool EquivalentWrapped(OMS sd2)
                => this.uri == sd2.uri;
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                => SOMDoctoLambdaExpression<float>.MakeLambdaExpression(uri, lambda_applicant, lambda_arguments, bound_params);
    
    
            public override string ToString()
                => uri;
    
    
            public override OMS MapURIsWrapped(Dictionary<string, string> old_to_new)
            {
                if (!old_to_new.TryGetValue(uri, out string new_uri))
                    new_uri = uri;
    
                return new OMS(new_uri);
            }
    
            public new string kind = "OMSTR";
    
            [JsonProperty("float")]
            public string s;
    
    
            [JsonConstructor]
    
                this.s = s;
    
            protected override bool EquivalentWrapped(OMSTR sd2)
                => this.s == sd2.s;
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                => Expression.Lambda(Expression.Constant(s, typeof(string)), null);
    
    
            public override string ToString()
                => s;
    
    
            public override OMSTR MapURIsWrapped(Dictionary<string, string> old_to_new)
                => (OMSTR)this.MemberwiseClone();
    
            public new string kind = "OMF";
    
            [JsonProperty("float")]
    
    MaZiFAU's avatar
    MaZiFAU committed
            public float @float;
    
            [JsonConstructor]
    
    MaZiFAU's avatar
    MaZiFAU committed
                this.@float = f;
    
            protected override bool EquivalentWrapped(OMF sd2)
    
    MaZiFAU's avatar
    MaZiFAU committed
                => Mathf.Approximately(@float, sd2.@float);
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
    MaZiFAU's avatar
    MaZiFAU committed
                => Expression.Lambda(Expression.Constant(@float, typeof(float)), null);
    
    
            public override string ToString()
    
    MaZiFAU's avatar
    MaZiFAU committed
                => @float.ToString();
    
    
            public override OMF MapURIsWrapped(Dictionary<string, string> old_to_new)
                => (OMF)this.MemberwiseClone();
    
            public new string kind = "OMC<" + typeof(T) + ">";
    
    
            public T value;
    
            [JsonConstructor]
    
            {
                this.value = value;
            }
    
    
            protected override bool EquivalentWrapped(OMC<T> sd2)
            {
                Debug.LogWarning("Cannot check Equivalency for " + this.GetType() + "; only whether it's exact!");
                return this.value.Equals(value);
            }
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                => Expression.Lambda(Expression.Constant(value, typeof(T)), null);
    
            public override string ToString()
                => "C_" + typeof(T) + "(" + value.ToString() + ")";
    
    
            public override OMC<T> MapURIsWrapped(Dictionary<string, string> old_to_new)
                => (OMC<T>)this.MemberwiseClone();
    
            public new string kind = "OMV";
    
    
            public string name;
    
            [JsonConstructor]
    
            public OMV(string name) : base()
    
            {
                this.name = name;
            }
    
    
            protected override bool EquivalentWrapped(OMV sd2)
    
                => this.name == sd2.name;
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
                ParameterExpression v = bound_params.FirstOrDefault(param => param.Name.Equals(name));
                if (v == null)
                {
                    Debug.LogErrorFormat("Unable to find {0} for {1} with name: {2}", nameof(OMBINDC), nameof(OMV), name);
                    return Expression.Lambda(Expression.Empty(), null);
                }
                else
                    return Expression.Lambda(v, new[] { v });
    
            }
    
            public override string ToString()
    
                => "Variable_" + "(" + name + ")";
    
    
            public override OMV MapURIsWrapped(Dictionary<string, string> old_to_new)
                => (OMV)this.MemberwiseClone();
    
    MaZiFAU's avatar
    MaZiFAU committed
        public class RAW : SOMDocCRTP<RAW>
        {
            public new string kind = "RAW";
    
            public string xml;
    
            [JsonConstructor]
            public RAW(string xml) : base()
            {
                this.xml = xml;
            }
    
            public override RAW MapURIsWrapped(Dictionary<string, string> old_to_new)
            {
                string copy = xml;
                foreach (KeyValuePair<string, string> KeyVal in old_to_new)
                    copy = copy.Replace(KeyVal.Key, KeyVal.Value);
    
                return new RAW(copy);
            }
    
            public override string ToString()
                => xml;
    
            protected override bool EquivalentWrapped(RAW sd2)
                => throw new NotImplementedException(); //xml == sd2.xml; // only exact
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
    
    MaZiFAU's avatar
    MaZiFAU committed
            {
                throw new NotImplementedException();
            }
        }
    
        [JsonConverter(typeof(JsonSubtypes), "kind")]
        [JsonSubtypes.KnownSubType(typeof(MMTSymbolDeclaration), "general")]
        [JsonSubtypes.KnownSubType(typeof(MMTValueDeclaration), "veq")]
        public abstract class MMTDeclaration
    
            public string kind;
    
            public UriReference @ref;
    
            public static MMTDeclaration FromJson(string json)
            {
                MMTDeclaration mmtDecl = JsonConvert.DeserializeObject<MMTDeclaration>(json);
    
                mmtDecl.label ??= string.Empty;
    
                return mmtDecl;
            }
    
    MaZiFAU's avatar
    MaZiFAU committed
            public string ToJson()
    
    MaZiFAU's avatar
    MaZiFAU committed
                label ??= string.Empty;
                return JsonConvert.SerializeObject(this);
    
    
            public abstract string getType();
    
            public abstract string getApplicant();
    
        /// <summary>MMTSymbolDeclaration: Class for facts without values, e.g. Points</summary>
    
        public class MMTSymbolDeclaration : MMTDeclaration
    
            public new string kind = "general";
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            [JsonProperty("tp")]
            public SOMDoc type;
            [JsonProperty("df")]
            public SOMDoc defines;
    
            [JsonConstructor]
            private MMTSymbolDeclaration() { }
    
            /// <summary>Constructor used for sending new declarations to mmt</summary>
    
    MaZiFAU's avatar
    MaZiFAU committed
            public MMTSymbolDeclaration(string label, SOMDoc type, SOMDoc defines)
    
    MaZiFAU's avatar
    MaZiFAU committed
                this.type = type;
                this.defines = defines;
    
            public override string getType()
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                return type switch
    
                {
                    OMS oMS => oMS.uri,
                    OMA oMA => ((oMA.arguments[0] as OMA).applicant as OMS).uri,
                    _ => null
                };
            }
    
            public override string getApplicant()
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                return defines switch
    
                {
                    OMA oMA when oMA.applicant is OMS oMS => oMS.uri,
                    _ => null
                };
            }
    
        /// <summary>MMTValueDeclaration: Class for facts with values, e.g. Distances or Angles</summary>
    
        public class MMTValueDeclaration : MMTDeclaration
    
            public new string kind = "veq";
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            [JsonProperty("valueTp")]
            public SOMDoc valueType;
    
            public SOMDoc proof;
    
            [JsonConstructor]
            private MMTValueDeclaration() { }
    
            /// <summary>Constructor used for sending new declarations to mmt</summary>
    
    MaZiFAU's avatar
    MaZiFAU committed
            public MMTValueDeclaration(string label, SOMDoc lhs, SOMDoc valueType, SOMDoc value, SOMDoc proof = null)
    
            {
                this.label = label;
                this.lhs = lhs;
    
    MaZiFAU's avatar
    MaZiFAU committed
                this.valueType = valueType;
    
                this.proof = proof;
            }
    
            public override string getType()
            {
                return lhs switch
                {
                    OMA oMA when oMA.applicant is OMS oMS => oMS.uri,
                    _ => null
                };
            }
    
            public override string getApplicant()
            {
                return lhs switch
                {
                    OMA oMA when oMA.applicant is OMS oMS => oMS.uri,
                    _ => null
                };