Beispiel #1
0
        public VM()
        {
            if (Current != null)
            {
                throw new Exception("Two instances of VM created");
            }

            Current           = this;
            Heap              = new Dictionary <string, byte[]>();
            Stack             = new Stack <byte[]>();
            InstructionLookup = new Dictionary <byte, Instruction>();

            formatter = new BinaryFormatter();

            var meths = this.GetType().GetMethods().Where(meth => Attribute.IsDefined(meth, typeof(MyInstruction)));

            foreach (System.Reflection.MethodInfo method in meths)
            {
                MyInstruction code = method.GetCustomAttributes(typeof(MyInstruction), true).First() as MyInstruction;
                Console.Out.WriteLine(code.Code + " " + method.Name);
                Instruction delegateInstruction = (Instruction)method.CreateDelegate(typeof(Instruction), this);
                InstructionLookup.Add(code.Code, delegateInstruction);
            }
        }
Beispiel #2
0
        public static Tuple <byte[][], int[][]> Compile(string raw)
        {
            // type%data
            // s%string
            // d%double
            // f%float
            // l%long
            // b%bool
            // i%int
            // $label
            // $references existing label
            // label:
            // creates_label_with_name_on_line:
            // InstructionName
            // calls_instruction_with s%arguments s%here s%seperated s%by s%spaces f%6.9

            // list that will hold the instructions. Converted to array[][] at the end
            List <List <byte> > procedure = new List <List <byte> >();

            // index for arguments;
            int[][] index = new int[0][];

            // splitting raw data into each line.
            string[] rawLines = raw.Split('\n');

            // number of lines = number of instructions
            index = new int[rawLines.Length][];

            // array of code symbols {labels, instructions, args}
            string[][] codeSymbols = new string[rawLines.Length][];

            // some dictionaries for tracking labels and what they point at
            Dictionary <string, int> labelLookup = new Dictionary <string, int>();
            Dictionary <Tuple <int, int>, string> reverseLabelLookup = new Dictionary <Tuple <int, int>, string>();

            // for each line we split the symbols by ' '. then for each char in the symbol
            // determine what it is. instruction, or arg (and what kind), or label
            for (int lineIndex = 0; lineIndex < codeSymbols.Length; lineIndex++)
            {
                codeSymbols[lineIndex] = rawLines[lineIndex].Split(' ');

                // don't expect arguments before instructions.
                bool instructionFound = false;

                // position of each argument in the instruction byte array
                List <int> argumentLocations = new List <int>();

                // byte list representation of the instruction line
                List <byte> instruction = new List <byte>();

                for (int symbolIndex = 0; symbolIndex < codeSymbols[lineIndex].Length; symbolIndex++)
                {
                    // the current symbol
                    string symbol = codeSymbols[lineIndex][symbolIndex];

                    // if the last symbol in the code is :
                    // it's a label
                    if (symbol.Length > 0 && symbol[symbol.Length - 1] == ':')
                    {
                        string labelName = symbol.Substring(0, symbol.Length - 1);
                        argumentLocations.Add(instruction.Count);
                        labelLookup.Add(labelName, lineIndex);
                    }
                    // Second char is a % -> we have an argument
                    else if (symbol.Length > 1 && symbol[1] == '%')
                    {
                        // If an instruction hasn't been found then we throw up
                        if (!instructionFound)
                        {
                            throw new Exception("Argument found before instruction " + symbol);
                        }

                        argumentLocations.Add(instruction.Count);
                        instruction.AddRange(VM.ByteParse(codeSymbols[lineIndex][symbolIndex]));
                    }
                    // first symbol is $ -> we have a reference to a label
                    else if (symbol.Length > 0 && symbol[0] == '$')
                    {
                        if (!instructionFound)
                        {
                            throw new Exception("Argument found before instruction " + codeSymbols[lineIndex][symbolIndex]);
                        }

                        reverseLabelLookup.Add(new Tuple <int, int>(lineIndex, instruction.Count), codeSymbols[lineIndex][symbolIndex].Substring(1));
                        // add a place holder byte
                        instruction.Add(0);
                    }
                    // matches none of the above. Must be an instruction
                    else if (symbol.Length > 0)
                    {
                        MethodInfo mf = VM.Current.GetType().GetMethod(symbol);

                        if (mf == null)
                        {
                            throw new Exception("Invalid Instruction: " + symbol);
                        }

                        MyInstruction ins = mf.GetCustomAttribute <MyInstruction>();
                        instruction.Add(ins.Code);
                        instructionFound = true;
                    }
                }

                // add the new instruction!
                procedure.Add(instruction);
                index[lineIndex] = argumentLocations.ToArray();
            }

            // Tuple: item1 - index of instruction line, item2 - index of instruction byte
            // reverseLabelLookup - Tuple (position of placeholder byte) -> string name of label
            // labelLookup - string name of label -> int index of the line of the next instruction
            foreach (Tuple <int, int> a in reverseLabelLookup.Keys)
            {
                // size of the label pos in bytes
                int labelSize;

                // temp list to build new instruction line
                List <byte> tlist = new List <byte>();

                // add all bytes before placeholder
                for (int x = 0; x < a.Item2; x++)
                {
                    tlist.Add(procedure[a.Item1][x]);
                }

                // get the bytes of the index of the line the label points to
                byte[] b = BitConverter.GetBytes(labelLookup[reverseLabelLookup[a]]);
                labelSize = b.Length;

                // add the bytes of the label to the list
                tlist.AddRange(b);

                // add the rest of the bytes after placeholder to the list
                for (int x = a.Item2 + 1; x < procedure[a.Item1].Count; x++)
                {
                    tlist.Add(procedure[a.Item1][x]);
                }

                // built list is done, set as new instruction
                procedure[a.Item1] = tlist;

                // bool controlling when to extend each index
                bool extend = false;

                // updating index
                for (int x = 0; x < index[a.Item1].Length; x++)
                {
                    // all arguments after the placeholder will be shifted
                    // labelSize -1 . since the placeholder took up 1 byte
                    // by itself
                    if (extend == true)
                    {
                        index[a.Item1][x] += labelSize - 1;
                    }

                    // if we have reached the placeholder
                    if (index[a.Item1][x] == a.Item2)
                    {
                        extend = true;
                    }
                }
            }

            byte[][] retProcedure = new byte[procedure.Count][];
            for (int i = 0; i < procedure.Count; i++)
            {
                retProcedure[i] = procedure[i].ToArray();
            }

            return(new Tuple <byte[][], int[][]>(retProcedure, index));
        }