Beispiel #1
0
        static NestedText GenTypeTagBody(string typeName, string tagName, Signature tag)
        {
            var modifiedArgs = tag.Args
                               .Map(x => new Arg(
                                        name: x.Name == tagName ? $"{x.Name}Value" : x.Name, // TODO: move to normalizer
                                        type: x.Type,
                                        kind: x.Kind
                                        ))
                               .ToArr();
            var argsWithoutFlags = modifiedArgs
                                   .Filter(x => x.Kind.Match(_: () => true, flags: _ => false))
                                   .ToArr();
            var tagArgs = argsWithoutFlags
                          .Map(x => (
                                   name: x.Name,
                                   lowerName: Helpers.LowerFirst(x.Name),
                                   type: TgTypeConverter.ConvertArgType(x),
                                   isRef: TgTypeConverter.IsRefArgType(x)
                                   )).ToArray();

            return(Scope(
                       Scope(
                           Line($"internal const uint TypeNumber = {Helpers.TypeNumber(tag.TypeNumber)};"),
                           Line("[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]"),
                           Line("uint ITgTypeTag.TypeNumber => TypeNumber;"),
                           Line("")
                           ),
                       tagArgs.Map(arg => Line($"public readonly {arg.type} {arg.name};")).Scope(),
                       Line(""),
                       Scope(
                           Line($"public {tagName}("),
                           IndentedScope(1, $",{Environment.NewLine}",
                                         tagArgs.Map(arg => Line($"{arg.type} {arg.lowerName}"))
                                         ),
                           Line(") {"),
                           IndentedScope(1,
                                         tagArgs.Map(arg => Line(
                                                         $"{arg.name} = {arg.lowerName}" +
                                                         $"{(arg.isRef ? $" ?? throw new ArgumentNullException(nameof({arg.lowerName}))" : "")};"
                                                         ))
                                         ),
                           Line("}")
                           ),
                       Line(""),
                       WithGen.GenWith(argsWithoutFlags, tagName),
                       Line(""),
                       typeName != tagName ? Scope(
                           Line($"public static implicit operator {typeName}({tagName} tag) => new {typeName}(tag);"),
                           Line($"public static implicit operator Some<{typeName}>({tagName} tag) => new {typeName}(tag);"),
                           Line("")
                           ) : EmptyScope(),
                       RelationsGen.GenRelations(tagName, argsWithoutFlags),
                       Line(""),
                       Line(""),
                       SerializerGen.GenSerializer(modifiedArgs, typeNumber: None, "ITgTypeTag.SerializeTag"),
                       Line(""),
                       SerializerGen.GenTypeTagDeserialize(tagName, modifiedArgs)
                       ));
        }
Beispiel #2
0
        static NestedText GenFunc(Signature func, string funcName)
        {
            var argsWithoutFlags = func.Args
                                   .Filter(x => x.Kind.Match(_: () => true, flags: _ => false))
                                   .ToArr();
            var funcArgs = argsWithoutFlags
                           .Map(x => (
                                    name: x.Name,
                                    lowerName: Helpers.LowerFirst(x.Name),
                                    type: TgTypeConverter.ConvertArgType(x),
                                    isRef: TgTypeConverter.IsRefArgType(x)
                                    )).ToArray();

            // usually it is a higher-order function, i am too lazy to modify the scheme just for this case
            var isWrapper        = func.Args.Exists(x => x.Type == TgType.OfTypeRef("X") || x.Type == TgType.OfTypeRef("!X"));
            var resType          = isWrapper ? "TFuncRes" : TgTypeConverter.ConvertType(func.ResultType);
            var classAccess      = isWrapper ? "" : "public ";
            var classTemplates   = isWrapper ? "<TFunc, TFuncRes>" : "";
            var classAnnotations = isWrapper
                ? $": ITgFunc<{resType}> where TFunc : class, ITgFunc<{resType}>"
                : $": ITgFunc<{resType}>, IEquatable<{funcName}>, IComparable<{funcName}>, IComparable";

            var resDes = isWrapper
                ? "Query.DeserializeResult(br);" // it is 'Query' all the time, i am too lazy
                : Concat("Read(br, ", SerializerGen.GenTypeDeserializer(func.ResultType), ");");
            var resultDeserializer = Scope(
                Line($"{resType} ITgFunc<{resType}>.DeserializeResult(BinaryReader br) =>"),
                Indent(1, Line(resDes))
                );

            return(Scope(
                       Line($"{classAccess}sealed class {funcName}{classTemplates} {classAnnotations}"),
                       Line("{"),
                       IndentedScope(1,
                                     funcArgs.Map(arg => Line($"public {arg.type} {arg.name} {{ get; }}")).Scope(),
                                     Scope(
                                         Line(""),
                                         Scope(
                                             Line($"public {funcName}("),
                                             IndentedScope(1, $",{Environment.NewLine}",
                                                           funcArgs.Map(arg => Line($"{arg.type} {arg.lowerName}"))
                                                           ),
                                             Line(") {"),
                                             IndentedScope(1,
                                                           funcArgs.Map(arg => Line(
                                                                            $"{arg.name} = {arg.lowerName}" +
                                                                            $"{(arg.isRef ? $" ?? throw new ArgumentNullException(nameof({arg.lowerName}))" : "")};"
                                                                            ))
                                                           ),
                                             Line("}")
                                             ),
                                         Line(""),
                                         Line(""),
                                         isWrapper ? Scope(new NestedText[0]) : Scope(
                                             WithGen.GenWith(argsWithoutFlags, funcName),
                                             Line(""),
                                             RelationsGen.GenRelations(funcName, argsWithoutFlags),
                                             Line("")
                                             ),
                                         SerializerGen.GenSerializer(func.Args, typeNumber: func.TypeNumber, "ITgSerializable.Serialize"),
                                         Line(""),
                                         resultDeserializer
                                         )
                                     ),
                       Line("}")
                       ));
        }
Beispiel #3
0
        static NestedText GenTypeWithManyTags(string typeName, Arr <Signature> typeTags)
        {
            var tagsDefs = typeTags.Map(x => GenTypeTag(typeName, x)).Scope(Environment.NewLine + Environment.NewLine);

            var tagDef = Scope(
                Line("readonly ITgTypeTag _tag;"),
                Line($"{typeName}(ITgTypeTag tag) => _tag = tag ?? throw new ArgumentNullException(nameof(tag));")
                );

            var serializeRef = Scope(
                Line("void ITgSerializable.Serialize(BinaryWriter bw)"),
                Line("{"),
                IndentedScope(1,
                              Line("WriteUint(bw, _tag.TypeNumber);"),
                              Line("_tag.SerializeTag(bw);")
                              ),
                Line("}")
                );

            var staticTryDeserializeDef = Scope(
                Line($"internal static Option<{typeName}> TryDeserialize(uint typeNumber, BinaryReader br)"),
                Line("{"),
                IndentedScope(1,
                              Line("switch (typeNumber)"),
                              Line("{"),
                              IndentedScope(1,
                                            typeTags.Map(x => Line($"case {x.Name}.TypeNumber: return ({typeName}) {x.Name}.DeserializeTag(br);")).Scope(),
                                            Line("default: return Prelude.None;")
                                            ),
                              Line("}")
                              ),
                Line("}")
                );

            var staticDeserializeDef = Scope(
                Line($"internal static {typeName} Deserialize(BinaryReader br)"),
                Line("{"),
                IndentedScope(1,
                              Line("var typeNumber = ReadUint(br);"),
                              Line(Concat(
                                       "return TryDeserialize(typeNumber, br).IfNone(() => ",
                                       "throw TgRpcDeserializeException.UnexpectedTypeNumber(actual: typeNumber, expected: new[] { ",
                                       typeTags.Map(x => $"{x.Name}.TypeNumber").Map(String).Apply(xs => Join(", ", xs)),
                                       " })",
                                       ");"
                                       ))
                              ),
                Line("}")
                );

            var matchArgFns =
                typeTags.Map(tag => tag.Name).Map(tagName =>
                                                  $"Func<{tagName}, T>? {Helpers.LowerFirst(tagName)}"
                                                  );

            var matchOptDef = Scope(
                Line($"{(typeTags.Count <= 1 ? "" : "public ")}T Match<T>("),
                IndentedScope(1, $",{Environment.NewLine}",
                              Line("Func<T> _").Singleton(),
                              matchArgFns.Map(x => Concat(x, " = null")).Map(Line)
                              ),
                Line(") {"),
                IndentedScope(1,
                              Line("if (_ == null) throw new ArgumentNullException(nameof(_));"),
                              Line("switch (_tag)"),
                              Line("{"),
                              IndentedScope(1,
                                            typeTags.Map(tag =>
            {
                var tagName      = tag.Name;
                var tagNameLower = Helpers.LowerFirst(tagName);
                return(Line($"case {tagName} x when {tagNameLower} != null: return {tagNameLower}(x);"));
            }).Scope(),
                                            Line("default: return _();")
                                            ),
                              Line("}")
                              ),
                Line("}")
                );

            var matchDef = Scope(
                Line("public T Match<T>("),
                IndentedScope(1, $",{Environment.NewLine}", matchArgFns.Map(Line)),
                Line(") => Match("),
                IndentedScope(1, $",{Environment.NewLine}",
                              Line(@"() => throw new Exception(""WTF"")").Singleton(),
                              typeTags.Map(tag =>
            {
                var tagName      = tag.Name;
                var tagNameLower = Helpers.LowerFirst(tagName);
                return(Line($"{tagNameLower} ?? throw new ArgumentNullException(nameof({tagNameLower}))"));
            })
                              ),
                Line(");")
                );

            var castHelpersDef = Scope(
                typeTags.Map(tag => $"public Option<{tag.Name}> As{tag.Name}() => _tag is {tag.Name} x ? Prelude.Some(x) : Prelude.None;").Map(Line)
                );

            var staticCastHelpersDef = Scope(
                typeTags.Map(tag => $"public static Option<{tag.Name}> As{tag.Name}({typeName} type) => type.As{tag.Name}();").Map(Line)
                );

            var cmpPairName = String("CmpPair");
            var helpersDef  = Scope(
                Line("int GetTagOrder()"),
                Line("{"),
                IndentedScope(1,
                              Line("switch (_tag)"),
                              Line("{"),
                              IndentedScope(1,
                                            typeTags.Map((idx, x) => $"case {x.Name} _: return {idx};").Map(Line).Scope(),
                                            Line("default: throw new Exception(\"WTF\");")
                                            ),
                              Line("}")
                              ),
                Line("}"),
                Line("[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]"),
                Line(Concat("(int, object) ", cmpPairName, " => (GetTagOrder(), _tag);"))
                );

            var bodyDef = Scope(Environment.NewLine + Environment.NewLine,
                                tagsDefs,
                                tagDef,
                                serializeRef,
                                staticTryDeserializeDef,
                                staticDeserializeDef,
                                matchOptDef,
                                matchDef,
                                castHelpersDef,
                                staticCastHelpersDef,
                                helpersDef,
                                RelationsGen.GenEqRelations(typeName, cmpPairName),
                                RelationsGen.GenCmpRelations(typeName, cmpPairName),
                                RelationsGen.GenGetHashCode(cmpPairName),
                                RelationsGen.GenToString($"$\"{typeName}.{{_tag.GetType().Name}}{{_tag}}\"")
                                );

            var def = Scope(
                Line($"public sealed class {typeName} : ITgType, IEquatable<{typeName}>, IComparable<{typeName}>, IComparable"),
                Line("{"),
                Indent(1, bodyDef),
                Line("}")
                );

            return(def);
        }