/// <summary>
        /// Writes the specification in code to the specified <see cref="TextWriter"/>.
        /// </summary>
        /// <param name="spec">The specification to write.</param>
        /// <param name="writer">The write to use.</param>
        protected virtual void WriteCode(OpcodeSpec spec, TextWriter writer)
        {
            WriteWarning(writer);
            WriteCodeUsingDirectives(writer);
            writer.WriteLine();
            WriteCodeOpcodeClassStart(spec, writer);
            WriteCodeOpcodeClassProperties(spec, writer);
            writer.WriteLine(T + T + "#region Constructors");
            WriteCodeOpcodeClassConstructors(spec, writer);
            writer.WriteLine(T + T + "#endregion");
            writer.WriteLine();
            WriteCodeOpcodeVariantMethod(spec, writer);
            WriteCodeOpcodeClassEnd(writer);

            WriteCodeSubnamespaceStart(writer);
            WriteCodeInstrClassStart(spec, writer);
            WriteCodeInstrOpcodeVariantMethods(spec, spec.Name, writer);
            foreach (string aka in spec.Aka)
            {
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine();
                WriteCodeInstrOpcodeVariantMethods(spec, aka, writer);
            }
            WriteCodeInstrClassEnd(writer);
            writer.WriteLine();
            WriteCodeOpcodeClassField(spec, writer);
            WriteCodeSubnamespaceEnd(writer);

            WriteWarning(writer);
        }
示例#2
0
        /// <summary>
        /// Writes the specification in code to the specified <see cref="TextWriter"/>.
        /// </summary>
        /// <param name="spec">The specification to write.</param>
        /// <param name="writer">The write to use.</param>
        protected virtual void WriteCode(OpcodeSpec spec, TextWriter writer)
        {
            WriteWarning(writer);
            WriteCodeUsingDirectives(writer);
            writer.WriteLine();
            WriteCodeOpcodeClassStart(spec, writer);
            WriteCodeOpcodeClassProperties(spec, writer);
            writer.WriteLine(T + T + "#region Constructors");
            WriteCodeOpcodeClassConstructors(spec, writer);
            writer.WriteLine(T + T + "#endregion");
            writer.WriteLine();
            WriteCodeOpcodeVariantMethod(spec, writer);
            WriteCodeOpcodeClassEnd(writer);

            WriteCodeSubnamespaceStart(writer);
            WriteCodeInstrClassStart(spec, writer);
            WriteCodeInstrOpcodeVariantMethods(spec, spec.Name, writer);
            foreach (string aka in spec.Aka)
            {
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine();
                WriteCodeInstrOpcodeVariantMethods(spec, aka, writer);
            }
            WriteCodeInstrClassEnd(writer);
            writer.WriteLine();
            WriteCodeOpcodeClassField(spec, writer);
            WriteCodeSubnamespaceEnd(writer);

            WriteWarning(writer);
        }
 /// <summary>
 /// Writes the specification tests to the specified <see cref="TextWriter"/>.
 /// </summary>
 /// <param name="spec">The specification to write.</param>
 /// <param name="writer">The write to use.</param>
 protected virtual void WriteTest(OpcodeSpec spec, TextWriter writer)
 {
     WriteWarning(writer);
     WriteTestUsingDirectives(writer);
     writer.WriteLine();
     WriteTestClassStart(spec, writer);
     WriteTestClassTests(spec, writer);
     WriteTestClassEnd(writer);
     WriteWarning(writer);
 }
示例#4
0
 /// <summary>
 /// Writes the specification tests to the specified <see cref="TextWriter"/>.
 /// </summary>
 /// <param name="spec">The specification to write.</param>
 /// <param name="writer">The write to use.</param>
 protected virtual void WriteTest(OpcodeSpec spec, TextWriter writer)
 {
     WriteWarning(writer);
     WriteTestUsingDirectives(writer);
     writer.WriteLine();
     WriteTestClassStart(spec, writer);
     WriteTestClassTests(spec, writer);
     WriteTestClassEnd(writer);
     WriteWarning(writer);
 }
示例#5
0
 /// <summary>
 /// Writes the namespace declaration start and the test class declaration start.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected void WriteTestClassStart(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine("namespace {0}", OpcodeTestNamespace);
     writer.WriteLine("{");
     writer.WriteLine(T + "/// <summary>");
     writer.WriteLine(T + "/// Tests all variants of the {0} opcode.", spec.Mnemonic.ToUpperInvariant());
     writer.WriteLine(T + "/// </summary>");
     writer.WriteLine(T + "[TestFixture]");
     writer.WriteLine(T + "public class {0} : {1}", AsValidIdentifier(spec.Name + "Tests"), GetTestBaseClassName());
     writer.WriteLine(T + "{");
 }
 /// <summary>
 /// Writes the namespace declaration start and the test class declaration start.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected void WriteTestClassStart(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine("namespace {0}", OpcodeTestNamespace);
     writer.WriteLine("{");
     writer.WriteLine(T + "/// <summary>");
     writer.WriteLine(T + "/// Tests all variants of the {0} opcode.", spec.Mnemonic.ToUpperInvariant());
     writer.WriteLine(T + "/// </summary>");
     writer.WriteLine(T + "[TestFixture]");
     writer.WriteLine(T + "public class {0} : {1}", AsValidIdentifier(spec.Name + "Tests"), GetTestBaseClassName());
     writer.WriteLine(T + "{");
 }
示例#7
0
        /// <summary>
        /// Writes the specification in code to the specified code writer,
        /// and tests for it to the specified test writer.
        /// </summary>
        /// <param name="spec">The specification to write.</param>
        /// <param name="codeWriter">The code writer to use;
        /// or <see langword="null"/> to write no code.</param>
        /// <param name="testWriter">The test writer to use;
        /// or <see langword="null"/> to write no tests.</param>
        public void Write(OpcodeSpec spec, TextWriter codeWriter, TextWriter testWriter)
        {
            if (codeWriter != null)
            {
                WriteCode(spec, codeWriter);
            }

            if (testWriter != null)
            {
                WriteTest(spec, testWriter);
            }
        }
示例#8
0
 /// <summary>
 /// Writes the namespace declaration start and the opcode class declaration start.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected void WriteCodeOpcodeClassStart(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine("namespace {0}", OpcodeNamespace);
     writer.WriteLine("{");
     writer.WriteLine(T + "/// <summary>");
     writer.WriteLine(T + "/// The {0} ({1}) instruction opcode.", spec.Mnemonic.ToUpperInvariant(), spec.ShortDescription);
     writer.WriteLine(T + "/// </summary>");
     writer.WriteLine(T + "public class {0} : {1}",
                      AsValidIdentifier(spec.Name + "Opcode"),
                      GetOpcodeBaseClassName());
     writer.WriteLine(T + "{");
 }
示例#9
0
        /// <summary>
        /// Writes the main constructor for the opcode class.
        /// </summary>
        /// <param name="spec">The opcode specification.</param>
        /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
        protected void WriteCodeOpcodeClassMainConstructor(OpcodeSpec spec, TextWriter writer)
        {
            string className = AsValidIdentifier(spec.Name + "Opcode");

            writer.WriteLine(T + T + "/// <summary>");
            writer.WriteLine(T + T + "/// Initializes a new instance of the <see cref=\"{0}\"/> class.", className);
            writer.WriteLine(T + T + "/// </summary>");
            writer.WriteLine(T + T + "public {0}()", className);
            writer.WriteLine(T + T + T + ": base(\"{0}\", GetOpcodeVariants())", spec.Mnemonic.ToLowerInvariant());
            writer.WriteLine(T + T + "{");
            writer.WriteLine(T + T + "}");
        }
示例#10
0
 /// <summary>
 /// Writes the read-only field member o the Opcode partial class.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 void WriteCodeOpcodeClassField(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine(T + "partial class {0}", GetOpcodeStaticClassName());
     writer.WriteLine(T + "{");
     writer.WriteLine(T + T + "/// <summary>");
     writer.WriteLine(T + T + "/// The {0} ({1}) instruction opcode.", spec.Mnemonic.ToUpperInvariant(), spec.ShortDescription);
     writer.WriteLine(T + T + "/// </summary>");
     writer.WriteLine(T + T + "public static readonly {0} {1} = new {2}();",
                      GetOpcodeBaseClassName(),
                      AsValidIdentifier(spec.Name),
                      AsValidIdentifier(spec.Name + "Opcode"));
     writer.WriteLine(T + "}");
 }
示例#11
0
        /// <summary>
        /// Writes the <c>GetOpcodeVariants</c> method for the opcode class.
        /// </summary>
        /// <param name="spec">The opcode specification.</param>
        /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
        protected void WriteCodeOpcodeVariantMethod(OpcodeSpec spec, TextWriter writer)
        {
            string variantClassName = GetOpcodeVariantClassName();

            writer.WriteLine(T + T + "/// <summary>");
            writer.WriteLine(T + T + "/// Returns the opcode variants of this opcode.");
            writer.WriteLine(T + T + "/// </summary>");
            writer.WriteLine(T + T + "/// <returns>An enumerable collection of <see cref=\"{0}\"/> objects.</returns>", variantClassName);
            writer.WriteLine(T + T + "private static IEnumerable<{0}> GetOpcodeVariants()", variantClassName);
            writer.WriteLine(T + T + "{");
            writer.WriteLine(T + T + T + "return new {0}[]{{", variantClassName);
            //writer.WriteLine(T + T + T + T + "#region Variants");

            foreach (var variant in spec.Variants)
            {
                WriteCodeOpcodeVariant(spec, variant, writer);
            }

            //writer.WriteLine(T + T + T + T + "#endregion");
            writer.WriteLine(T + T + T + "};");
            writer.WriteLine(T + T + "}");
        }
        /// <summary>
        /// Reads an opcode variant.
        /// </summary>
        void ReadOpcodeVariant(OpcodeSpec opcodeSpec)
        {
            ExpectRead("var");

            var opcodeVariantSpec = factory.CreateOpcodeVariantSpec();

            opcodeSpec.Variants.Add(opcodeVariantSpec);

            string opcodeBytesStr = ReadIdentifier();

            opcodeVariantSpec.OpcodeBytes = ReadByteArray(opcodeBytesStr);

            ApplyAnnotations(opcodeVariantSpec);

            reader.ReadListInRegion(ScriptReader.RegionType.Parentheses, ",", () =>
            {
                ReadAnnotations();

                string operandType  = ReadIdentifier();
                string operandName  = ReadIdentifier();
                object defaultValue = null;

                if (reader.Peek().Equals("="))
                {
                    reader.Read();
                    defaultValue = ReadAnyValue();
                }

                var operandSpec = factory.CreateOperandSpec(operandType, defaultValue);
                opcodeVariantSpec.Operands.Add(operandSpec);
                operandSpec.Name = operandName;

                ApplyAnnotations(operandSpec);
            });

            ExpectRead(";");
        }
示例#13
0
 /// <summary>
 /// Writes the properties for the opcode class.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected virtual void WriteCodeOpcodeClassProperties(OpcodeSpec spec, TextWriter writer)
 {
 }
示例#14
0
        /// <summary>
        /// Writes the specification in code to the specified code writer,
        /// and tests for it to the specified test writer.
        /// </summary>
        /// <param name="spec">The specification to write.</param>
        /// <param name="codeWriter">The code writer to use;
        /// or <see langword="null"/> to write no code.</param>
        /// <param name="testWriter">The test writer to use;
        /// or <see langword="null"/> to write no tests.</param>
        public void Write(OpcodeSpec spec, TextWriter codeWriter, TextWriter testWriter)
        {
            if (codeWriter != null)
                WriteCode(spec, codeWriter);

            if (testWriter != null)
                WriteTest(spec, testWriter);
        }
示例#15
0
 /// <summary>
 /// Writes the specification in code to the specified code stream,
 /// and tests for it to the specified test stream.
 /// </summary>
 /// <param name="spec">The specification to write.</param>
 /// <param name="codeStream">The code <see cref="Stream"/> to write to;
 /// or <see langword="null"/> to write no code.</param>
 /// <param name="testStream">The test <see cref="Stream"/> to write to;
 /// or <see langword="null"/> to write no tests.</param>
 public void Write(OpcodeSpec spec, Stream codeStream, Stream testStream)
 {
     using (var codeWriter = new StreamWriter(codeStream, Encoding.UTF8))
     using (var testWriter = new StreamWriter(testStream, Encoding.UTF8))
         Write(spec, codeWriter, testWriter);
 }
 /// <summary>
 /// Writes an opcode variant method.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="mnemonic">The mnemonic to use.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected abstract void WriteCodeInstrOpcodeVariantMethods(OpcodeSpec spec, string mnemonic, TextWriter writer);
 /// <summary>
 /// Writes the constructors for the opcode class.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected virtual void WriteCodeOpcodeClassConstructors(OpcodeSpec spec, TextWriter writer)
 {
     WriteCodeOpcodeClassMainConstructor(spec, writer);
 }
示例#18
0
 /// <summary>
 /// Writes the tests.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected abstract void WriteTestClassTests(OpcodeSpec spec, TextWriter writer);
 /// <summary>
 /// Writes the namespace declaration start and the <c>Instr</c> class declaration start.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected void WriteCodeInstrClassStart(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine(T + "partial class Instr");
     writer.WriteLine(T + "{");
 }
        /// <summary>
        /// Writes the <c>GetOpcodeVariants</c> method for the opcode class.
        /// </summary>
        /// <param name="spec">The opcode specification.</param>
        /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
        protected void WriteCodeOpcodeVariantMethod(OpcodeSpec spec, TextWriter writer)
        {
            string variantClassName = GetOpcodeVariantClassName();

            writer.WriteLine(T + T + "/// <summary>");
            writer.WriteLine(T + T + "/// Returns the opcode variants of this opcode.");
            writer.WriteLine(T + T + "/// </summary>");
            writer.WriteLine(T + T + "/// <returns>An enumerable collection of <see cref=\"{0}\"/> objects.</returns>", variantClassName);
            writer.WriteLine(T + T + "private static IEnumerable<{0}> GetOpcodeVariants()", variantClassName);
            writer.WriteLine(T + T + "{");
            writer.WriteLine(T + T + T + "return new {0}[]{{", variantClassName);
            //writer.WriteLine(T + T + T + T + "#region Variants");

            foreach (var variant in spec.Variants)
            {
                WriteCodeOpcodeVariant(spec, variant, writer);
            }

            //writer.WriteLine(T + T + T + T + "#endregion");
            writer.WriteLine(T + T + T + "};");
            writer.WriteLine(T + T + "}");
        }
 /// <summary>
 /// Writes the read-only field member o the Opcode partial class.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 void WriteCodeOpcodeClassField(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine(T + "partial class {0}", GetOpcodeStaticClassName());
     writer.WriteLine(T + "{");
     writer.WriteLine(T + T + "/// <summary>");
     writer.WriteLine(T + T + "/// The {0} ({1}) instruction opcode.", spec.Mnemonic.ToUpperInvariant(), spec.ShortDescription);
     writer.WriteLine(T + T + "/// </summary>");
     writer.WriteLine(T + T + "public static readonly {0} {1} = new {2}();",
         GetOpcodeBaseClassName(),
         AsValidIdentifier(spec.Name),
         AsValidIdentifier(spec.Name + "Opcode"));
     writer.WriteLine(T + "}");
 }
示例#22
0
 /// <summary>
 /// Writes the specification in code to the specified code stream,
 /// and tests for it to the specified test stream.
 /// </summary>
 /// <param name="spec">The specification to write.</param>
 /// <param name="codeStream">The code <see cref="Stream"/> to write to;
 /// or <see langword="null"/> to write no code.</param>
 /// <param name="testStream">The test <see cref="Stream"/> to write to;
 /// or <see langword="null"/> to write no tests.</param>
 public void Write(OpcodeSpec spec, Stream codeStream, Stream testStream)
 {
     using (var codeWriter = new StreamWriter(codeStream, Encoding.UTF8))
         using (var testWriter = new StreamWriter(testStream, Encoding.UTF8))
             Write(spec, codeWriter, testWriter);
 }
示例#23
0
 /// <summary>
 /// Writes the specification in code to the specified code file,
 /// and tests for it to the specified test file.
 /// </summary>
 /// <param name="spec">The specification to write.</param>
 /// <param name="codeFile">The full path to the code file to write to;
 /// or <see langword="null"/> to write no code.</param>
 /// <param name="testFile">The full path to the code file to write to;
 /// or <see langword="null"/> to write no tests.</param>
 /// <remarks>
 /// Any data that is already in the files is overwritten and discarded.
 /// </remarks>
 public void Write(OpcodeSpec spec, string codeFile, string testFile)
 {
     using (var codeStream = File.Create(codeFile))
     using (var testStream = File.Create(testFile))
         Write(spec, codeStream, testStream);
 }
示例#24
0
 /// <summary>
 /// Writes the namespace declaration start and the <c>Instr</c> class declaration start.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected void WriteCodeInstrClassStart(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine(T + "partial class Instr");
     writer.WriteLine(T + "{");
 }
 /// <summary>
 /// Writes the tests.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected abstract void WriteTestClassTests(OpcodeSpec spec, TextWriter writer);
示例#26
0
 /// <summary>
 /// Returns the file name of the test file for the specified opcode.
 /// </summary>
 /// <param name="opcodeSpec">The opcode specification.</param>
 /// <returns>A filename.</returns>
 static string GetTestFilename(OpcodeSpec opcodeSpec)
 {
     return SpecWriter.AsValidIdentifier(opcodeSpec.Name + "Tests") + ".generated.cs";
 }
示例#27
0
 /// <summary>
 /// Writes the constructors for the opcode class.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected virtual void WriteCodeOpcodeClassConstructors(OpcodeSpec spec, TextWriter writer)
 {
     WriteCodeOpcodeClassMainConstructor(spec, writer);
 }
示例#28
0
 /// <summary>
 /// Writes the specification in code to the specified code file,
 /// and tests for it to the specified test file.
 /// </summary>
 /// <param name="spec">The specification to write.</param>
 /// <param name="codeFile">The full path to the code file to write to;
 /// or <see langword="null"/> to write no code.</param>
 /// <param name="testFile">The full path to the code file to write to;
 /// or <see langword="null"/> to write no tests.</param>
 /// <remarks>
 /// Any data that is already in the files is overwritten and discarded.
 /// </remarks>
 public void Write(OpcodeSpec spec, string codeFile, string testFile)
 {
     using (var codeStream = File.Create(codeFile))
         using (var testStream = File.Create(testFile))
             Write(spec, codeStream, testStream);
 }
        /// <summary>
        /// Writes the main constructor for the opcode class.
        /// </summary>
        /// <param name="spec">The opcode specification.</param>
        /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
        protected void WriteCodeOpcodeClassMainConstructor(OpcodeSpec spec, TextWriter writer)
        {
            string className = AsValidIdentifier(spec.Name + "Opcode");

            writer.WriteLine(T + T + "/// <summary>");
            writer.WriteLine(T + T + "/// Initializes a new instance of the <see cref=\"{0}\"/> class.", className);
            writer.WriteLine(T + T + "/// </summary>");
            writer.WriteLine(T + T + "public {0}()", className);
            writer.WriteLine(T + T + T + ": base(\"{0}\", GetOpcodeVariants())", spec.Mnemonic.ToLowerInvariant());
            writer.WriteLine(T + T + "{");
            writer.WriteLine(T + T + "}");
        }
示例#30
0
 /// <summary>
 /// Returns the file name of the test file for the specified opcode.
 /// </summary>
 /// <param name="opcodeSpec">The opcode specification.</param>
 /// <returns>A filename.</returns>
 static string GetTestFilename(OpcodeSpec opcodeSpec)
 {
     return(SpecWriter.AsValidIdentifier(opcodeSpec.Name + "Tests") + ".generated.cs");
 }
示例#31
0
 /// <summary>
 /// Writes the opcode variant specification in the variants array.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="variant">The opcode variant.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected abstract void WriteCodeOpcodeVariant(OpcodeSpec spec, OpcodeVariantSpec variant, TextWriter writer);
 /// <summary>
 /// Writes the properties for the opcode class.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected virtual void WriteCodeOpcodeClassProperties(OpcodeSpec spec, TextWriter writer)
 {
 }
示例#33
0
 /// <summary>
 /// Writes an opcode variant method.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="mnemonic">The mnemonic to use.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected abstract void WriteCodeInstrOpcodeVariantMethods(OpcodeSpec spec, string mnemonic, TextWriter writer);
 /// <summary>
 /// Writes the namespace declaration start and the opcode class declaration start.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected void WriteCodeOpcodeClassStart(OpcodeSpec spec, TextWriter writer)
 {
     writer.WriteLine("namespace {0}", OpcodeNamespace);
     writer.WriteLine("{");
     writer.WriteLine(T + "/// <summary>");
     writer.WriteLine(T + "/// The {0} ({1}) instruction opcode.", spec.Mnemonic.ToUpperInvariant(), spec.ShortDescription);
     writer.WriteLine(T + "/// </summary>");
     writer.WriteLine(T + "public class {0} : {1}",
         AsValidIdentifier(spec.Name + "Opcode"),
         GetOpcodeBaseClassName());
     writer.WriteLine(T + "{");
 }
 /// <summary>
 /// Writes the opcode variant specification in the variants array.
 /// </summary>
 /// <param name="spec">The opcode specification.</param>
 /// <param name="variant">The opcode variant.</param>
 /// <param name="writer">The <see cref="TextWriter"/> to write to.</param>
 protected abstract void WriteCodeOpcodeVariant(OpcodeSpec spec, OpcodeVariantSpec variant, TextWriter writer);
        /// <summary>
        /// Reads an opcode variant.
        /// </summary>
        void ReadOpcodeVariant(OpcodeSpec opcodeSpec)
        {
            ExpectRead("var");

            var opcodeVariantSpec = factory.CreateOpcodeVariantSpec();
            opcodeSpec.Variants.Add(opcodeVariantSpec);

            string opcodeBytesStr = ReadIdentifier();
            opcodeVariantSpec.OpcodeBytes = ReadByteArray(opcodeBytesStr);

            ApplyAnnotations(opcodeVariantSpec);

            reader.ReadListInRegion(ScriptReader.RegionType.Parentheses, ",", () =>
            {
                ReadAnnotations();

                string operandType = ReadIdentifier();
                string operandName = ReadIdentifier();
                object defaultValue = null;

                if (reader.Peek().Equals("="))
                {
                    reader.Read();
                    defaultValue = ReadAnyValue();
                }

                var operandSpec = factory.CreateOperandSpec(operandType, defaultValue);
                opcodeVariantSpec.Operands.Add(operandSpec);
                operandSpec.Name = operandName;

                ApplyAnnotations(operandSpec);
            });

            ExpectRead(";");
        }