// Finds var table entry by VarID
        //
        // Returns: VarTableEntry or null on no find
        public VarTableEntry GetVarTableEntry(int varID)
        {
            // Inits
            bool          found = false;
            VarTableEntry entry = null;
            VarTableEntry ret   = null;

            // Cycle through block size table entries
            for (int i = 0; (i < varTable.Count) && !found; i++)
            {
                // Get current entry
                entry = (VarTableEntry)varTable[i];

                // Check if Ids match and set found
                if (entry.VarID == varID)
                {
                    found = true;
                }
            }

            // Check if found entry
            if (found)
            {
                // Set return value
                ret = entry;
            }

            // Return entry or null
            return(ret);
        }
        // Gens op codes to find address from var table,
        // and store value in accumulator.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            VarTableEntry varEntry = null;

            // Find var in var table
            varEntry = param.tables.GetVarTableEntry(SymbolTableEntry.EntryID);

            // Verify var entry exists
            if (varEntry != null)
            {
                try
                {
                    // Load value into accumlator
                    param.opCodes.AppendFormat("AD V{0} 00 ", varEntry.VarID);
                    param.AddBytes(0xAD);
                    param.AddByteForUpdate('V', varEntry.VarID);
                    param.AddBytes(0x00);
                }

                // Catch over 256 byte error,
                // and throw up
                catch (IndexOutOfRangeException ex)
                {
                    throw ex;
                }
            }

            // Return number of bytes
            return(3);
        }
        // Creates a var table entry based on symbol table entry,
        // and calculates current in use off set (position).
        //
        // Returns: New entry created.
        public VarTableEntry CreateVarTableEntry(SymbolTableEntry entry)
        {
            // Inits
            VarTableEntry varEntry = new VarTableEntry(entry.EntryID, entry);

            // Set off set
            varEntry.Offset = FindNextAvaialbleOffset();

            // Add to table
            varTable.Add(varEntry);

            // Return entry
            return(varEntry);
        }
        // Finds next avaialble offset to maximize stack size
        //
        // Returns: Next avaialbe (un used) mem location offset from start
        public int FindNextAvaialbleOffset()
        {
            // Inits
            bool          foundOffset = false;
            bool          found       = false;
            VarTableEntry varEntry    = null;
            int           offset      = 0;
            int           tableCount  = varTable.Count;

            // Cycle through all possible offsets
            for (int i = 0; ((i < tableCount) && !found); i++)
            {
                // Reset found off set flag
                foundOffset = false;

                // Cycle through all entries
                for (int n = 0; ((n < tableCount) && !foundOffset); n++)
                {
                    // Get var entry
                    varEntry = (VarTableEntry)varTable[n];

                    // Check if in use and right offet
                    if (varEntry.InUse && varEntry.Offset == i)
                    {
                        // Set found off set flag
                        foundOffset = true;
                    }
                }

                // Check if did not find off set
                if (!foundOffset)
                {
                    // Record offset
                    offset = i;

                    // Set found next offset flag
                    found = true;
                }
            }

            // Check if not found, than add 1 to count
            if (!found)
            {
                offset = tableCount;
            }

            // Return next off set
            return(offset);
        }
Esempio n. 5
0
        // Gens code that allocates 00 to a location in memory,
        // tracked in var table.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            VarTableEntry varEntry = null;


            // Create var table entry for this
            varEntry = param.tables.CreateVarTableEntry(id.SymbolTableEntry);

            // Increment current vars in use
            param.tables.IncVarIsUseCount();

            // Check if entry found incase of some wierd error
            if (varEntry != null)
            {
                try
                {
                    // Load accumlator with 0
                    //param.opCodes.Append("A9 00 ");
                    param.AddBytes(0xA9, 0x00);

                    // Add var entry to init value table
                    // for optimization
                    param.tables.AddInitValueEntry(id.Value, param.curByte - 1,
                                                   param.curBlockID - 1, id.SymbolTableEntry.DataType);

                    // Copy to temp location in memory
                    //param.opCodes.AppendFormat("8D V{0} 00 ",varEntry.VarID);
                    param.AddBytes(0x8D);
                    param.AddByteForUpdate('V', varEntry.VarID);
                    param.AddBytes(0x00);
                }

                // Catch over 256 byte error,
                // and throw up
                catch (IndexOutOfRangeException ex)
                {
                    throw ex;
                }

                // Add number of bytes
                // param.curByte += 5;
            }

            // Return cur bytes
            return(5);
        }
        // Get var table entry by index
        //
        // Throws: IndexOutOfRangeException
        // Returns: Entry at given index.
        public VarTableEntry GetVarTableEntryByIndex(int index)
        {
            //Inits
            VarTableEntry ret = null;

            if (index >= varTable.Count || index < 0)
            {
                throw new IndexOutOfRangeException("OpCodeVarTable entry idex out of range.");
            }
            else
            {
                ret = (VarTableEntry)varTable[index];
            }

            // Return var table entry
            return(ret);
        }
        // Creates a new temp var ref, with a new calculated offset.
        //
        // Returns: Temp var entry.
        public VarTableEntry CreateTempVarTableEntry()
        {
            // Inits
            VarTableEntry entry = null;

            // Create new entry
            entry = new VarTableEntry(curTempVarID, null);

            // Increment cur temp var id
            curTempVarID++;

            // Set off set
            entry.Offset = FindNextAvaialbleOffset();

            // Add to table
            varTable.Add(entry);

            // Return found var or newly created one
            return(entry);
        }
        // Gens op codes for if statement, and following block.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            int           bytes    = 0;
            int           bytes2   = 0;
            VarTableEntry varEntry = null;

            try
            {
                // Gen op codes for boolean exp ( results in accum )
                bytes += expr.GenOpCodes(param);

                // Create new temp var
                varEntry = param.tables.CreateTempVarTableEntry();

                // Set in use flag
                varEntry.InUse = true;

                // Increment in use count
                param.tables.IncVarIsUseCount();

                // Move results into temp memory
                param.AddBytes(0x8D);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                // Load 1 into accum
                param.AddBytes(0xA2, 0x01);

                // Compare temp (res of expr) to true (1)
                param.AddBytes(0xEC);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                // Branch to end of block (using curBlockID, as gen op
                // will use this id and incremement it. The current
                // block at any time is really curBlockID - 1 ).
                param.AddBytes(0xD0);
                param.AddByteForUpdate('B', param.curBlockID);

                // Incrmeent bytes
                bytes += 10;

                // Set temp var not in use
                varEntry.InUse = false;

                // Decremeent in use count
                param.tables.DecVarInUseCount();

                // Gen op codes for block
                bytes += block.GenOpCodes(param);
            }

            // Catch over 256 byte error,
            // and throw up
            catch (IndexOutOfRangeException ex)
            {
                throw ex;
            }

            // Return bytes added
            return(bytes);
        }
        // Gens opp codes for int operation add.
        // Results are in the accum.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            VarTableEntry varEntry = null;
            int           bytes    = 0;
            int           bytes2   = 0;

            try
            {
                // Load accummulator with constant
                param.AddBytes(0xA9, (byte)intVal.Value);


                // Get avaialbe stack location
                varEntry = param.tables.CreateTempVarTableEntry();

                // Set in use flag
                varEntry.InUse = true;

                // Increment var in use flag
                param.tables.IncVarIsUseCount();

                // Store accumulator in stack location
                param.AddBytes(0x8D);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                // Increment bytes
                bytes += 5;

                // Check if expr is not null
                if (expr != null)
                {
                    // Gen op codes for expr
                    bytes2 += expr.GenOpCodes(param);
                }
                // Else expr is null
                else
                {
                    // Move 0 to accumulator
                    param.AddBytes(0xA9, 0x00);

                    // Increment bytes
                    bytes2 += 2;
                }

                // Add temp var to accumulator
                param.AddBytes(0x6D);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                // Increment bytes
                bytes2 += 3;

                // Set temp var not in use
                varEntry.InUse = false;

                // Decrement counter
                param.tables.DecVarInUseCount();
            }

            // Catch over 256 byte error,
            // and throw up
            catch (IndexOutOfRangeException ex)
            {
                throw ex;
            }

            // Return bytes added
            return(bytes + bytes2);
        }
        // Gens op codes for while loop.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            int           bytes     = 0;
            int           bytes2    = 0;
            int           jumpByte  = 0;
            int           startByte = param.curByte;
            VarTableEntry varEntry  = null;
            VarTableEntry varEntry2 = null;

            try
            {
                // Gen op codes for boolean exp ( results in accum )
                bytes += expr.GenOpCodes(param);

                // Create new temp var
                varEntry = param.tables.CreateTempVarTableEntry();

                // Set in use flag
                varEntry.InUse = true;

                // Increment in use count
                param.tables.IncVarIsUseCount();

                // Move results into temp memory
                //param.opCodes.AppendFormat("8D V{0} 00 ", varEntry.VarID);
                param.AddBytes(0x8D);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                // Incrmeent bytes
                bytes += 3;

                // Capture current byte (where to jump to at end of loop)
                jumpByte = param.curByte + bytes;

                // Load 1 into accum
                //param.opCodes.Append("A2 01 ");
                param.AddBytes(0xA2, 0x01);

                // Compare temp (res of expr) to true (1)
                //param.opCodes.AppendFormat("EC V{0} 00 ", varEntry.VarID);
                param.AddBytes(0xEC);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                // Branch to end of block, and 12 more to skip
                // forced jump to begining of while
                //param.opCodes.AppendFormat("D0 B{0}S{1} ", param.curBlockID, 12);
                param.AddBytes(0xD0);
                param.AddByteForUpdate('B', param.curBlockID, 12);

                // Incrmeent bytes
                bytes += 7;

                // Set current byte (for calling gen op)
                //param.curByte += 10;

                // Set temp var not in use
                varEntry.InUse = false;

                // Decremeent in use count
                param.tables.DecVarInUseCount();

                // Gen op codes for block
                bytes2 += block.GenOpCodes(param);

                // ### Force NE Jump ### //

                // Create another new temp var
                varEntry2 = param.tables.CreateTempVarTableEntry();

                // Set in use
                varEntry2.InUse = true;

                // Inc var in use count
                param.tables.IncVarIsUseCount();

                // Load 0 into acc
                //param.opCodes.Append("A9 00 ");
                param.AddBytes(0xA9, 0x00);

                // Load acc to temp var
                //param.opCodes.AppendFormat("8D V{0} 00 ", varEntry2.VarID);
                param.AddBytes(0x8D);
                param.AddByteForUpdate('V', varEntry2.VarID);
                param.AddBytes(0x00);

                // Load 1 into x reg
                //param.opCodes.Append("A2 01 ");
                param.AddBytes(0xA2, 0x01);

                // Compare temp to x (which will always be not equal )
                //param.opCodes.AppendFormat("EC V{0} 00 ", varEntry2.VarID);
                param.AddBytes(0xEC);
                param.AddByteForUpdate('V', varEntry2.VarID);
                param.AddBytes(0x00);

                // Incremeent bytes
                bytes2 += 12;

                // Update bytes ( I do it before next statmement for
                // caculation of accurate curByte )
                //param.curByte += 12;

                // Branch to top of while loop ( note these two bytes already
                // added to curByte )
                //param.opCodes.AppendFormat("D0 {0} ",(256 - param.curByte + startByte + 1).ToString("X2"));
                param.AddBytes(0xD0, (byte)(255 - (param.curByte - startByte + 1)));


                // Set temp var not in use
                varEntry2.InUse = false;

                // Decremeent in use count
                param.tables.DecVarInUseCount();
            }

            // Catch over 256 byte error,
            // and throw up
            catch (IndexOutOfRangeException ex)
            {
                throw ex;
            }


            // Return bytes added
            return(bytes + bytes2);
        }
Esempio n. 11
0
        // Gens op codes for print statment.
        // Calls system to print based on type of expr.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            int            bytes          = 0;
            VarTableEntry  varEntry       = null;
            VarTableEntry  varEntryTrue   = null;
            VarTableEntry  varEntryFalse  = null;
            HeapTableEntry heapEntryTrue  = null;
            HeapTableEntry heapEntryFalse = null;
            IDASTNode      idASTNode      = null;

            try
            {
                // Gen op codes for expr. Results in accum
                bytes += expr.GenOpCodes(param);

                // Create temp var on stack
                varEntry       = param.tables.CreateTempVarTableEntry();
                varEntry.InUse = true;
                param.tables.IncVarIsUseCount();

                // Load accumlator to memory (results from expr )
                //param.opCodes.AppendFormat("8D V{0} 00 ", varEntry.VarID);
                param.AddBytes(0x8D);
                param.AddByteForUpdate('V', varEntry.VarID);
                param.AddBytes(0x00);

                bytes += 3;

                // Inc cur bytes
                //param.curByte += 3;

                // Check if int expr, or var dec of type int
                if ((expr is IntExprASTNode) ||
                    ((expr is IDASTNode) && (((IDASTNode)expr).SymbolTableEntry.DataType == DataType.DT_INT)))
                {
                    // Load 1 int x reg
                    //param.opCodes.Append("A2 01 ");
                    param.AddBytes(0xA2, 0x01);

                    // Load into y register
                    //param.opCodes.AppendFormat("AC V{0} 00 ",varEntry.VarID);
                    param.AddBytes(0xAC);
                    param.AddByteForUpdate('V', varEntry.VarID);
                    param.AddBytes(0x00);

                    // Make system call
                    //param.opCodes.Append("FF ");
                    param.AddBytes(0xFF);

                    // Inc bytes
                    bytes += 6;

                    // Inc cur bytes
                    // param.curByte += 6;
                }
                // Else check if bool expr, or var dec with boolean type
                else if ((expr is BooleanExprASTNode) ||
                         ((expr is IDASTNode) && (((IDASTNode)expr).SymbolTableEntry.DataType == DataType.DT_BOOLEAN)))
                {
                    // Create strings for true and false on heap.
                    // If already on their it wont allocate new
                    // ones, but use the same.

                    heapEntryTrue  = param.tables.AddHeapTableEntry(param, "true");
                    heapEntryFalse = param.tables.AddHeapTableEntry(param, "false");


                    // Create temp vars on stack for true
                    varEntryTrue       = param.tables.CreateTempVarTableEntry();
                    varEntryTrue.InUse = true;
                    param.tables.IncVarIsUseCount();

                    // Create temp var on stack for false
                    varEntryFalse       = param.tables.CreateTempVarTableEntry();
                    varEntryFalse.InUse = true;
                    param.tables.IncVarIsUseCount();

                    // Load true string address in acc
                    //param.opCodes.AppendFormat("A9 H{0} ", heapEntryTrue.HeapID);
                    param.AddBytes(0xA9);
                    param.AddByteForUpdate('H', heapEntryTrue.HeapID);

                    // Move to temp var
                    //param.opCodes.AppendFormat("8D V{0} 00 ", varEntryTrue.VarID);
                    param.AddBytes(0x8D);
                    param.AddByteForUpdate('V', varEntryTrue.VarID);
                    param.AddBytes(0x00);


                    // Load true add in acc
                    //param.opCodes.AppendFormat("A9 H{0} ", heapEntryFalse.HeapID);
                    param.AddBytes(0xA9);
                    param.AddByteForUpdate('H', heapEntryFalse.HeapID);

                    // Move to temp var
                    //param.opCodes.AppendFormat("8D V{0} 00 ", varEntryFalse.VarID);
                    param.AddBytes(0x8D);
                    param.AddByteForUpdate('V', varEntryFalse.VarID);
                    param.AddBytes(0x00);



                    // Load false into y reg
                    //param.opCodes.AppendFormat("AC V{0} 00 ", varEntryFalse.VarID);
                    param.AddBytes(0xAC);
                    param.AddByteForUpdate('V', varEntryFalse.VarID);
                    param.AddBytes(0x00);

                    // Load 01 int x reg
                    //param.opCodes.Append("A2 01 ");
                    param.AddBytes(0xA2, 0x01);

                    // Compare results with results from acc
                    //param.opCodes.AppendFormat("EC V{0} 00 ", varEntry.VarID);
                    param.AddBytes(0xEC);
                    param.AddByteForUpdate('V', varEntry.VarID);
                    param.AddBytes(0x00);

                    // Branch on not equal x bytes
                    //param.opCodes.Append("D0 04 ");
                    param.AddBytes(0xD0, 0x03);

                    // Load true into y reg
                    //param.opCodes.AppendFormat("AC V{0} 00 ", varEntryTrue.VarID);
                    param.AddBytes(0xAC);
                    param.AddByteForUpdate('V', varEntryTrue.VarID);
                    param.AddBytes(0x00);

                    // Load 2 int x reg
                    //param.opCodes.Append("A2 02 ");
                    param.AddBytes(0xA2, 0x02);

                    // Make system call
                    //param.opCodes.Append("FF ");
                    param.AddBytes(0xFF);

                    // Inc bytes
                    bytes += 26;

                    // Inc cur bytes
                    //param.curByte += 26;

                    /*
                     * // Set temp vars not in use
                     * varEntryTrue.InUse = false;
                     * varEntryFalse.InUse = false;
                     * param.tables.DecVarInUseCount();
                     * param.tables.DecVarInUseCount();
                     * */
                }

                // Else check if string expr or var of string type
                else if ((expr is StringExprASTNode) ||
                         ((expr is IDASTNode) && (((IDASTNode)expr).SymbolTableEntry.DataType == DataType.DT_STRING)))
                {
                    // Load into temp var
                    //param.opCodes.AppendFormat("8D
                    // Load expr res into y reg
                    //param.opCodes.AppendFormat("AC V{0} 00 ", varEntry.VarID);
                    param.AddBytes(0xAC);
                    param.AddByteForUpdate('V', varEntry.VarID);
                    param.AddBytes(0x00);

                    // Load 2 int x reg
                    //param.opCodes.Append("A2 02 ");
                    param.AddBytes(0xA2, 0x02);

                    // Make system call
                    //param.opCodes.Append("FF ");
                    param.AddBytes(0xFF);

                    // Increment bytes
                    bytes += 6;

                    // Inc cur bytes
                    //param.curByte += 6;
                }

                // Reset temp var
                varEntry.InUse = false;
                param.tables.DecVarInUseCount();
            }

            // Catch over 256 byte error,
            // and throw up
            catch (IndexOutOfRangeException ex)
            {
                throw ex;
            }

            // Return bytes added
            return(bytes);
        }
Esempio n. 12
0
        // Gens op codes for all statments in block.
        // Manges which symbol table is current.
        // Keeps table of start and end of blocks.
        // All vars allocated on stack in this block
        // are set to not in use.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            int                 nextSymbIndex = 0;
            int                 bytesAdded    = 0;
            int                 block         = 0;
            ASTNode             curNode       = null;
            BlockSizeTableEntry entry         = null;
            VarTableEntry       varEntry      = null;
            SymbolHashTable     curSymbTable  = null;

            SymbolTableEntry[] symbEntries = null;
            DynamicBranchTreeNode <SymbolHashTable> startSymbolTable = null;

            // Get start symbol table
            startSymbolTable = param.curSymbTable;

            // Check if not root symbol table
            if (!param.firstBlock)
            {
                // Move into next symbol table child
                param.curSymbTable = param.curSymbTable.GetChild(param.curSymbTableIndex);


                // Record last symb index
                nextSymbIndex = param.curSymbTableIndex + 1;

                // Set current symbol table index to 0
                param.curSymbTableIndex = 0;
            }
            // Else root table
            else
            {
                // Set first block flag false
                param.firstBlock = false;
            }

            // Record current symbol table
            curSymbTable = param.curSymbTable.Data;

            // Add new entry to block size table
            entry = new BlockSizeTableEntry(param.curBlockID, param.curByte);
            param.tables.AddBlockSizeTableEntry(entry);
            param.curBlockID++;
            block = param.curBlockID - 1;

            // Cycle through stmts calling their gen op code
            curNode = this.leftMostChild;
            while (curNode != null)
            {
                // Try for over 256 bytes
                try
                {
                    // Call child statment gen op code method
                    bytesAdded += curNode.GenOpCodes(param);
                }

                // Catch over 256 bytes
                catch (IndexOutOfRangeException ex)
                {
                    throw ex;
                }

                // Get next symbling
                curNode = curNode.RightSibling;
            }

            // Reset cur symbol table index
            param.curSymbTableIndex = nextSymbIndex;

            // Reset cur symbol table
            param.curSymbTable = startSymbolTable;

            // Set end byte of block
            entry.EndByte = param.curByte - 1;

            // Remove out of scope vars from init var table
            param.tables.RemoveBlockVarEntries(block);

            // Cycle through symbol table
            symbEntries = curSymbTable.GetAllItems();
            for (int i = 0; i < symbEntries.Length; i++)
            {
                // Get item from temp var table
                varEntry = param.tables.GetVarTableEntry(symbEntries[i].EntryID);

                // Check if exists
                if (varEntry != null)
                {
                    // Set not in use flag
                    varEntry.InUse = false;

                    // Decrement var in use count
                    param.tables.DecVarInUseCount();
                }
            }

            // Return number of bytes
            return(bytesAdded);
        }
        // Fills in variable locations, heap locations, and jump size for
        // blocks in one pase. Collected some meta data about program.
        //
        // Returns: OpCodeData describing memory of program.
        private OpCodeData FillInTempOpCodeValues(OpCodeGenParam param)
        {
            // Inits
            int zeros       = 0;
            int num         = 0;
            int localOffSet = 0;
            int curByte     = 0;

            String[] strings = null;
            String   s       = null;

            String[]            offStrings  = null;
            String              o           = null;
            int                 len         = 0;
            VarTableEntry       varEntry    = null;
            HeapTableEntry      heapEntry   = null;
            BlockSizeTableEntry blockEntry  = null;
            OpCodeData          programData = new OpCodeData();
            TempByteData        byteData    = null;
            int                 location    = 0;

            // Determin stack size
            programData.stackSize  = param.tables.MaxVarUsage;
            programData.stackStart = param.curByte;

            // Determine heap size
            programData.heapSize  = param.tables.TotalHeapSize();
            programData.heapStart = param.curByte + programData.stackSize;



            // Write 00 over stack
            zeros = programData.stackSize;
            for (int i = 0; i < zeros; i++)
            {
                //param.opCodes.Append("00 ");
                param.AddBytes(0x00);
            }

            // Update size of file
            //param.curByte += zeros;

            // Send message
            SendGeneralMessage("Creating strings in memory...");

            // Fill in memory locations for heap
            for (int i = 0; i < param.tables.HeapTableCount(); i++)
            {
                heapEntry = param.tables.GetHeapTableEntryByIndex(i);

                heapEntry.MemoryLocation = programData.heapStart + curByte;

                // Write char
                for (int n = 0; n < heapEntry.StringValue.Length; n++)
                {
                    //param.opCodes.AppendFormat("{0} ", ((int)heapEntry.StringValue[n]).ToString("X2"));
                    param.AddBytes((byte)heapEntry.StringValue[n]);
                }
                //param.opCodes.Append("00 ");
                param.AddBytes(0x00);
                //param.curByte += heapEntry.Length + 1;

                curByte += heapEntry.Length;
            }

            // Send message
            SendGeneralMessage("String creation complete.");

            // Set program data size
            programData.totalBytes = param.curByte;


            // Cycle through codes
            for (int i = 0; i < param.insertBytes.Count; i++)
            {
                // Get byte data
                byteData = (TempByteData)param.insertBytes[i];

                // Get place holder string
                s = byteData.VarSymbol;

                // Check for V (var table
                if (s[0] == 'V')
                {
                    // Get number off string
                    num = int.Parse(s.Substring(1, s.Length - 1));

                    // Find entry
                    varEntry = param.tables.GetVarTableEntry(num);

                    // Replace entry with address
                    if (varEntry != null)
                    {
                        // Set location
                        location = programData.stackStart + varEntry.Offset;
                        param.SetByte(byteData.Index, (byte)(location));

                        if (varEntry.VarEntry != null)
                        {
                            varEntry.VarEntry.MemoryLocation = location;
                        }
                    }
                }
                // Check for H (heap)
                else if (s[0] == 'H')
                {
                    // Find length to s or end
                    len = s.Length;
                    for (int n = 1; n < s.Length; n++)
                    {
                        if (s[n] == 'S')
                        {
                            len = n;
                        }
                    }


                    // Get number off string
                    num = int.Parse(s.Substring(1, len - 1));


                    // Find entry
                    heapEntry = param.tables.GetHeapTableEntry(num);

                    // Split of F
                    offStrings = s.Split('S');


                    // Get offf num if valid
                    if (offStrings.Length > 1)
                    {
                        o = offStrings[1];

                        localOffSet = int.Parse(o.Substring(0, o.Length));
                    }
                    else
                    {
                        localOffSet = 0;
                    }


                    // Replace entry with address
                    if (heapEntry != null)
                    {
                        // strings[i] = String.Format("{0}", (heapEntry.MemoryLocation + localOffSet).ToString("X2"));
                        param.SetByte(byteData.Index, (byte)(heapEntry.MemoryLocation + localOffSet));
                    }
                }
                // Else if block parse flag
                else if (s[0] == 'B')
                {
                    // Find length to s or end
                    len = s.Length;
                    for (int n = 1; n < s.Length; n++)
                    {
                        if (s[n] == 'S')
                        {
                            len = n;
                        }
                    }

                    // Get number off string
                    num = int.Parse(s.Substring(1, len - 1));


                    // Find entry ( happens to work out that block id = index )
                    blockEntry = param.tables.GetBlockSizeTableEntry(num);


                    // Split of F
                    offStrings = s.Split('S');


                    // Get offf num if valid
                    if (offStrings.Length > 1)
                    {
                        o = offStrings[1];

                        localOffSet = int.Parse(o.Substring(0, o.Length));
                    }
                    else
                    {
                        localOffSet = 0;
                    }

                    // Replace entry with address
                    if (blockEntry != null)
                    {
                        //strings[i] = String.Format("{0}", (blockEntry.BlockSize + localOffSet).ToString("X2"));
                        param.SetByte(byteData.Index, (byte)(blockEntry.BlockSize + localOffSet));
                    }
                }
            }

            // Return program data
            return(programData);
        }
        // Gens op codes for comparision of boolean expr == or !=,
        // and puts results in accum. 1 for true, 0 for false.
        //
        // Returns: Number of bytes generated.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            VarTableEntry varEntryTemp = null;
            int           bytes        = 0;
            int           index        = 0;

            // ### Checking Expr 1 ### //

            // try for error
            try
            {
                // Gen op codes for expr one
                bytes += exprOne.GenOpCodes(param);

                // ### Check if not only bool val, as if it was  ### //
                // ### the value is just left in the accumulator ### //

                // Check if expr 2 is not null
                if (exprTwo != null)
                {
                    // ### Add acc results from expr 1 ### //

                    // Add temp var for expr one results
                    varEntryTemp = param.tables.CreateTempVarTableEntry();


                    // Set in use
                    varEntryTemp.InUse = true;


                    // Increment var in use
                    param.tables.IncVarIsUseCount();

                    // Move value of accumulator to temp var
                    param.AddBytes(0x8D);
                    param.AddByteForUpdate('V', varEntryTemp.VarID);
                    param.AddBytes(0x00);

                    // ### Generate expr 2 value and put in accumm ### //

                    // Gen op codes for expr two
                    bytes += exprTwo.GenOpCodes(param);


                    // ### Compare values of temp var (expr 1), and accum (expr2) ### //
                    // ### Put results in accumulator.                            ### //

                    // Load temp value from first expr into reg x
                    param.AddBytes(0xAE);
                    param.AddByteForUpdate('V', varEntryTemp.VarID);
                    param.AddBytes(0x00);

                    // Move accum into same temp val
                    param.AddBytes(0x8D);
                    param.AddByteForUpdate('V', varEntryTemp.VarID);
                    param.AddBytes(0x00);

                    // Increment bytes
                    bytes += 9;

                    // Check if equals
                    if (value == BOOLOP_TYPE.BOOLOP_EQUALS)
                    {
                        // Set false in accum "A9 00 "
                        param.AddBytes(0xA9, 0x00);
                    }
                    else
                    {
                        // Set true in accum
                        param.AddBytes(0xA9, 0x01);
                    }

                    // Compare x to temp var
                    param.AddBytes(0xEC);
                    param.AddByteForUpdate('V', varEntryTemp.VarID);
                    param.AddBytes(0x00);

                    // Branch 2 bytes if equl
                    param.AddBytes(0xD0, 0x02);

                    // Check if equals
                    if (value == BOOLOP_TYPE.BOOLOP_EQUALS)
                    {
                        // Set true in accum (skip in nnot equal)

                        param.AddBytes(0xA9, 0x01);
                    }
                    else
                    {
                        // Set false in accum (skip in nnot equal)
                        param.AddBytes(0xA9, 0x00);
                    }

                    // Increment bytes
                    bytes += 9;

                    // Reset in use flag for temp var
                    varEntryTemp.InUse = false;

                    // Decremeent in use flag
                    param.tables.DecVarInUseCount();
                }
            }

            // Throw error up
            catch (IndexOutOfRangeException ex)
            {
                throw ex;
            }

            // Return number of bytes
            return(bytes);
        }
        // Generates op codes for expr, which is put in accum.
        // This value is then loaded into var's value.
        //
        // Returns: Number of op code bytes added.
        public override int GenOpCodes(OpCodeGenParam param)
        {
            // Inits
            VarTableEntry     varEntry   = null;
            InitValueEntry    initEntry  = null;
            int               bytes      = 0;
            int               curByte    = param.curByte;
            bool              value      = false;
            StringExprASTNode stringNode = null;
            HeapTableEntry    heapEntry  = null;
            bool              initVar    = false;

            // Try for over 256 bytes
            try
            {
                // Get init value entry
                initEntry = param.tables.GetLastInitValueEntry(id.Value, id.SymbolTableEntry.DataType);

                // Check if value was already init
                if (initEntry != null)
                {
                    // Set init var
                    initVar = true;

                    // Check if int value
                    if (expr is IntValASTNode)
                    {
                        // Set byte with value
                        param.SetByte(initEntry.Index, (byte)((IntValASTNode)expr).Value);

                        // Set inital value in symbol table
                        id.SymbolTableEntry.IntValue = ((IntValASTNode)expr).Value;
                    }
                    else if (expr is BoolValASTNode)
                    {
                        // Get bool value
                        if (((BoolValASTNode)expr).Value == BOOLVAL_TYPE.BOOLVAL_TRUE)
                        {
                            value = true;
                        }
                        else
                        {
                            value = false;
                        }

                        // Set byte with value
                        param.SetByte(initEntry.Index, (byte)(value == true ? 1 : 0));

                        // Set inital value in symbol table
                        id.SymbolTableEntry.IntValue = (value == true ? 1 : 0);
                    }
                    else if (expr is StringExprASTNode)
                    {
                        stringNode = ((StringExprASTNode)expr);
                        heapEntry  = param.tables.AddHeapTableEntry(param, stringNode.Value);
                        param.AddInsertByte(initEntry.Index, 'H', heapEntry.HeapID, 0);

                        id.SymbolTableEntry.StringValue = stringNode.Value;
                    }
                    else
                    {
                        initVar = false;
                    }

                    // Remove from table if iniitalized
                    if (initVar)
                    {
                        param.tables.RemoveLastInitValueEntry(initEntry);
                        param.initVars++;
                    }
                }


                // Check if initialized optimization
                if (!initVar)
                {
                    // Gen op codes for expr , value in accum
                    bytes += expr.GenOpCodes(param);

                    // Retreive temp placehold from var table
                    varEntry = param.tables.GetVarTableEntry(id.SymbolTableEntry.EntryID);

                    // Move accumlator to memory "8D V{0} 00 "
                    param.AddBytes(0x8D);
                    param.AddByteForUpdate('V', varEntry.VarID);
                    param.AddBytes(0x00);

                    // Increment bytes
                    bytes += 3;
                }
            }

            // Catch over 256 bytes
            catch (IndexOutOfRangeException ex)
            {
                throw ex;
            }

            // Return bytesa added
            return(bytes);
        }