Exemple #1
0
        private static string previousLabel = "######"; // bogus value that is ensured to differ from any real value the first time through.

        /// <summary>
        /// Returns the compiled program's opcodes packed into a tight form, that is a direct
        /// streamed dump of the list of opcodes.
        /// </summary>
        /// <param name="program">The list of opcode codeparts for the compiled program.</param>
        /// <returns>The packed bytes that should be written to the binary file.</returns>
        public static byte[] Pack(List <CodePart> program)
        {
            packTempWriter = new BinaryWriter(new MemoryStream());
            var allCodeBuff = new List <byte>();
            var headBuff    = new List <byte>();

            argumentPack = new byte[8];    // this will grow bigger (be replaced by new arrays) as needed.
            argumentPackLogicalLength = 0; // nothing in the argumentPack yet.
            argumentPackFinder        = new Dictionary <object, int>();
            lineMap       = new DebugLineMap();
            previousLabel = "######";                           // bogus value that is ensured to differ from any real value the first time through.

            for (int index = 0; index < program.Count; ++index) // --.    This can be replaced with a
            {                                                   //   |--- foreach.  I do it this way so I
                CodePart codePart = program[index];             // --'    can print the index in debugging.
                PackArgs(codePart.FunctionsCode);
                PackArgs(codePart.InitializationCode);
                PackArgs(codePart.MainCode);
            }

            // Now that we've seen every argument, we know how many bytes are needed
            // to store the argumentPack, and thus the largest possible index into it.
            // This will be how many bytes our indeces will be in this packed ML file.
            int numArgIndexBytes = FewestBytesToHold(argumentPackLogicalLength);

            headBuff.Add((byte)'%');
            headBuff.Add((byte)'A');
            headBuff.Add(((byte)numArgIndexBytes));

            var truncatedArgumentPack = new byte[argumentPackLogicalLength];

            Array.Copy(argumentPack, 0, truncatedArgumentPack, 0, argumentPackLogicalLength);

            headBuff.AddRange(truncatedArgumentPack);

            for (int index = 0; index < program.Count; ++index)    // --.    This can be replaced with a
            {                                                      //   |--- foreach.  I do it this way so I
                CodePart codePart = program[index];                // --'    can print the index in debugging.

                var codeBuff = new List <byte>();

                int indexSoFar = allCodeBuff.Count + codeBuff.Count;
                codeBuff.Add((byte)'%');
                codeBuff.Add((byte)'F');
                byte[] packedCode = PackCode(codePart.FunctionsCode, numArgIndexBytes, indexSoFar + 2);
                codeBuff.AddRange(packedCode);

                indexSoFar = allCodeBuff.Count + codeBuff.Count;
                codeBuff.Add((byte)'%');
                codeBuff.Add((byte)'I');
                packedCode = PackCode(codePart.InitializationCode, numArgIndexBytes, indexSoFar + 2);
                codeBuff.AddRange(packedCode);

                indexSoFar = allCodeBuff.Count + codeBuff.Count;
                codeBuff.Add((byte)'%');
                codeBuff.Add((byte)'M');
                packedCode = PackCode(codePart.MainCode, numArgIndexBytes, indexSoFar + 2);
                codeBuff.AddRange(packedCode);

                allCodeBuff.AddRange(codeBuff);
            }

            var everything = new List <byte>();

            everything.AddRange(MagicId);
            everything.AddRange(headBuff);
            everything.AddRange(allCodeBuff);
            everything.AddRange(lineMap.Pack());
            return(everything.ToArray());
        }
Exemple #2
0
        private static string previousLabel = "######"; // bogus value that is ensured to differ from any real value the first time through.

        /// <summary>
        /// Returns the compiled program's opcodes packed into a tight form, that is a direct
        /// streamed dump of the list of opcodes.
        /// </summary>
        /// <param name="program">The list of opcode codeparts for the compiled program.</param>
        /// <returns>The packed bytes that should be written to the binary file.</returns>
        public static byte[] Pack(List <CodePart> program)
        {
            packTempWriter = new BinaryWriter(new MemoryStream());
            var allCodeBuff = new List <byte>();
            var headBuff    = new List <byte>();

            argumentPack = new byte[8];    // this will grow bigger (be replaced by new arrays) as needed.
            argumentPackLogicalLength = 0; // nothing in the argumentPack yet.
            argumentPackFinder        = new Dictionary <object, int>();
            lineMap       = new DebugLineMap();
            previousLabel = "######";                           // bogus value that is ensured to differ from any real value the first time through.

            for (int index = 0; index < program.Count; ++index) // --.    This can be replaced with a
            {                                                   //   |--- foreach.  I do it this way so I
                CodePart codePart = program[index];             // --'    can print the index in debugging.
                PackArgs(codePart.FunctionsCode);
                PackArgs(codePart.InitializationCode);
                PackArgs(codePart.MainCode);
            }

            // Purpose of numArgIndexBytes calculated below:
            // The first thing in the argument pack section after the "%A" idicator
            // is a single byte that tells how big the addresses into the argment pack
            // are.  The argument pack might address arguments using a single byte if
            // the argument pack is small enough that you don't need addresses bigger than
            // 255.  If you need addresses bigger than 255, then it might take two bytes
            // to store addresses so it can cover values up to 65535, and so on.
            int argSectionHeaderBytes = 3; // Adjust this if you add or subtract headBuf.Add() lines below:
            int numArgIndexBytes      = FewestBytesToHold(argumentPackLogicalLength + argSectionHeaderBytes);

            headBuff.Add((byte)'%');
            headBuff.Add((byte)'A');
            headBuff.Add(((byte)numArgIndexBytes));
            // ^^^ IF YOU ADD OR REMOVE ANY headBuff.Add(...) LINES ABOVE YOU MUST ALSO CHANGE argSectionHeaderBytes.

            var truncatedArgumentPack = new byte[argumentPackLogicalLength];

            Array.Copy(argumentPack, 0, truncatedArgumentPack, 0, argumentPackLogicalLength);

            headBuff.AddRange(truncatedArgumentPack);

            for (int index = 0; index < program.Count; ++index)    // --.    This can be replaced with a
            {                                                      //   |--- foreach.  I do it this way so I
                CodePart codePart = program[index];                // --'    can print the index in debugging.

                var codeBuff = new List <byte>();

                int indexSoFar = allCodeBuff.Count + codeBuff.Count;
                codeBuff.Add((byte)'%');
                codeBuff.Add((byte)'F');
                byte[] packedCode = PackCode(codePart.FunctionsCode, numArgIndexBytes, indexSoFar + 2);
                codeBuff.AddRange(packedCode);

                indexSoFar = allCodeBuff.Count + codeBuff.Count;
                codeBuff.Add((byte)'%');
                codeBuff.Add((byte)'I');
                packedCode = PackCode(codePart.InitializationCode, numArgIndexBytes, indexSoFar + 2);
                codeBuff.AddRange(packedCode);

                indexSoFar = allCodeBuff.Count + codeBuff.Count;
                codeBuff.Add((byte)'%');
                codeBuff.Add((byte)'M');
                packedCode = PackCode(codePart.MainCode, numArgIndexBytes, indexSoFar + 2);
                codeBuff.AddRange(packedCode);

                allCodeBuff.AddRange(codeBuff);
            }

            var everything = new List <byte>();

            everything.AddRange(MagicId);
            everything.AddRange(headBuff);
            everything.AddRange(allCodeBuff);
            everything.AddRange(lineMap.Pack());
            using (var compressedStream = new MemoryStream())
            {
                using (var csStream = new GZipOutputStream(compressedStream))
                {
                    csStream.Write(everything.ToArray(), 0, everything.Count);
                    csStream.Flush();
                }
                return(compressedStream.ToArray());
            }
        }