From 3b7728f234ffc0138b1731c4455738adf28c8de9 Mon Sep 17 00:00:00 2001
From: MaZiFAU <63099053+MaZiFAU@users.noreply.github.com>
Date: Mon, 11 Sep 2023 21:01:41 +0200
Subject: [PATCH] Fixed SOMDocToLambdaExpression for Lambdas

---
 .../FactHandling/Facts/FunctionFact.cs        |  11 +-
 .../CommunicationProtocoll/MMTConstants.cs    |  11 +-
 .../SOMDocToLambdaExpression.cs               | 103 ++++++---
 .../CommunicationProtocoll/SOMDocs.cs         | 218 +++++++++++-------
 .../Utility/Extensions/FuncExtensions.cs      |  13 +-
 .../Utility/Extensions/TupleExtensions.cs     |   6 +-
 6 files changed, 235 insertions(+), 127 deletions(-)

diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs
index 871c438f..093ba178 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs
@@ -135,7 +135,7 @@ protected override void RecalculateTransform() { }
     {// TODO Correctness
 
         if (((MMTGeneralFact)fact).defines is not FUN fun
-            && (((MMTGeneralFact)fact).defines is not SFunctionWrapper SFW 
+            && (((MMTGeneralFact)fact).defines is not FallbackWrapper SFW 
             || (fun = SFW.SFunction as FUN) == null)
         )
             return null;
@@ -164,10 +164,11 @@ protected override bool EquivalentWrapped(FunctionFact f1, FunctionFact f2)
     protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactRecorder organizer)
         => new FunctionFact(this.Function_SOMDoc.MapURIs(old_to_new), organizer);
 
-    public override MMTFact MakeMMTDeclaration()
-    {
-        throw new NotImplementedException();
-    }
+    public override MMTFact MakeMMTDeclaration() 
+        => new MMTGeneralFact(
+            Label, 
+            SOMDoc.SOMDocType(FuncExtensions.CreateFuncType(Signature)), 
+            Function_SOMDoc);
 }
 
 public class AttachedPositionFunction : FactWrappedCRTP<AttachedPositionFunction>
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs
index 06e81e37..3ca1fb65 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using UnityEngine;
 
 namespace REST_JSON_API
@@ -163,10 +164,12 @@ public static class MMTConstants
                 typeof(List<>) },
 
             { AddRealLit,
-                typeof(float) }, //typeof(Func<,,>).MakeGenericType(typeof(float), typeof(float), typeof(float))
+                typeof(Func<,,>).MakeGenericType(typeof(float), typeof(float), typeof(float)) },
+            { ProjL, // how?
+                typeof(Func<,>) }, //.MakeGenericType(typeof(Tuple))
 
-            { MkCircle3d, null }, //typeof(CircleFact) },
-            { ConeOfCircleApex, null }, //typeof(ConeVolumeFact) },
+            { MkCircle3d, typeof(CircleFact) },
+            { ConeOfCircleApex, typeof(ConeVolumeFact) },
 
             { Ded, null },
             { Sketch, null },
@@ -175,8 +178,6 @@ public static class MMTConstants
             { pointNormalPlane, null },
             { ParallelCircles, null },
 
-            { "R",
-                typeof(float) },
             { typeof(float).ToString(),
                 typeof(float) },
             { typeof(double).ToString(),
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
index 00e6d6fe..d369bd77 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
@@ -201,7 +201,35 @@ void ThrowArgumentException(ExpressionType expression_cast, int expected)
                         ? gf.defines
                         : (decl as MMTValueFact).lhs;
 
-                    return df.GetLambdaExpression();
+                    LambdaExpression lambda_orig = df.GetLambdaExpression();
+
+                    if (lambda_orig.Body is not LambdaExpression lambda_lambda
+                     || lambda_applicant.Length == 0)
+                        return lambda_orig;
+
+                    int free_params = lambda_lambda.Parameters.Count() - lambda_applicant.Length;
+                    if (free_params <= 0)
+                        return Expression.Lambda(
+                            Expression.Invoke(lambda_lambda, lambda_applicant[..^Math.Max(0, free_params)]),
+                            found_bound_params
+                        );
+
+                    ParameterExpression[] new_params =
+                        lambda_lambda.Parameters
+                        .Skip(lambda_applicant.Length)
+                        .Select(p => Expression.Parameter(p.Type))
+                        .ToArray();
+
+                    return Expression.Lambda(
+                        Expression.Lambda(
+                            Expression.Invoke(
+                                lambda_lambda,
+                                lambda_applicant.Select(app => app.Body).AppendRange(new_params)
+                            ),
+                            new_params
+                        ),
+                        found_bound_params
+                    );
                 }
                 else
                 if (MMTtoUnaryExpressionType.TryGetValue(URI, out var unnary_type))
@@ -342,12 +370,12 @@ private static LambdaExpression MakeObjArray(LambdaExpression[] lambda_applicant
                 }
 
                 return Expression.Lambda(
-                                    Expression.NewArrayInit(
-                                        typeof(object),
-                                        lambda_applicant.Select(l => Expression.Convert(l.Body, typeof(object)))
-                                    ),
-                                    bound_params
-                                );
+                            Expression.NewArrayInit(
+                                typeof(object),
+                                lambda_applicant.Select(l => Expression.Convert(l.Body, typeof(object)))
+                            ),
+                            bound_params
+                        );
             }
 
             private static LambdaExpression MakeInstantList(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
@@ -416,7 +444,7 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
 
                     if (call_method == null)
                     { // call_method is overloaded or generic
-                        (MethodInfo m, bool Success, Dictionary<string, (Type To, int Dirty)> method_types)[] recipe =
+                        (MethodInfo m, bool Success, Dictionary<string, (Type To, int Dirty)> method_types, Expression[] partials)[] recipe =
                             type.GetMethods()
                             .Where(m =>
                                 m.Name.Equals(method_name) &&
@@ -433,9 +461,9 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
 
                                 if (!test.All(t => t.Success)
                                  || !test.All(t => method_types.TryAddAllFrom(t.GenericParameters)))
-                                    return (m, false, new());
+                                    return (m, false, new(), new LambdaExpression[0]);
                                 else
-                                    return (m, Success: true, method_types);
+                                    return (m, Success: true, method_types, test.Select(t => t.partials).ToArray());
                             }).Where(t => t.Success)
                             .ToArray();
 
@@ -445,6 +473,7 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
                             Debug.LogWarning($"Found methods not unique for \"{method_name}\" in Type \"{type}\" and Type Signature [{lambda_args_type}]");
 
                         call_method = recipe[0].m;
+                        call_args = recipe[0].partials;
                         if (call_method.IsGenericMethod)
                         {
                             call_method = call_method.MakeGenericMethod(
@@ -453,21 +482,6 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
                                 .ToArray()
                             );
                         }
-
-                        ParameterInfo[] call_para = call_method.GetParameters();
-                        for (int i = 0; i < lambda_args_new.Length; i++)
-                        {
-                            if (!call_para[i].ParameterType
-                                .GetGenericArguments()
-                                .Any(arg => recipe[0].method_types[arg.Name].Dirty)
-                            )
-                                continue;
-
-
-                        }
-
-
-                        ;
                     }
 
                     return Expression.Lambda(
@@ -482,8 +496,6 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
                     IsCompatibleType(Type generic, Type from_me, Expression source_from_me, int dirty)
                     {
                         Dictionary<string, (Type To, int Dirty)> retDic = new();
-                        (bool Success, Dictionary<string, (Type To, int Dirty)> GenericParameters, Expression partials) retVal =
-                            (false, retDic, source_from_me);
 
                         if (generic.HasElementType
                          && from_me.HasElementType)
@@ -544,19 +556,40 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
                                     Expression[] expr_decomp = null;
                                     if (IsParame)
                                     {
+                                        if (IsDirty)
+                                        {
+                                            Debug.LogWarning(
+                                                "If you see this message, you have found an example for this branch.\n" +
+                                                "I have no clue what will happen now. Good Luck!");
+
+                                            // What should it be?
+                                            // Call(generic)([(from_me)=>generic](from_me))
+                                            // Call([(A)=>C]=>...)([([(a,b)=>c]=>...)=>[(A)=>C]=>...]([(a,b)=>c]=>...))
+                                            // [(from_me-generic)=>Call(generic)([(from_me)=>generic](from_me))]
+                                            //
+                                            //generic: [(A)=>C]=>...
+                                            //from_me: [(a,b)=>c]=>...
+                                            //result:  [(A)=>[(a,b)=>c](b)]=>...
+                                            //   or?:  [(a)=>[(b)=>c]]=>...
+                                            //   or?:  [[(a,b)=>c]=>C]=>...
+                                            //
+                                            //(from_me)=>generic]:
+                                            //  [[(a,b)=>c]=>...]=>[[(A)=>C]=>...]
+
+                                            //Lamb(Call(from_me, (A,b)), A) -> escalate b
+                                        }
+
                                         Type[] from_args = from_me.GetGenericArguments();
                                         Type partial_type = generic
                                             .GetGenericTypeDefinition()
-                                            .MakeGenericType(
-                                                from_args[..(gene_sig - 1)]
+                                            .MakeGenericType(!IsDirty
+                                                ? from_args
+                                                : from_args[..(gene_sig - 1)]
                                                 .Append(FuncExtensions.CreateFuncType(from_args[(gene_sig - 1)..]))
                                                 .ToArray()
                                             );
-                                        //[(a)=>c]
-                                        //[(a,b)=>c]
-                                        //
-                                        //[(a)=>[(a,b)=>c](b)]
-                                        expr_decomp = // schould it be (from_me)=>generic
+
+                                        expr_decomp =
                                             partial_type.GetGenericArguments()
                                             .Select(typ => Expression.Parameter(typ))
                                             .ToArray();
@@ -585,7 +618,7 @@ private static CustomFunction CallAnyFunction(bool self, string method_name, Typ
                                         return (false, new(), source_from_me);
 
                                     Expression source_partial =
-                                        IsParame ? 
+                                        IsParame ?
                                             Expression.Parameter(
                                                 FuncExtensions.CreateFuncType(
                                                     recursion.Select(t => t.partials.Type).ToArray())) :
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs
index 51374261..7f454029 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs
@@ -22,22 +22,40 @@ namespace REST_JSON_API
     [JsonSubtypes.KnownSubType(typeof(OMC<Vector3>), "OMC<UnityEngine.Vector3>")]
     [JsonSubtypes.KnownSubType(typeof(OMC<float>), "OMC<System.Single>")]
     [JsonSubtypes.KnownSubType(typeof(OMC<double>), "OMC<System.Double>")]
-    [JsonSubtypes.FallBackSubType(typeof(SFunctionWrapper))]
+    [JsonSubtypes.FallBackSubType(typeof(FallbackWrapper))]
     abstract public partial class SOMDoc
     {
         public string kind;
 
         protected SOMDoc() { kind = this.GetType().Name; }
 
+        protected internal abstract SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params);
         public SOMDoc SOMDocType()
-            => SOMDocType(new SOMDoc[0]);
+            => SOMDocType(new SOMDoc[0], new FUN.Param[0]);
 
-        protected internal abstract SOMDoc SOMDocType(SOMDoc[] args);
+        public static SOMDoc SOMDocType(Type type)
+        {
+            if (type == typeof(Vector3)) // Isomoprhismus
+                type = typeof(Tuple);
 
-        public Type ToType()
-            => ToType(new Type[0]);
+            SOMDoc[] args = type.IsGenericType
+                ? type.GetGenericArguments().Select(t => SOMDocType(t)).ToArray()
+                : null;
+
+            if (FuncExtensions.GenericFuncTypes.Contains(type.IsGenericType ? type.GetGenericTypeDefinition() : type))
+                return new FUNTYPE(args[..^1], args[^1]);
 
-        protected internal abstract Type ToType(Type[] args);
+            if (MMTConstants.TYPE_TO_OMS.TryGetValue(type, out string uri))
+                return type.IsGenericType
+                    ? new OMA(new OMS(uri), args)
+                    : new OMS(uri);
+
+            throw new NotImplementedException();
+        }
+
+        protected internal abstract Type ToType(Type[] args, (string name, Type type)[] bound_params);
+        public Type ToType()
+            => ToType(new Type[0], new (string name, Type type)[0] );
 
         public static bool Equivalent(SOMDoc sd1, SOMDoc sd2)
             => sd1 != null && sd2 != null
@@ -228,13 +246,13 @@ protected internal override LambdaExpression GetLambdaExpression(LambdaExpressio
             throw new NotImplementedException();
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
         {
             throw new NotImplementedException();
         }
 
-        protected internal override Type ToType(Type[] args)
-            => typeof(Func<>).MakeGenericType(Enumerable.Append(@params.Select(p => p.ToType()), ret.ToType()).ToArray());
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params) 
+            => FuncExtensions.CreateFuncType(Enumerable.Append(@params.Select(p => p.ToType()), ret.ToType()).ToArray());
     }
 
     public class FUN : SOMDocCRTP<FUN>
@@ -255,19 +273,23 @@ public FUN(Param[] @params, SOMDoc body)
         public class Param
         {
             public string name;
-            public SOMDoc tp;
+            [JsonProperty("tp")]
+            public SOMDoc type;
 
             [JsonConstructor]
             public Param(string name, SOMDoc tp)
             {
                 this.name = name;
-                this.tp = tp;
+                this.type = tp;
             }
+
+            public override string ToString()
+                => name + "(" + type.ToString() + ")";
         }
 
         public override string ToString()
             => "["
-            + string.Join(", ", @params.Select(p => p.name + "(" + p.tp.ToString() + ")"))
+            + string.Join(", ", @params.Select(p => p.ToString()))
             + "] => {"
             + body.ToString()
             + "}";
@@ -275,18 +297,18 @@ public override string ToString()
         protected override bool EquivalentWrapped(FUN sd2)
             => @params.Length == sd2.@params.Length
             && @params.Zip(sd2.@params, (a, b) => a.name.Equals(b.name)
-                                               && a.tp.Equivalent(b.tp))
+                                               && a.type.Equivalent(b.type))
                       .All(b => b)
             && body.Equivalent(sd2.body);
 
         protected override FUN MapURIsWrapped(Dictionary<string, string> old_to_new)
-            => new(@params.Select(p => new Param(p.name, p.tp.MapURIs(old_to_new))).ToArray()
+            => new(@params.Select(p => new Param(p.name, p.type.MapURIs(old_to_new))).ToArray()
                  , body.MapURIs(old_to_new));
 
         protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
         {
             ParameterExpression[] bind_me = bound_params.ShallowCloneAppend(
-                @params.Select(p => Expression.Parameter(p.tp.ToType(), p.name)).ToArray()
+                @params.Select(p => Expression.Parameter(p.type.ToType(), p.name)).ToArray()
             );
 
             return Expression.Lambda(
@@ -294,11 +316,24 @@ protected internal override LambdaExpression GetLambdaExpression(LambdaExpressio
                 bound_params);
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-            => new FUNTYPE(@params.Select(p => p.tp.SOMDocType()).ToArray(), body.SOMDocType());
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, Param[] bound_params)
+        {
+            Param[] bind_me = bound_params.ShallowCloneAppend(@params);
 
-        protected internal override Type ToType(Type[] args)
-            => SOMDocType().ToType();
+            return new FUNTYPE(
+                @params.Select(p => p.type).ToArray(),
+                body.SOMDocType(new SOMDoc[0], bind_me)
+            );
+        }
+
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
+        {
+            (string name, Type)[] bind_me = bound_params
+                .AppendRange(@params.Select(p => (p.name, p.type.ToType())))
+                .ToArray();
+
+            return SOMDocType().ToType(new Type[0], bind_me);
+        }
     }
 
     public class OMV : SOMDocCRTP<OMV>
@@ -313,12 +348,27 @@ public OMV(string name) : base()
             this.name = name;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-            => throw new NotImplementedException();
-
         protected override bool EquivalentWrapped(OMV sd2)
             => this.name == sd2.name;
 
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
+        {
+            FUN.Param p = bound_params.FirstOrDefault(param => param.name.Equals(name))
+                ?? throw new FormatException($"Unable to find {nameof(FUN.Param)} for {nameof(OMV)} with name: {name}");
+
+            return p.type;
+        }
+
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
+        {
+            (string name, Type type) p = bound_params.FirstOrDefault(param => param.name.Equals(name));
+
+            if(p == default)
+                throw new FormatException($"Unable to find {nameof(FUN.Param)} for {nameof(OMV)} with name: {name}");
+
+            return p.type;
+        }
+
         protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
         {
             ParameterExpression v = bound_params.FirstOrDefault(param => param.Name.Equals(name));
@@ -336,11 +386,6 @@ public override string ToString()
 
         protected override OMV MapURIsWrapped(Dictionary<string, string> old_to_new)
             => (OMV)this.MemberwiseClone();
-
-        protected internal override Type ToType(Type[] args)
-        {
-            throw new NotImplementedException();
-        }
     }
 
     public class OMA : SOMDocCRTP<OMA>
@@ -357,8 +402,11 @@ public OMA(SOMDoc applicant, SOMDoc[] arguments) : base()
             this.arguments = arguments;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-            => applicant.SOMDocType(arguments.Select(a => a.SOMDocType()).ToArray());
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
+            => applicant.SOMDocType(
+                arguments.Select(a => a.SOMDocType(new SOMDoc[0], bound_params)).ToArray(),
+                bound_params
+            );
 
         protected override bool EquivalentWrapped(OMA sd2)
             => Equivalent(this.applicant, sd2.applicant)
@@ -382,8 +430,11 @@ protected override OMA MapURIsWrapped(Dictionary<string, string> old_to_new)
                 arguments.Select(arg => arg.MapURIs(old_to_new)).ToArray()
             );
 
-        protected internal override Type ToType(Type[] args)
-            => applicant.ToType(arguments.Select(arg => arg.ToType()).ToArray());
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
+            => applicant.ToType(
+                arguments.Select(arg => arg.ToType(new Type[0], bound_params)).ToArray(),
+                bound_params
+            );
     }
 
     public class OMS : SOMDocCRTP<OMS>
@@ -398,29 +449,6 @@ public OMS(string uri) : base()
             this.uri = uri;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-        {
-            if (FactRecorder.AllFacts.TryGetValue(uri, out Fact found))
-                return new OMS(MMTConstants.TYPE_TO_OMS[found.GetType()]);
-
-            if (MMTConstants.HeterogenApplication_TO_TypeOF.TryGetValue(uri, out string type))
-                return new OMA(
-                    new OMS(type),
-                    args
-                );
-
-            if (MMTConstants.HomogenApplication_TO_TypeOF.TryGetValue(uri, out type))
-                return new OMA(
-                    new OMS(type),
-                    new[] { args[0] }
-                );
-
-            if (MMTConstants.URI_TO_TypeOF.TryGetValue(uri, out type))
-                return new OMS(type);
-
-            throw new NotImplementedException();
-        }
-
         protected override bool EquivalentWrapped(OMS sd2)
             => this.uri == sd2.uri;
 
@@ -438,7 +466,7 @@ protected override OMS MapURIsWrapped(Dictionary<string, string> old_to_new)
             return new OMS(new_uri);
         }
 
-        protected internal override Type ToType(Type[] args)
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
         {
             if (FactRecorder.AllFacts.TryGetValue(uri, out Fact found))
                 return found.GetType();
@@ -455,6 +483,9 @@ protected internal override Type ToType(Type[] args)
 
                     type = TupleExtensions.GetGenericTupleType(args.Length);
                 }
+                else
+                if (type.Equals(typeof(Func<>)))
+                    return FuncExtensions.CreateFuncType(args);
 
                 return type
                     .MakeGenericType(args);
@@ -472,6 +503,38 @@ protected internal override Type ToType(Type[] args)
 
             throw new NotImplementedException();
         }
+
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
+        {
+            string _uri = uri;
+            bool use_uri;
+            if (use_uri = MMTConstants.OMS_TO_TYPE.TryGetValue(_uri, out Type tmp_type))
+                _uri = MMTConstants.TYPE_TO_OMS[tmp_type];
+
+            if (FactRecorder.AllFacts.TryGetValue(_uri, out Fact found))
+                return new OMS(MMTConstants.TYPE_TO_OMS[found.GetType()]);
+
+            if (MMTConstants.HeterogenApplication_TO_TypeOF.TryGetValue(_uri, out string type))
+                return new OMA(
+                    new OMS(type),
+                    args
+                );
+
+            if (MMTConstants.HomogenApplication_TO_TypeOF.TryGetValue(_uri, out type))
+                return new OMA(
+                    new OMS(type),
+                    new[] { args[0] }
+                );
+
+            if (MMTConstants.URI_TO_TypeOF.TryGetValue(_uri, out type))
+                return new OMS(type);
+
+            if (use_uri)
+                return SOMDocType(tmp_type);
+                //return new OMS(_uri);
+
+            throw new NotImplementedException(uri);
+        }
     }
 
     public class OMSTR : SOMDocCRTP<OMSTR>
@@ -487,7 +550,7 @@ public OMSTR(string s) : base()
             this.s = s;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
             => throw new NotImplementedException();
 
         protected override bool EquivalentWrapped(OMSTR sd2)
@@ -502,7 +565,7 @@ public override string ToString()
         protected override OMSTR MapURIsWrapped(Dictionary<string, string> old_to_new)
             => (OMSTR)this.MemberwiseClone();
 
-        protected internal override Type ToType(Type[] args)
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
             => typeof(string);
     }
 
@@ -519,7 +582,7 @@ public OMF(float f) : base()
             this.@float = f;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
             => new OMS(MMTConstants.RealLit);
 
         protected override bool EquivalentWrapped(OMF sd2)
@@ -534,7 +597,7 @@ public override string ToString()
         protected override OMF MapURIsWrapped(Dictionary<string, string> old_to_new)
             => (OMF)this.MemberwiseClone();
 
-        protected internal override Type ToType(Type[] args)
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
             => typeof(float);
     }
 
@@ -550,8 +613,8 @@ public RAW(string xml) : base()
             this.xml = xml;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-            => throw new NotImplementedException();
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
+            => throw new NotSupportedException();
 
         protected override RAW MapURIsWrapped(Dictionary<string, string> old_to_new)
         {
@@ -569,22 +632,19 @@ protected override bool EquivalentWrapped(RAW sd2)
             => throw new NotImplementedException(); //xml == sd2.xml; // only exact
 
         protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
-        {
-            throw new NotImplementedException();
-        }
+            => throw new NotSupportedException();
 
-        protected internal override Type ToType(Type[] args)
-        {
-            throw new NotImplementedException();
-        }
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
+            => throw new NotSupportedException();
     }
 
-    public class SFunctionWrapper : SOMDocCRTP<SFunctionWrapper>
+    // temporary fix if Serialzation is broken
+    public class FallbackWrapper : SOMDocCRTP<FallbackWrapper>
     {
         public SOMDoc SFunction;
 
         [JsonConstructor]
-        public SFunctionWrapper(SOMDoc SFunction)
+        public FallbackWrapper(SOMDoc SFunction)
         {
             this.SFunction = SFunction;
         }
@@ -592,20 +652,20 @@ public SFunctionWrapper(SOMDoc SFunction)
         public override string ToString()
             => SFunction.ToString();
 
-        protected override bool EquivalentWrapped(SFunctionWrapper sd2)
+        protected override bool EquivalentWrapped(FallbackWrapper sd2)
             => SFunction.Equivalent(sd2);
 
-        protected override SFunctionWrapper MapURIsWrapped(Dictionary<string, string> old_to_new)
+        protected override FallbackWrapper MapURIsWrapped(Dictionary<string, string> old_to_new)
             => new(SFunction.MapURIs(old_to_new));
 
         protected internal override LambdaExpression GetLambdaExpression(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
             => SFunction.GetLambdaExpression(lambda_applicant, lambda_arguments, bound_params);
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-            => SFunction.SOMDocType(args);
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
+            => SFunction.SOMDocType(args, bound_params);
 
-        protected internal override Type ToType(Type[] args)
-            => SFunction.ToType(args);
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
+            => SFunction.ToType(args, bound_params);
     }
 
     // internal use only
@@ -621,8 +681,8 @@ public OMC(T value) : base()
             this.value = value;
         }
 
-        protected internal override SOMDoc SOMDocType(SOMDoc[] args)
-            => new OMS(MMTConstants.TYPE_TO_OMS[typeof(T)]);
+        protected internal override SOMDoc SOMDocType(SOMDoc[] args, FUN.Param[] bound_params)
+            => SOMDocType(typeof(T));
 
         protected override bool EquivalentWrapped(OMC<T> sd2)
         {
@@ -639,7 +699,7 @@ public override string ToString()
         protected override OMC<T> MapURIsWrapped(Dictionary<string, string> old_to_new)
             => (OMC<T>)this.MemberwiseClone();
 
-        protected internal override Type ToType(Type[] args)
+        protected internal override Type ToType(Type[] args, (string name, Type type)[] bound_params)
             => typeof(T);
     }
 }
\ No newline at end of file
diff --git a/Assets/Scripts/Utility/Extensions/FuncExtensions.cs b/Assets/Scripts/Utility/Extensions/FuncExtensions.cs
index 46fc7828..7afa4caf 100644
--- a/Assets/Scripts/Utility/Extensions/FuncExtensions.cs
+++ b/Assets/Scripts/Utility/Extensions/FuncExtensions.cs
@@ -4,7 +4,7 @@
 
 public class FuncExtensions
 {
-    private static readonly Type[] GenericFuncTypes = new Type[]
+    public static readonly Type[] GenericFuncTypes = new Type[]
 {
     //typeof(Action),
     typeof(Func<>),
@@ -14,7 +14,16 @@ public class FuncExtensions
     typeof(Func<,,,,>),
     typeof(Func<,,,,,>),
     typeof(Func<,,,,,,>),
-    typeof(Func<,,,,,,,>)
+    typeof(Func<,,,,,,,>),
+    typeof(Func<,,,,,,,,>),
+    typeof(Func<,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,,,,,,>),
+    typeof(Func<,,,,,,,,,,,,,,,,>),
 };
 
     private static readonly IReadOnlyDictionary<Type, int> GenericFuncSignature =
diff --git a/Assets/Scripts/Utility/Extensions/TupleExtensions.cs b/Assets/Scripts/Utility/Extensions/TupleExtensions.cs
index 8847a7da..f6ad9157 100644
--- a/Assets/Scripts/Utility/Extensions/TupleExtensions.cs
+++ b/Assets/Scripts/Utility/Extensions/TupleExtensions.cs
@@ -2,7 +2,7 @@
 
 public static class TupleExtensions
 {
-    private static readonly Type[] GenericTupleTypes = new Type[]
+    public static readonly Type[] GenericTupleTypes = new Type[]
 {
     typeof(Tuple),
     typeof(Tuple<>),
@@ -17,4 +17,8 @@ public static class TupleExtensions
 
     public static Type GetGenericTupleType(int argumentsCount) 
         => GenericTupleTypes[argumentsCount];
+
+    public static Type CreateTupleType(Type[] signature)
+        => GetGenericTupleType(signature.Length)
+            .MakeGenericType(signature);
 }
\ No newline at end of file
-- 
GitLab