Пример #1
0
 void AddFoldDocs(CodeTypeDeclaration type, CodeMemberMethod method, int n)
 {
     method.Comments.AddDocs(
         XmlDocs.TypeParam("TResult",
                           "  The type to convert the " + XmlDocs.See(DefaultNamespace, type) + " to."
                           ),
         GetFoldParametersDocs(type, n),
         XmlDocs.Summary(
             "  Converts a " + XmlDocs.See(DefaultNamespace, type) + " into a <typeparamref name=\"TResult\" /> value."
             ),
         XmlDocs.Returns(
             "  A <typeparamref name=\"TResult\" /> as generated by one",
             "  of the conversion delegate parameters."
             ),
         XmlDocs.Remarks(
             "  <para>",
             "   Converts a " + XmlDocs.See(DefaultNamespace, type) + " into a <typeparamref name=\"TResult\" />",
             "   by invoking one of the provided delegate parameters.",
             "  </para>",
             "  <para>",
             "   The parameter which is invoked is predicated upon the internal position of",
             "   the value held.  For example, if the internal value is in the first position ",
             "   (i.e. " + XmlDocs.See(DefaultNamespace, type, type.GetMethods(A(0)).First()),
             "   was used to create the " + XmlDocs.See(DefaultNamespace, type) + " instance), then",
             "   <paramref name=\"a\" /> (the first delegate parameter) will be invoked to",
             "   convert the <typeparamref name=\"T1\" /> into a ",
             "   <typeparamref name=\"TResult\" />.",
             "  </para>"
             ),
         XmlDocs.ArgumentNullException(Enumerable.Range(0, n).Select(v => a(v)))
         );
 }
Пример #2
0
        CodeMemberMethod CreateAggregateMethod(int n)
        {
            var retType = new CodeTypeReference("TResult");
            var m       = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "Aggregate",
                ReturnType = retType,
            };

            for (int i = 0; i < n; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n, i));
            }
            m.TypeParameters.Add("TResult");

            var selfType = new CodeTypeReference("this Tuple", Types.GetTypeParameterReferences(n, false).ToArray());

            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));

            var funcType = Types.Func(n);

            m.Parameters.Add(new CodeParameterDeclarationExpression(funcType, "func"));

            m.Statements.AddCheck("Self", "self");
            m.Statements.AddCheck("Func", "func");
            m.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeDelegateInvokeExpression(
                        new CodeVariableReferenceExpression("func"),
                        Enumerable.Range(0, n).Select(p =>
                                                      new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("self"), Tuple.Item(n, p))).ToArray())));

            var tref  = "<see cref=\"T:Cadenza.Tuple{" + Types.GetTypeParameterList(n) + "}\" />";
            var props = string.Join(", ",
                                    Enumerable.Range(0, n).Select(p => "<see cref=\"P:Cadenza.Tuple`" + n + "." + Tuple.Item(n, p) + "\"/>").ToArray());

            m.Comments.AddDocs(
                XmlDocs.TypeParams(m.TypeParameters),
                XmlDocs.Param("self", "A " + tref + " to aggregate the values of."),
                XmlDocs.Param("func",
                              "A " + XmlDocs.See(funcType) + " which will be invoked, providing the values",
                              props,
                              "to <paramref name=\"func\"/> and ",
                              "returning the value returned by <paramref name=\"func\"/>."),
                XmlDocs.Summary(
                    "Converts the " + tref + " into a <typeparamref name=\"TResult\"/>."),
                XmlDocs.Returns(
                    "The <typeparamref name=\"TResult\"/> returned by <paramref name=\"func\"/>."),
                XmlDocs.Remarks(
                    "<para>",
                    " <block subset=\"none\" type=\"behaviors\">",
                    "  Passes the values " + props + " to ",
                    "  <paramref name=\"func\"/>, returning the value produced by ",
                    "  <paramref name=\"func\"/>.",
                    " </block>",
                    "</para>"),
                XmlDocs.ArgumentNullException(new[] { "self", "func" }));
            return(m);
        }
Пример #3
0
        void AddCreatorDocs(CodeTypeDeclaration type, CodeMemberMethod method, int w, int n)
        {
            var tp   = Types.GetTypeParameter(n, w);
            var idx  = XmlDocs.GetIndex(tp);
            var fold = type.GetMethods("Fold").First();

            method.Comments.AddDocs(
                XmlDocs.Param("value",
                              "  A <typeparamref name=\"" + tp + "\" /> containing the value",
                              "  to provide to the " + idx,
                              "  " + XmlDocs.See(DefaultNamespace, type, fold),
                              "  delegate."
                              ),
                XmlDocs.Summary(
                    "  Creates a " + XmlDocs.See(DefaultNamespace, type) + " instance which",
                    "  holds a <typeparamref name=\"" + tp + "\" /> value."
                    ),
                XmlDocs.Returns(
                    "  A " + XmlDocs.See(DefaultNamespace, type) + " instance which holds a ",
                    "  holds a <typeparamref name=\"" + tp + "\" /> value."
                    ),
                XmlDocs.Remarks(
                    "  <para>",
                    "   When",
                    "   " + XmlDocs.See(DefaultNamespace, type, fold),
                    "   is invoked,",
                    "   the returned " + XmlDocs.See(DefaultNamespace, type) + " instance",
                    "   will invoke the " + idx + " delegate",
                    "   for conversions.",
                    "  </para>"
                    ),
                XmlDocs.ArgumentNullException("value")
                );
        }
Пример #4
0
        protected static CodeMemberMethod CreateComposeMethod(Func <int, int, int, CodeTypeReference> getSelfType, Func <int, int, int, CodeTypeReference> getRetType, int n, bool tret)
        {
            var selfType = getSelfType(n + 1, n, 1);
            var retType  = getRetType(n + 1, 0, n);
            var m        = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "Compose",
                ReturnType = retType,
            };

            for (int i = 0; i < n + 1; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n + 1, i));
            }
            if (tret)
            {
                m.TypeParameters.Add("TResult");
            }
            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));
            var composerType = new CodeTypeReference(
                Types.FuncType(n),
                Types.GetTypeParameterReferences(n + 1, 0, n + 1, false).ToArray());

            m.Parameters.Add(new CodeParameterDeclarationExpression(composerType, "composer"));
            m.Statements.AddCheck("Self", "self");
            m.Statements.AddCheck("Composer", "composer");
            var expr = new StringBuilder().Append("(");

            Values(expr, n, 0, n);
            expr.Append(") => self (composer (");
            Values(expr, n, 0, n);
            expr.Append("))");
            m.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(expr.ToString())));
            m.Comments.AddDocs(
                GetComposeTypeParameters(n, selfType, composerType, tret),
                XmlDocs.Summary("Creates a " + XmlDocs.See(retType) + " delegate."),
                XmlDocs.Param("self", "The " + XmlDocs.See(selfType) + " to compose."),
                XmlDocs.Param("composer", "The " + XmlDocs.See(composerType) + " to compose with <paramref name=\"self\" />."),
                XmlDocs.Returns(
                    "Returns a " + XmlDocs.See(retType) + " which, when invoked, will",
                    "invoke <paramref name=\"composer\"/> and pass the return value of",
                    "<paramref name=\"composer\" /> to <paramref name=\"self\" />."),
                XmlDocs.Remarks(
                    "<para>",
                    " Composition is useful for chaining delegates together, so that the",
                    " return value of <paramref name=\"composer\" /> is automatically used as",
                    " the input parameter for <paramref name=\"self\" />.",
                    "</para>",
                    "<code lang=\"C#\">",
                    "Func&lt;int,string> tostring = Lambda.F ((int n) => n.ToString ());",
                    "Func&lt;int, int>    doubler = Lambda.F ((int n) => n * 2);",
                    "Func&lt;int, string>",
                    "     double_then_tostring = tostring.Compose (doubler);",
                    "Console.WriteLine (double_then_tostring (5));",
                    "    // Prints \"10\";</code>"),
                XmlDocs.ArgumentNullException(new[] { "self", "composer" }));
            return(m);
        }
Пример #5
0
        protected static CodeMemberMethod CreateCurryTupleMethod(Func <int, int, CodeTypeReference> getSelfType, Func <int, int, CodeTypeReference> getRetType, int n, int a, bool tret)
        {
            var selfType = getSelfType(n, 0);
            var retType  = getRetType(n, a);
            var m        = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "Curry",
                ReturnType = retType,
            };

            for (int i = 0; i < n; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n, i));
            }
            if (tret)
            {
                m.TypeParameters.Add("TResult");
            }
            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));
            var valuesType =
                new CodeTypeReference("Tuple", Types.GetTypeParameterReferences(n, 0, a, false).ToArray());

            m.Parameters.Add(new CodeParameterDeclarationExpression(valuesType, "values"));
            m.Statements.AddCheck("Self", "self");
            var expr = new StringBuilder().Append("(");

            Values(expr, n, a, n);
            expr.Append(") => self (values.Item1");
            for (int i = 1; i < a; ++i)
            {
                expr.Append(", ").Append("values.Item" + (i + 1));
            }
            if (a < n)
            {
                expr.Append(", ");
                Values(expr, n, a, n);
            }
            expr.Append(")");
            m.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(expr.ToString())));

            m.Comments.AddDocs(
                GetTypeParameters(n, selfType),
                XmlDocs.Summary("Creates a " + XmlDocs.See(retType) + " delegate."),
                XmlDocs.Param("self", "The " + XmlDocs.See(selfType) + " to curry."),
                XmlDocs.Param("values", "A value of type " + XmlDocs.See(valuesType) + " which contains the values to fix."),
                XmlDocs.Returns(
                    "Returns a " + XmlDocs.See(retType) + " which, when invoked, will",
                    "invoke <paramref name=\"self\"/> along with the provided fixed parameters."),
                XmlDocs.ArgumentNullException("self"));
            return(m);
        }
Пример #6
0
        CodeMemberMethod CreateToEnumerableMethod(int n)
        {
            var retType = new CodeTypeReference("System.Collections.Generic.IEnumerable", new CodeTypeReference(typeof(object)));
            var m       = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "ToEnumerable",
                ReturnType = retType,
            };

            for (int i = 0; i < n; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n, i));
            }

            var selfType = new CodeTypeReference("this Tuple", Types.GetTypeParameterReferences(n, false).ToArray());

            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));

            m.Statements.AddCheck("Self", "self");
            m.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(new CodeTypeReferenceExpression("TupleCoda"), "CreateToEnumerableIterator"),
                        new CodeVariableReferenceExpression("self"))));

            var tref  = "<see cref=\"T:Cadenza.Tuple{" + Types.GetTypeParameterList(n) + "}\" />";
            var props = string.Join(", ",
                                    Enumerable.Range(0, n).Select(p => "<see cref=\"P:Cadenza.Tuple`" + n + "." + Tuple.Item(n, p) + "\"/>").ToArray());

            m.Comments.AddDocs(
                XmlDocs.TypeParams(m.TypeParameters),
                XmlDocs.Param("self", "A " + tref + " to convert into an <see cref=\"T:System.Collections.Generic.IEnumerable{System.Object}\"/>."),
                XmlDocs.Summary(
                    "Converts the " + tref + " into a <see cref=\"T:System.Collections.Generic.IEnumerable{System.Object}\"/>."),
                XmlDocs.Returns(
                    "A <see cref=\"T:System.Collections.Generic.IEnumerable{System.Object}\"/>."),
                XmlDocs.Remarks(
                    "<para>",
                    " <block subset=\"none\" type=\"behaviors\">",
                    "  Passes the values " + props + " to ",
                    "  <paramref name=\"func\"/>, returning the value produced by ",
                    "  <paramref name=\"func\"/>.",
                    " </block>",
                    "</para>"),
                XmlDocs.ArgumentNullException("self"));
            return(m);
        }
Пример #7
0
        protected static CodeMemberMethod CreateCurryMethod(Func <int, int, CodeTypeReference> getSelfType, Func <int, int, CodeTypeReference> getRetType, int n, int a, bool tret)
        {
            var selfType = getSelfType(n, 0);
            var retType  = getRetType(n, a);
            var m        = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "Curry",
                ReturnType = retType,
            };

            for (int i = 0; i < n; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n, i));
            }
            if (tret)
            {
                m.TypeParameters.Add("TResult");
            }
            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));
            for (int i = 0; i < a; ++i)
            {
                m.Parameters.Add(new CodeParameterDeclarationExpression(Types.GetTypeParameter(n, i), Value(n, i)));
            }
            m.Statements.AddCheck("Self", "self");
            var expr = new StringBuilder().Append("(");

            Values(expr, n, a, n);
            expr.Append(") => self (");
            Values(expr, n, 0, n);
            expr.Append(")");
            m.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(expr.ToString())));

            m.Comments.AddDocs(
                GetTypeParameters(n, selfType),
                XmlDocs.Summary("Creates a " + XmlDocs.See(retType) + " delegate."),
                XmlDocs.Param("self", "The " + XmlDocs.See(selfType) + " to curry."),
                Enumerable.Range(0, a).Select(p => XmlDocs.Param(Value(n, p),
                                                                 "A value of type <typeparamref name=\"" + Types.GetTypeParameter(n, p) + "\"/> to fix.")),
                XmlDocs.Returns(
                    "Returns a " + XmlDocs.See(retType) + " which, when invoked, will",
                    "invoke <paramref name=\"self\"/> along with the provided fixed parameters."),
                XmlDocs.ArgumentNullException("self"));
            return(m);
        }
Пример #8
0
        static CodeMemberMethod RecFunc(int args)
        {
            var t = Types.Func(args);
            var m = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Static | MemberAttributes.Public,
                Name       = "RecFunc",
                ReturnType = t,
            };

            m.TypeParameters.AddRange(Types.GetTypeParameters(args, true).ToArray());
            var a = "lambda";

            m.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference("Func", t, t), a));
            m.Statements.ThrowWhenArgumentIsNull(a);
            var expr = AppendArgs(new StringBuilder(), args);

            expr.Append(" => lambda (RecFunc (lambda))");
            AppendArgs(expr, args);
            m.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(expr.ToString())));
            m.Comments.AddRange("From: http://blogs.msdn.com/madst/archive/2007/05/11/recursive-lambda-expressions.aspx");
            m.Comments.AddDocs(
                XmlDocs.TypeParams(m.TypeParameters, t),
                XmlDocs.Param("lambda", "The " + XmlDocs.See(t) + " to use."),
                XmlDocs.Summary("Creates a " + XmlDocs.See(t) + " delegate, which may be recursive."),
                XmlDocs.Returns("Returns a " + XmlDocs.See(t) + " which (eventually) invokes <paramref name=\"lambda\"/>."),
                XmlDocs.ArgumentNullException("lambda"),
                XmlDocs.Remarks(
                    "<para>",
                    "  The following example makes use of a recursive lambda:",
                    "</para>",
                    "<code lang=\"C#\">",
                    "  Func<int, int> factorial = Lambda.RecFunc<int, int> (".Replace("<", "&lt;"),
                    "      fac => x => x == 0 ? 1 : x * fac (x-1));",
                    "  Console.WriteLine (factorial (5));  // prints \"120\"",
                    "</code>"
                    )
                );
            return(m);
        }
Пример #9
0
        CodeMemberMethod CreateMatchMethod(int n)
        {
            var retType = new CodeTypeReference("TResult");
            var m       = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "Match",
                ReturnType = retType,
            };

            for (int i = 0; i < n; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n, i));
            }
            m.TypeParameters.Add("TResult");

            var selfType = new CodeTypeReference("this Tuple", Types.GetTypeParameterReferences(n, false).ToArray());

            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));

            var matchersType = new CodeTypeReference(
                new CodeTypeReference(Types.FuncType(n),
                                      Types.GetTypeParameterReferences(n, false)
                                      .Concat(new[] { new CodeTypeReference("Cadenza.Maybe", new[] { new CodeTypeReference("TResult") }) })
                                      .ToArray()),
                1);
            var matchersParam = new CodeParameterDeclarationExpression(matchersType, "matchers");

            matchersParam.CustomAttributes.Add(new CodeAttributeDeclaration("System.ParamArrayAttribute"));
            m.Parameters.Add(matchersParam);

            m.Statements.AddCheck("Self", "self");
            m.Statements.ThrowWhenArgumentIsNull("matchers");

            var loop = new StringBuilder();

            loop.Append("            foreach (var m in matchers) {\n");
            loop.Append("              var r = m (self.Item1");
            for (int i = 1; i < n; ++i)
            {
                loop.Append(", self.").Append(Tuple.Item(n, i));
            }
            loop.Append(");\n");
            loop.Append("              if (r.HasValue)\n");
            loop.Append("                return r.Value;\n");
            loop.Append("            }");
            m.Statements.Add(new CodeSnippetStatement(loop.ToString()));
            m.Statements.Add(
                new CodeThrowExceptionStatement(
                    new CodeObjectCreateExpression(
                        new CodeTypeReference("System.InvalidOperationException"),
                        new CodePrimitiveExpression("no match"))));

            var fref = "<see cref=\"T:System.Func{" + Types.GetTypeParameterList(n) + ",Cadenza.Maybe{TResult}}\" />";
            var tref = "<see cref=\"T:Cadenza.Tuple{" + Types.GetTypeParameterList(n) + "}\" />";

            m.Comments.AddDocs(
                XmlDocs.TypeParams(m.TypeParameters),
                XmlDocs.Param("self", "A " + tref + " to match against."),
                XmlDocs.Param("matchers", "A " + fref,
                              "array containing the conversion routines to use to convert ",
                              "the current " + tref + " instance into a ",
                              "<typeparamref name=\"TResult\" /> value."),
                XmlDocs.Summary(
                    "Converts the current " + tref + " instance into a <typeparamref name=\"TResult\"/>."),
                XmlDocs.Returns(
                    "The <typeparamref name=\"TResult\"/> returned by one of the <paramref name=\"matchers\"/>."),
                XmlDocs.Remarks(
                    "<para>",
                    " <block subset=\"none\" type=\"behaviors\">",
                    "  <para>",
                    "   The current " + tref + " instance is converted into a ",
                    "   <typeparamref name=\"TResult\" /> instance by trying each",
                    "   " + fref,
                    "   within <paramref name=\"matchers\" />.",
                    "  </para>",
                    "  <para>",
                    "   This method returns ",
                    "   <see cref=\"P:Cadenza.Maybe{TResult}.Value\" /> ",
                    "   for the first delegate to return a",
                    "   <see cref=\"T:Cadenza.Maybe{TResult}\" /> instance",
                    "   where <see cref=\"P:Cadenza.Maybe{TResult}.HasValue\" />",
                    "   is <see langword=\"true\" />.",
                    "  </para>",
                    "  <para>",
                    "   If no " + fref,
                    "   returns a ",
                    "   <see cref=\"T:Cadenza.Maybe{TResult}\" /> instance",
                    "   where <see cref=\"P:Cadenza.Maybe{TResult}.HasValue\" />",
                    "   is <see langword=\"true\" />, then an",
                    "   <see cref=\"T:System.InvalidOperationException\" /> is thrown.",
                    "  </para>",
                    " </block>",
                    " <code lang=\"C#\">",
                    "var    a = Tuple.Create (1, 2);",
                    "string b = a.Match (",
                    "    (t, v) =&gt; Match.When ( t + v == 3, \"foo!\"),",
                    "    (t, v) =&gt; \"*default*\".Just ());",
                    "Console.WriteLine (b);  // prints \"foo!\"</code>",
                    "</para>"),
                XmlDocs.ArgumentNullException(new[] { "self", "matchers" }),
                XmlDocs.Exception(typeof(InvalidOperationException),
                                  "None of the ",
                                  "<see cref=\"T:System.Func{TSource,Cadenza.Maybe{TResult}}\" />",
                                  "delegates within <paramref name=\"matchers\" /> returned a ",
                                  "<see cref=\"T:Cadenza.Maybe{TResult}\" /> instance where",
                                  "<see cref=\"P:Cadenza.Maybe{TResult}.HasValue\" /> was",
                                  "<see langword=\"true\" />."));
            return(m);
        }
Пример #10
0
        CodeMemberMethod AddTimingsDocs(CodeMemberMethod m, int n, CodeTypeDeclaration t, CodeMemberMethod full)
        {
            m.Comments.AddDocs(
                GetTypeParameters(n, m.Parameters [0].Type),
                XmlDocs.Summary("Get timing information for delegate invocations."),
                XmlDocs.Param("self", "The " + XmlDocs.See(m.Parameters [0].Type) + " to generate timings for."),
                GetTimingsParameters(n),
                XmlDocs.Param("runs", "An <see cref=\"T:System.Int32\" /> containing the number of <see cref=\"T:System.TimeSpan\" /> values to return."),
                full == null
                                                ? XmlDocs.Param("loopsPerRun",
                                                                "An <see cref=\"T:System.Int32\" /> containing the number of " +
                                                                "times to invoke <paramref name=\"self\" /> for each " +
                                                                "<see cref=\"T:System.TimeSpan\" /> value returned.")
                                                : new[] { "" },
                XmlDocs.Returns(
                    "An " + XmlDocs.See(m.ReturnType),
                    "which will return the timing information for <paramref name=\"self\" />."));
            if (full != null)
            {
                var alt = new StringBuilder().Append("self.Timing (");
                Values(alt, n, 0, n);
                if (n > 0)
                {
                    alt.Append(", ");
                }
                alt.Append("runs, 1)");
                m.Comments.AddDocs(
                    XmlDocs.Remarks(
                        "<para>",
                        " This is equivalent to calling",
                        " " + XmlDocs.See(DefaultNamespace, t, full),
                        " with a <paramref name=\"loopsPerRun\" /> value of <c>1</c>,",
                        " e.g. as if by calling <c>" + alt.ToString() + "</c>.",
                        "</para>"),
                    "<seealso cref=\"" + XmlDocs.Cref(DefaultNamespace, t, full) + "\" />");
            }
            else
            {
                m.Comments.AddDocs(XmlDocs.Remarks(
                                       "<para>",
                                       " Generates <paramref name=\"runs\" /> <see cref=\"T:System.TimeSpan\" />",
                                       " instances, in which each <c>TimeSpan</c> instance is the amount of time",
                                       " required to execute <paramref name=\"self\" /> for",
                                       " <paramref name=\"loopsPerRun\" /> times.",
                                       "</para>"));
            }
            m.Comments.AddDocs(
                XmlDocs.Exception(typeof(ArgumentException),
                                  "<para>",
                                  " <paramref name=\"runs\" /> is negative.",
                                  "</para>",
                                  full != null ? new object[0] : new object[] {
                "<para>-or-</para>",
                "<para>",
                " <paramref name=\"loopsPerRun\" /> is negative.",
                "</para>"
            }),
                XmlDocs.ArgumentNullException("self"));

            return(m);
        }
Пример #11
0
        protected static CodeMemberMethod CreateTraditionalCurryMethod(Func <int, int, CodeTypeReference> getSelfType, Func <int, int, CodeTypeReference> getRetType, int n, bool tret)
        {
            var selfType = getSelfType(n, 0);
            var retType  = getRetType(n, n - 1);

            for (int i = n - 2; i >= 0; --i)
            {
                retType = new CodeTypeReference("System.Func", new CodeTypeReference(Types.GetTypeParameter(n, i)), retType);
            }
            var m = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "Curry",
                ReturnType = retType,
            };

            for (int i = 0; i < n; ++i)
            {
                m.TypeParameters.Add(Types.GetTypeParameter(n, i));
            }
            if (tret)
            {
                m.TypeParameters.Add("TResult");
            }
            m.Parameters.Add(new CodeParameterDeclarationExpression(selfType, "self"));
            m.Statements.AddCheck("Self", "self");
            var expr = new StringBuilder();

            for (int i = 0; i < n; ++i)
            {
                expr.Append(Value(n, i)).Append(" => ");
            }
            expr.Append("self (");
            Values(expr, n, 0, n);
            expr.Append(")");
            m.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(expr.ToString())));
            var retDocs = new StringBuilder();

            if (retType.TypeArguments.Count > 1)
            {
                var rt = retType.TypeArguments [1];
                while (rt != null && rt.TypeArguments.Count > 1)
                {
                    retDocs.Append("return a ").Append(XmlDocs.See(rt)).Append(" which, when invoked, will ");
                    rt = rt.TypeArguments [1];
                }
                if (rt.TypeArguments.Count > 0)
                {
                    retDocs.Append("return a ").Append(XmlDocs.See(rt)).Append(" which, when invoked, will ");
                }
            }
            m.Comments.Add(new CodeCommentStatement("Currying method idea courtesy of:"));
            m.Comments.Add(new CodeCommentStatement("http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx"));
            m.Comments.AddDocs(
                XmlDocs.TypeParams(m.TypeParameters),
                XmlDocs.Param("self", "The " + XmlDocs.See(selfType) + " to curry."),
                XmlDocs.Summary("Creates a " + XmlDocs.See(retType) + " for currying."),
                XmlDocs.Returns(
                    "A " + XmlDocs.See(retType) + " which, when invoked, will ",
                    retDocs.ToString(),
                    "invoke <paramref name=\"self\"/>."),
                XmlDocs.Remarks(
                    "<para>",
                    " This is the more \"traditional\" view of currying, turning a method",
                    " which takes <c>(X * Y)-&gt;Z</c> (i.e. separate arguments) into a",
                    " <c>X -&gt; (Y -&gt; Z)</c> (that is a \"chain\" of nested Funcs such that",
                    " you provide only one argument to each Func until you provide enough",
                    " arguments to invoke the original method).",
                    "</para>",
                    "<code lang=\"C#\">",
                    "Func&lt;int,int,int,int&gt; function = (int a, int b, int c) =&gt; a + b + c;",
                    "Func&lt;int,Func&lt;int,Func&lt;int, int&gt;&gt;&gt; curry = function.Curry ();",
                    "Assert.AreEqual(6, curry (3)(2)(1));</code>"),
                XmlDocs.ArgumentNullException("self"));
            return(m);
        }