コード例 #1
0
        public static void GenTypeAttributeTest(AssemblyGen ag)
        {
            TypeGen MyAttribute = ag.Public.Class("MyAttribute", typeof(Attribute))
                                  .BeginAttribute <AttributeUsageAttribute>(AttributeTargets.Class).Set("AllowMultiple", true).End();

            FieldGen testField = MyAttribute.Field <object>("testField")
                                 .Attribute <DescriptionAttribute>("Test field");

            PropertyGen testProperty = MyAttribute.Public.SimpleProperty(testField, "TestProperty")
                                       .Attribute <ObsoleteAttribute>("Do not use this");

            testProperty.Getter().Attribute <DescriptionAttribute>("Getter method");
            testProperty.Getter().ReturnParameter.Attribute <DescriptionAttribute>("Getter return value");
            testProperty.Setter().Attribute <DescriptionAttribute>("Setter method");

            TypeGen tg = ag.Class("Test")
                         .BeginAttribute(MyAttribute).Set("TestProperty", 3).End()
                         .Attribute <DescriptionAttribute>("Test class");

            tg.Static.Void("Main")
            .BeginAttribute(MyAttribute).Set("TestProperty", 3).End();

            TypeGen SimpleDelegate = ag.DelegateVoid("SimpleDelegate")
                                     .Attribute <DescriptionAttribute>("Test delegate");

            EventGen TestEvent = tg.Static.Event(SimpleDelegate, "TestEvent")
                                 .Attribute <DescriptionAttribute>("Test event");

            TestEvent.AddMethod().Attribute <DescriptionAttribute>("Event add method");
            TestEvent.RemoveMethod().Attribute <DescriptionAttribute>("Event remove method");
        }
コード例 #2
0
ファイル: 07_Structs.cs プロジェクト: smartcaveman/runsharp
        // example based on the MSDN Structs Sample (struct1.cs)
        public static void GenStruct1(AssemblyGen ag)
        {
            var st  = ag.StaticFactory;
            var exp = ag.ExpressionFactory;

            CodeGen g;

            TypeGen SimpleStruct = ag.Struct("SimpleStruct");
            {
                FieldGen xval = SimpleStruct.Field(typeof(int), "xval");

                PropertyGen X = SimpleStruct.Public.Property(typeof(int), "X");
                {
                    X.Getter().GetCode().Return(xval);
                    g = X.Setter();
                    {
                        g.If(g.PropertyValue() < 100);
                        {
                            g.Assign(xval, g.PropertyValue());
                        }
                        g.End();
                    }
                }

                g = SimpleStruct.Public.Method(typeof(void), "DisplayX");
                {
                    g.WriteLine("The stored value is: {0}", xval);
                }
            }

            TypeGen TestClass = ag.Class("TestClass");
            {
                g = TestClass.Public.Static.Method(typeof(void), "Main");
                {
                    var ss = g.Local(SimpleStruct);
                    g.InitObj(ss);
                    ITypeMapper typeMapper = ag.TypeMapper;
                    g.Assign(ss.Property("X"), 5);
                    g.Invoke(ss, "DisplayX");
                }
            }
        }
コード例 #3
0
ファイル: 07_Structs.cs プロジェクト: ectacoh/RunSharp
        // example based on the MSDN Structs Sample (struct1.cs)
        public static void GenStruct1(AssemblyGen ag)
        {
            CodeGen g;

            TypeGen SimpleStruct = ag.Struct("SimpleStruct");
            {
                FieldGen xval = SimpleStruct.Field <int>("xval");

                PropertyGen X = SimpleStruct.Public.Property <int>("X");
                {
                    X.Getter().GetCode().Return(xval);
                    g = X.Setter();
                    {
                        g.If(g.PropertyValue() < 100);
                        {
                            g.Assign(xval, g.PropertyValue());
                        }
                        g.End();
                    }
                }

                g = SimpleStruct.Public.Void("DisplayX");
                {
                    g.WriteLine("The stored value is: {0}", xval);
                }
            }

            TypeGen TestClass = ag.Class("TestClass");
            {
                g = TestClass.Public.Static.Void("Main");
                {
                    Operand ss = g.Local(SimpleStruct);
                    g.InitObj(ss);
                    g.Assign(ss.Property("X"), 5);
                    g.Invoke(ss, "DisplayX");
                }
            }
        }
コード例 #4
0
        // example based on the MSDN Indexed Properties Sample (indexedproperty.cs)
        public static void GenIndexedProperty(AssemblyGen ag)
        {
            var st  = ag.StaticFactory;
            var exp = ag.ExpressionFactory;

            CodeGen     g;
            ITypeMapper m = ag.TypeMapper;

            TypeGen Document = ag.Public.Class("Document");
            {
                FieldGen TextArray = Document.Private.Field(typeof(char[]), "TextArray");                  // The text of the document.

                // Type allowing the document to be viewed like an array of words:
                TypeGen WordCollection = Document.Public.Class("WordCollection");
                {
                    FieldGen document           = WordCollection.ReadOnly.Field(Document, "document"); // The containing document
                    var      document_TextArray = document.Field("TextArray", m);                      // example of a saved expression - it is always re-evaluated when used

                    g = WordCollection.Internal.Constructor().Parameter(Document, "d");
                    {
                        g.Assign(document, g.Arg("d"));
                    }

                    // Helper function -- search character array "text", starting at
                    // character "begin", for word number "wordCount." Returns false
                    // if there are less than wordCount words.Sets "start" and
                    // length" to the position and length of the word within text:
                    g = WordCollection.Private.Method(typeof(bool), "GetWord")
                        .Parameter(typeof(char[]), "text")
                        .Parameter(typeof(int), "begin")
                        .Parameter(typeof(int), "wordCount")
                        .Out.Parameter(typeof(int), "start")
                        .Out.Parameter(typeof(int), "length")
                    ;
                    {
                        ContextualOperand text = g.Arg("text"), begin = g.Arg("begin"), wordCount = g.Arg("wordCount"),
                                          start = g.Arg("start"), length = g.Arg("length");

                        var end = g.Local(text.ArrayLength());
                        var count = g.Local(0);
                        var inWord = g.Local(-1);
                        g.Assign(start, length.Assign(0));

                        var i = g.Local();
                        g.For(i.Assign(begin), i <= end, i.Increment());
                        {
                            var isLetter = g.Local(i < end && st.Invoke(typeof(char), "IsLetterOrDigit", text[i]));

                            g.If(inWord >= 0);
                            {
                                g.If(!isLetter);
                                {
                                    g.If(count.PostIncrement() == wordCount);
                                    {
                                        g.Assign(start, inWord);
                                        g.Assign(length, i - inWord);
                                        g.Return(true);
                                    }
                                    g.End();

                                    g.Assign(inWord, -1);
                                }
                                g.End();
                            }
                            g.Else();
                            {
                                g.If(isLetter);
                                {
                                    g.Assign(inWord, i);
                                }
                                g.End();
                            }
                            g.End();
                        }
                        g.End();

                        g.Return(false);
                    }

                    // Indexer to get and set words of the containing document:
                    PropertyGen Item = WordCollection.Public.Indexer(typeof(string)).Index(typeof(int), "index");
                    {
                        g = Item.Getter();
                        {
                            var index = g.Arg("index");

                            var start  = g.Local(0);
                            var length = g.Local(0);

                            g.If(g.This().Invoke("GetWord", document_TextArray, 0, index, start.Ref(), length.Ref()));
                            {
                                g.Return(exp.New(typeof(string), document_TextArray, start, length));
                            }
                            g.Else();
                            {
                                g.Throw(exp.New(typeof(IndexOutOfRangeException)));
                            }
                            g.End();
                        }
                        g = Item.Setter();
                        {
                            var index = g.Arg("index");
                            var value = g.PropertyValue();

                            var start  = g.Local(0);
                            var length = g.Local(0);

                            g.If(g.This().Invoke("GetWord", document_TextArray, 0, index, start.Ref(), length.Ref()));
                            {
                                // Replace the word at start/length with the
                                // string "value":
                                g.If(length == value.Property("Length"));
                                {
                                    g.Invoke(typeof(Array), "Copy", value.Invoke("ToCharArray"), 0,
                                             document_TextArray, start, length);
                                }
                                g.Else();
                                {
                                    var newText = g.Local(exp.NewArray(typeof(char),
                                                                       document_TextArray.ArrayLength() + value.Property("Length") - length));

                                    g.Invoke(typeof(Array), "Copy", document_TextArray, 0, newText,
                                             0, start);
                                    g.Invoke(typeof(Array), "Copy", value.Invoke("ToCharArray"), 0, newText,
                                             start, value.Property("Length"));
                                    g.Invoke(typeof(Array), "Copy", document_TextArray, start + length,
                                             newText, start + value.Property("Length"),
                                             document_TextArray.ArrayLength() - start
                                             - length);
                                    g.Assign(document_TextArray, newText);
                                }
                                g.End();
                            }
                            g.Else();
                            {
                                g.Throw(exp.New(typeof(IndexOutOfRangeException)));
                            }
                            g.End();
                        }
                    }

                    // Get the count of words in the containing document:
                    g = WordCollection.Public.Property(typeof(int), "Count").Getter();
                    {
                        ContextualOperand count = g.Local(0), start = g.Local(0), length = g.Local(0);

                        g.While(g.This().Invoke("GetWord", document_TextArray, start + length, 0, start.Ref(), length.Ref()));
                        {
                            g.Increment(count);
                        }
                        g.End();

                        g.Return(count);
                    }
                }

                // Type allowing the document to be viewed like an "array"
                // of characters:
                TypeGen CharacterCollection = Document.Public.Class("CharacterCollection");
                {
                    FieldGen document           = CharacterCollection.ReadOnly.Field(Document, "document");             // The containing document
                    var      document_TextArray = document.Field("TextArray", m);

                    g = CharacterCollection.Internal.Constructor().Parameter(Document, "d");
                    {
                        g.Assign(document, g.Arg("d"));
                    }

                    // Indexer to get and set characters in the containing document:
                    PropertyGen Item = CharacterCollection.Public.Indexer(typeof(char)).Index(typeof(int), "index");
                    {
                        g = Item.Getter();
                        {
                            g.Return(document_TextArray[g.Arg("index")]);
                        }
                        g = Item.Setter();
                        {
                            g.Assign(document_TextArray[g.Arg("index")], g.PropertyValue());
                        }
                    }

                    // Get the count of characters in the containing document:
                    g = CharacterCollection.Public.Property(typeof(int), "Count").Getter();
                    {
                        g.Return(document_TextArray.ArrayLength());
                    }
                }

                // Because the types of the fields have indexers,
                // these fields appear as "indexed properties":
                FieldGen Words      = Document.Public.ReadOnly.Field(WordCollection, "Words");
                FieldGen Characters = Document.Public.ReadOnly.Field(CharacterCollection, "Characters");

                g = Document.Public.Constructor().Parameter(typeof(string), "initialText");
                {
                    g.Assign(TextArray, g.Arg("initialText").Invoke("ToCharArray"));
                    g.Assign(Words, exp.New(WordCollection, g.This()));
                    g.Assign(Characters, exp.New(CharacterCollection, g.This()));
                }

                g = Document.Public.Property(typeof(string), "Text").Getter();
                {
                    g.Return(exp.New(typeof(string), TextArray));
                }
            }

            TypeGen Test = ag.Class("Test");
            {
                g = Test.Public.Static.Method(typeof(void), "Main");
                {
                    var d = g.Local(exp.New(Document, "peter piper picked a peck of pickled peppers. How many pickled peppers did peter piper pick?"));

                    // Change word "peter" to "penelope":
                    var i = g.Local();
                    g.For(i.Assign(0), i < d.Field("Words").Property("Count"), i.Increment());
                    {
                        g.If(d.Field("Words")[i] == "peter");
                        {
                            g.Assign(d.Field("Words")[i], "penelope");
                        }
                        g.End();
                    }
                    g.End();

                    // Change character "p" to "P"
                    g.For(i.Assign(0), i < d.Field("Characters").Property("Count"), i.Increment());
                    {
                        g.If(d.Field("Characters")[i] == 'p');
                        {
                            g.Assign(d.Field("Characters")[i], 'P');
                        }
                        g.End();
                    }
                    g.End();

                    g.WriteLine(d.Property("Text"));
                }
            }
        }
コード例 #5
0
        public static void GenIndexer(AssemblyGen ag)
        {
            // Class to provide access to a large file
            // as if it were a byte array.
            TypeGen FileByteArray = ag.Public.Class("FileByteArray");
            {
                FieldGen stream = FileByteArray.Field <Stream>("stream");                       // Holds the underlying stream
                // used to access the file.

                // Create a new FileByteArray encapsulating a particular file.
                CodeGen g = FileByteArray.Public.Constructor().Parameter <string>("fileName");
                {
                    g.Assign(stream, Exp.New <FileStream>(g.Arg("fileName"), FileMode.Open));
                }

                // Close the stream. This should be the last thing done
                // when you are finished.
                g = FileByteArray.Public.Void("Close");
                {
                    g.Invoke(stream, "Close");
                    g.Assign(stream, null);
                }

                // Indexer to provide read/write access to the file.
                PropertyGen Item = FileByteArray.Public.Indexer <byte>().Index <long>("index");                 // long is a 64-bit integer
                {
                    // Read one byte at offset index and return it.
                    g = Item.Getter();
                    {
                        Operand buffer = g.Local(Exp.NewArray <byte>(1));
                        g.Invoke(stream, "Seek", g.Arg("index"), SeekOrigin.Begin);
                        g.Invoke(stream, "Read", buffer, 0, 1);
                        g.Return(buffer[0]);
                    }
                    // Write one byte at offset index and return it.
                    g = Item.Setter();
                    {
                        Operand buffer = g.Local(Exp.NewInitializedArray <byte>(g.PropertyValue()));
                        g.Invoke(stream, "Seek", g.Arg("index"), SeekOrigin.Begin);
                        g.Invoke(stream, "Write", buffer, 0, 1);
                    }
                }

                // Get the total length of the file.
                FileByteArray.Public.Property <long>("Length").Getter().GetCode()
                .Return(stream.Invoke("Seek", 0, SeekOrigin.End));
            }

            // Demonstrate the FileByteArray class.
            // Reverses the bytes in a file.
            TypeGen Reverse = ag.Public.Class("Reverse");
            {
                CodeGen g = Reverse.Public.Static.Void("Main").Parameter <string[]>("args");
                {
                    Operand args = g.Arg("args");

                    // Check for arguments.
                    g.If(args.ArrayLength() != 1);
                    {
                        g.WriteLine("Usage : Indexer <filename>");
                        g.Return();
                    }
                    g.End();

                    // Check for file existence
                    g.If(!Static.Invoke(typeof(File), "Exists", args[0]));
                    {
                        g.WriteLine("File " + args[0] + " not found.");
                        g.Return();
                    }
                    g.End();

                    Operand file = g.Local(Exp.New(FileByteArray, args[0]));
                    Operand len  = g.Local(file.Property("Length"));

                    // Swap bytes in the file to reverse it.
                    Operand i = g.Local <long>();
                    g.For(i.Assign(0), i < len / 2, i.Increment());
                    {
                        Operand t = g.Local();

                        // Note that indexing the "file" variable invokes the
                        // indexer on the FileByteStream class, which reads
                        // and writes the bytes in the file.
                        g.Assign(t, file[i]);
                        g.Assign(file[i], file[len - i - 1]);
                        g.Assign(file[len - i - 1], t);
                    }
                    g.End();

                    g.Invoke(file, "Close");
                }
            }
        }
コード例 #6
0
        // example based on the MSDN Properties Sample (abstractshape.cs, shapes.cs, shapetest.cs)
        public static void GenShapeTest(AssemblyGen ag)
        {
            // abstractshape.cs
            TypeGen Shape = ag.Public.Abstract.Class("Shape");
            {
                FieldGen myId = Shape.Private.Field(typeof(string), "myId");

                PropertyGen Id = Shape.Public.SimpleProperty(myId, "Id");

                CodeGen g = Shape.Public.Constructor().Parameter(typeof(string), "s");
                {
                    g.Assign(Id, g.Arg("s"));                           // calling the set accessor of the Id property
                }

                // Area is a read-only property - only a get accessor is needed:
                PropertyGen Area = Shape.Public.Abstract.Property(typeof(double), "Area");
                Area.Getter();

                g = Shape.Public.Override.Method(typeof(string), "ToString");
                {
                    g.Return(Id + " Area = " + Static.Invoke(typeof(string), "Format", "{0:F2}", Area));
                }
            }

            // shapes.cs
            TypeGen Square = ag.Public.Class("Square", Shape);
            {
                FieldGen mySide = Square.Private.Field(typeof(int), "mySide");

                CodeGen g = Square.Public.Constructor().Parameter(typeof(int), "side").Parameter(typeof(string), "id");
                {
                    g.InvokeBase(g.Arg("id"));
                    g.Assign(mySide, g.Arg("side"));
                }

                PropertyGen Area = Square.Public.Override.Property(typeof(double), "Area");
                g = Area.Getter();
                {
                    // Given the side, return the area of a square:
                    g.Return(mySide * mySide);
                }
            }

            TypeGen Circle = ag.Public.Class("Circle", Shape);
            {
                FieldGen myRadius = Circle.Private.Field(typeof(int), "myRadius");

                CodeGen g = Circle.Public.Constructor().Parameter(typeof(int), "radius").Parameter(typeof(string), "id");
                {
                    g.InvokeBase(g.Arg("id"));
                    g.Assign(myRadius, g.Arg("radius"));
                }

                PropertyGen Area = Circle.Public.Override.Property(typeof(double), "Area");
                g = Area.Getter();
                {
                    // Given the radius, return the area of a circle:
                    g.Return(myRadius * myRadius * Math.PI);
                }
            }

            TypeGen Rectangle = ag.Public.Class("Rectangle", Shape);
            {
                FieldGen myWidth  = Rectangle.Private.Field(typeof(int), "myWidth");
                FieldGen myHeight = Rectangle.Private.Field(typeof(int), "myHeight");

                CodeGen g = Rectangle.Public.Constructor()
                            .Parameter(typeof(int), "width")
                            .Parameter(typeof(int), "height")
                            .Parameter(typeof(string), "id")
                ;
                {
                    g.InvokeBase(g.Arg("id"));
                    g.Assign(myWidth, g.Arg("width"));
                    g.Assign(myHeight, g.Arg("height"));
                }

                PropertyGen Area = Rectangle.Public.Override.Property(typeof(double), "Area");
                g = Area.Getter();
                {
                    // Given the width and height, return the area of a rectangle:
                    g.Return(myWidth * myHeight);
                }
            }

            // shapetest.cs
            TypeGen TestClass = ag.Public.Class("TestClass");
            {
                CodeGen g = TestClass.Public.Static.Method(typeof(void), "Main");
                {
                    Operand shapes = g.Local(Exp.NewInitializedArray(Shape,
                                                                     Exp.New(Square, 5, "Square #1"),
                                                                     Exp.New(Circle, 3, "Circle #1"),
                                                                     Exp.New(Rectangle, 4, 5, "Rectangle #1")));

                    g.WriteLine("Shapes Collection");
                    Operand s = g.ForEach(Shape, shapes);
                    {
                        g.WriteLine(s);
                    }
                    g.End();
                }
            }
        }
コード例 #7
0
            /// <summary>
            /// Iterate over all loaded mods and emit new types
            /// </summary>
            void Awake()
            {
                // Generate overloaded PQSMod types
                AssemblyGen assembly = new AssemblyGen(Guid.NewGuid().ToString(),
                                                       new CompilerOptions {
                    OutputPath = Path.GetTempFileName()
                });

                List <Type> modTypes = GetModTypes();

                foreach (Type modType in modTypes)
                {
                    if (typeof(PQSMod).IsAssignableFrom(modType))
                    {
                        // Get the ModLoader type we want to extend
                        Type loaderType = modTypes.FirstOrDefault(t =>
                                                                  t.BaseType != null && t.BaseType.FullName != null &&
                                                                  t.BaseType.FullName.StartsWith("Kopernicus.Configuration.ModLoader.ModLoader") &&
                                                                  t.BaseType.GetGenericArguments()[0] == modType);
                        if (loaderType == null)
                        {
                            continue;
                        }

                        // Generate the Mod Type
                        TypeGen modGen = assembly.Public.Class($"{modType.Name}Regional", modType);
                        {
                            FieldGen multiplierMap  = modGen.Public.Field(typeof(MapSO), "multiplierMap");
                            FieldGen splitChannels  = modGen.Public.Field(typeof(Boolean), "splitChannels");
                            FieldGen multiplier     = modGen.Private.Field(typeof(Color), "multiplier");
                            FieldGen preBuildColor  = modGen.Private.Field(typeof(Color), "preBuildColor");
                            FieldGen preBuildHeight = modGen.Private.Field(typeof(Double), "preBuildHeight");

                            // OnVertexBuildHeight
                            CodeGen onVertexBuild = modGen.Public.Override.Method(typeof(void), "OnVertexBuild")
                                                    .Parameter(typeof(PQS.VertexBuildData), "data");
                            {
                                ContextualOperand data = onVertexBuild.Arg("data");
                                onVertexBuild.Assign(multiplier, onVertexBuild.Local(multiplierMap.Invoke(
                                                                                         "GetPixelColor", new TypeMapper(),
                                                                                         data.Field("u"), data.Field("v"))));
                                onVertexBuild.If(!splitChannels);
                                {
                                    onVertexBuild.Assign(multiplier.Field("a", new TypeMapper()),
                                                         multiplier.Field("r", new TypeMapper()));
                                }
                                onVertexBuild.End();
                                onVertexBuild.Assign(preBuildColor, data.Field("vertColor"));
                                onVertexBuild.Assign(preBuildHeight, data.Field("vertHeight"));
                                onVertexBuild.Invoke(onVertexBuild.Base(), "OnVertexBuild", data);
                                onVertexBuild.Assign(data.Field("vertColor"),
                                                     assembly.StaticFactory.Invoke(typeof(Color), "Lerp", preBuildColor,
                                                                                   data.Field("vertColor"), multiplier.Field("a", new TypeMapper())));
                                onVertexBuild.Assign(data.Field("vertHeight"),
                                                     assembly.StaticFactory.Invoke(typeof(UtilMath), "Lerp", preBuildHeight,
                                                                                   data.Field("vertHeight"), multiplier.Field("r", new TypeMapper())));
                            }

                            // OnVertexBuildHeight
                            CodeGen onVertexBuildHeight = modGen.Public.Override.Method(typeof(void), "OnVertexBuildHeight")
                                                          .Parameter(typeof(PQS.VertexBuildData), "data");
                            {
                                ContextualOperand data = onVertexBuildHeight.Arg("data");
                                onVertexBuildHeight.Assign(multiplier, onVertexBuildHeight.Local(multiplierMap.Invoke(
                                                                                                     "GetPixelColor", new TypeMapper(),
                                                                                                     data.Field("u"), data.Field("v"))));
                                onVertexBuildHeight.If(!splitChannels);
                                {
                                    onVertexBuildHeight.Assign(multiplier.Field("a", new TypeMapper()),
                                                               multiplier.Field("r", new TypeMapper()));
                                }
                                onVertexBuildHeight.End();
                                onVertexBuildHeight.Assign(preBuildColor, data.Field("vertColor"));
                                onVertexBuildHeight.Assign(preBuildHeight, data.Field("vertHeight"));
                                onVertexBuildHeight.Invoke(onVertexBuildHeight.Base(), "OnVertexBuildHeight", data);
                                onVertexBuildHeight.Assign(data.Field("vertColor"),
                                                           assembly.StaticFactory.Invoke(typeof(Color), "Lerp", preBuildColor,
                                                                                         data.Field("vertColor"), multiplier.Field("a", new TypeMapper())));
                                onVertexBuildHeight.Assign(data.Field("vertHeight"),
                                                           assembly.StaticFactory.Invoke(typeof(UtilMath), "Lerp", preBuildHeight,
                                                                                         data.Field("vertHeight"), multiplier.Field("r", new TypeMapper())));
                            }
                        }

                        // Generate the Loader Type
                        Type    modLoader = typeof(ModLoader <>).MakeGenericType(modGen);
                        TypeGen loaderGen =
                            assembly.Public.Class($"{modType.Name.Replace("PQSMod_", "").Replace("PQS", "")}Regional",
                                                  modLoader);
                        {
                            PropertyGen multiplierMap = loaderGen.Public.Property(typeof(MapSOParserRGB <MapSO>), "multiplierMap")
                                                        .Attribute(typeof(ParserTarget), "multiplierMap");
                            {
                                CodeGen getter = multiplierMap.Getter();
                                {
                                    getter.Return(getter.Base().Property("Mod").Field("multiplierMap"));
                                }
                                CodeGen setter = multiplierMap.Setter();
                                {
                                    setter.Assign(setter.Base().Property("Mod").Field("multiplierMap"),
                                                  setter.PropertyValue());
                                }
                            }

                            PropertyGen splitChannels = loaderGen.Public.Property(typeof(NumericParser <Boolean>), "splitChannels")
                                                        .Attribute(typeof(ParserTarget), "splitChannels");
                            {
                                CodeGen getter = splitChannels.Getter();
                                {
                                    getter.Return(getter.Base().Property("Mod").Field("splitChannels"));
                                }
                                CodeGen setter = splitChannels.Setter();
                                {
                                    setter.Assign(setter.Base().Property("Mod").Field("splitChannels"),
                                                  setter.PropertyValue());
                                }
                            }

                            FieldGen loader = loaderGen.Public.Field(loaderType, "loader")
                                              .BeginAttribute(typeof(ParserTarget), "Mod").SetField("AllowMerge", true).End();

                            CodeGen create_PQS = loaderGen.Public.Override.Method(typeof(void), "Create")
                                                 .Parameter(typeof(PQS), "pqsVersion");
                            {
                                ContextualOperand pqsVersion = create_PQS.Arg("pqsVersion");
                                create_PQS.Invoke(create_PQS.Base(), "Create", pqsVersion);
                                create_PQS.Assign(loader, assembly.ExpressionFactory.New(loaderType));
                                create_PQS.Invoke(loader, "Create", create_PQS.Base().Property("Mod"), pqsVersion);
                            }
                            CodeGen create_Mod_PQS = loaderGen.Public.Override.Method(typeof(void), "Create")
                                                     .Parameter(modGen, "_mod")
                                                     .Parameter(typeof(PQS), "pqsVersion");
                            {
                                ContextualOperand _mod       = create_Mod_PQS.Arg("_mod");
                                ContextualOperand pqsVersion = create_Mod_PQS.Arg("pqsVersion");
                                create_Mod_PQS.Invoke(create_Mod_PQS.Base(), "Create", _mod, pqsVersion);
                                create_Mod_PQS.Assign(loader, assembly.ExpressionFactory.New(loaderType));
                                create_Mod_PQS.Invoke(loader, "Create", create_Mod_PQS.Base().Property("Mod"), pqsVersion);
                            }
                        }
                    }
                }
                assembly.Save();

                // Hacking into my own mod. Oh well.
                modTypes.AddRange(assembly.GetAssembly().GetTypes());
                typeof(Parser).GetField("_modTypes", BindingFlags.NonPublic | BindingFlags.Static)
                ?.SetValue(null, modTypes);
            }