using System; using System.Collections.Generic; using System.Text; namespace Sunweaver.VM { public class Memory { IList BaseMem; Dictionary Filters = new Dictionary(); public const Int16 MemorySlots = 999; public const Int16 MaxAbsoluteMemoryValue = 9999; public Memory() { BaseMem = new Int16[MemorySlots + 1]; } public IDictionary ChangesSinceLastFlatten { get { return Filters; } } public Memory(IList baseMemory) { if (baseMemory.Count < (MemorySlots + 1)) { throw new Exception(String.Format( @"Can't assign base memory because it has {0} slots and we're expecting at least {1} slots.", baseMemory.Count, MemorySlots + 1)); } BaseMem = baseMemory; } /// /// Copies the memory values (including from the filters) to the given integer array. /// It should have a length of MemorySlots + 1. /// public void CopyAndFlattenTo(Int16[] memory) { BaseMem.CopyTo(memory, 0); foreach (var pair in Filters) { memory[pair.Key] = pair.Value; } } /// /// Flattens and copies the memory values (including from the filters) to the given 'other' Memory instance. /// Because filters are collapsed, they're cleared. /// /// public void CopyAndFlattenTo(Memory other) { if (other.BaseMem is Int16[]) { CopyAndFlattenTo(other.BaseMem as Int16[]); other.Filters.Clear(); } else { // Can't do anything fancy, so just iterate over the memory one slot at a time for (int i = 0; i < MemorySlots; ++i) { other.BaseMem[i] = this[i]; other.Filters.Clear(); } } } /// /// Copies any saved filters to the base memory and clears the list of filters. /// public void Flatten() { foreach (var pair in Filters) { BaseMem[pair.Key] = pair.Value; } Filters.Clear(); } /// /// What the memory values are before filtering /// /// /// public Int16 GetBase(int index) { index = Math.Abs(index); if (index > MemorySlots) { throw new Exception(String.Format("Attempting to address a memory location" + " outside of the range [1, {0}] in a robot's virtual machine.", MemorySlots)); } if (index == 0) { // the 0th location always returns 0. return 0; } else { return BaseMem[index]; } } // default indexer public Int16 this[int index] { get { index = Math.Abs(index); if (index > MemorySlots) { throw new Exception(String.Format("Attempting to address a memory location" + " outside of the range [1, {0}] in a robot's virtual machine.", MemorySlots)); } if (index == 0) { // the 0th location always returns 0. return 0; } else if (Filters.ContainsKey(index)) { return Filters[index]; } else { return BaseMem[index]; } } set { index = Math.Abs(index); if (index > MemorySlots) { throw new Exception(String.Format("Attempting to address a memory location" + " outside of the range [1, {0}] in a robot's virtual machine.", MemorySlots)); } if (index == 0) { // store to 0 is a noop. return; } else { Filters[index] = value; } } } public static Int16 ModValueToMemoryStore(long value) { return (Int16)(value % (Memory.MaxAbsoluteMemoryValue + 1)); } public static Int16 ModMemlocToMemorySpace(long memloc) { return (Int16)(Math.Abs(memloc) % (Memory.MemorySlots + 1)); } } }