package gui;
import builtin.graphics.ButtonManager;
import builtin.graphics.MintWindow;
import builtin.graphics.Shape;
import java.awt.image.BufferedImage;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
/**
*
* @author Oliver Chu
*/
public class Heap {
private static HashMap<Integer, String> names;
public static HashMap<Integer, String> strings;
private static HashMap<Integer, Double> reals;
private static HashMap<Integer, Message> messages;
private static HashMap<Integer, MintObject> objects;
private static HashMap<Integer, SmartList<Pointer>> lists;
private static HashMap<Integer, Table> tables;
private static HashMap<Integer, Subprogram> subprograms;
private static HashMap<Integer, Block> blocks;
private static HashMap<Integer, BigInteger> bigInts;
private static HashMap<Integer, BigDecimal> preciseReals;
private static HashMap<Integer, SmartList<Byte>> bytes;
private static HashMap<Integer, MintWindow> windows;
private static HashMap<Integer, ButtonManager> buttons;
private static ArrayList<Thread> threads;
private static HashMap<Integer, Interpreter> interpreters;
private static HashMap<Integer, Shape> shapes;
private static HashMap<Integer, Rational> rationals;
private static HashMap<Integer, BufferedImage> images;
private static int nextImageAddress;
private static int nextNameAddress;
private static int nextStringAddress;
private static int nextRealAddress;
private static int nextMessageAddress;
private static int nextObjectAddress;
private static int nextListAddress;
private static int nextSubprogramAddress;
private static int nextBlockAddress;
private static int nextSystemVar;
private static int nextBigIntAddress;
private static int nextPreciseRealAddress;
private static int nextBytesAddress;
private static int nextWindowAddress;
private static int nextButtonAddress;
private static int nextInterpreterAddress;
private static int nextShapeAddress;
private static int nextTableAddress;
private static int nextRationalAddress;
/** Swaps two variable values by editing pointers. */
public static void swapReals(Pointer first, Pointer second) {
if (first.type != Constants.REAL_TYPE ||
second.type != Constants.REAL_TYPE) {
return;
}
int addressFirst = first.value;
int addressSecond = second.value;
Double valueFirst = reals.remove(addressFirst);
Double valueSecond = reals.remove(addressSecond);
if (valueFirst == null) {
valueFirst = 0.0;
}
if (valueSecond == null) {
valueSecond = 0.0;
}
/** Swap the two numbers. */
reals.put(addressFirst, valueSecond);
reals.put(addressSecond, valueFirst);
}
Heap() {
names = new HashMap<Integer, String>();
strings = new HashMap<Integer, String>();
reals = new HashMap<Integer, Double>();
messages = new HashMap<Integer, Message>();
objects = new HashMap<Integer, MintObject>();
lists = new HashMap<Integer, SmartList<Pointer>>();
subprograms = new HashMap<Integer, Subprogram>();
blocks = new HashMap<Integer, Block>();
bigInts = new HashMap<Integer, BigInteger>();
preciseReals = new HashMap<Integer, BigDecimal>();
bytes = new HashMap<Integer, SmartList<Byte>>();
windows = new HashMap<Integer, MintWindow>();
buttons = new HashMap<Integer, ButtonManager>();
threads = new ArrayList<Thread>();
interpreters = new HashMap<Integer, Interpreter>();
shapes = new HashMap<Integer, Shape>();
tables = new HashMap<Integer, Table>();
rationals = new HashMap<Integer, Rational>();
images = new HashMap<Integer, BufferedImage>();
nextRationalAddress = 0;
nextBigIntAddress = 0;
nextPreciseRealAddress = 0;
nextNameAddress = 0;
nextStringAddress = 0;
nextRealAddress = 0;
nextMessageAddress = 0;
nextObjectAddress = 0;
nextListAddress = 0;
nextSubprogramAddress = 0;
nextBlockAddress = 0;
nextSystemVar = 0;
nextBytesAddress = 0;
nextWindowAddress = 0;
nextButtonAddress = 0;
nextInterpreterAddress = 0;
nextShapeAddress = 0;
nextTableAddress = 0;
nextImageAddress = 0;
}
public static void eraseAllExcept(SmartList<Pointer> values) {
SmartList<Byte> valueTypes = new SmartList<Byte>();
for (Pointer p : values) {
valueTypes.add(p.type);
}
//names = new HashMap<Integer, String>();
if (!valueTypes.contains(Constants.STR_TYPE))
strings = new HashMap<Integer, String>();
if (!valueTypes.contains(Constants.REAL_TYPE))
reals = new HashMap<Integer, Double>();
if (!valueTypes.contains(Constants.MESSAGE_TYPE))
messages = new HashMap<Integer, Message>();
if (!valueTypes.contains(Constants.OBJECT_TYPE))
objects = new HashMap<Integer, MintObject>();
if (!valueTypes.contains(Constants.LIST_TYPE))
lists = new HashMap<Integer, SmartList<Pointer>>();
if (!valueTypes.contains(Constants.SUBPROGRAM_TYPE))
subprograms = new HashMap<Integer, Subprogram>();
if (!valueTypes.contains(Constants.BLOCK_TYPE))
blocks = new HashMap<Integer, Block>();
if (!valueTypes.contains(Constants.BIG_INT_TYPE))
bigInts = new HashMap<Integer, BigInteger>();
if (!valueTypes.contains(Constants.PRECISE_REAL_TYPE))
preciseReals = new HashMap<Integer, BigDecimal>();
if (!valueTypes.contains(Constants.BYTES_TYPE))
bytes = new HashMap<Integer, SmartList<Byte>>();
if (!valueTypes.contains(Constants.WINDOW_TYPE))
windows = new HashMap<Integer, MintWindow>();
if (!valueTypes.contains(Constants.BUTTON_TYPE))
buttons = new HashMap<Integer, ButtonManager>();
threads = new ArrayList<Thread>();
if (!valueTypes.contains(Constants.INTERPRETER_TYPE))
interpreters = new HashMap<Integer, Interpreter>();
/* nextBigIntAddress = 0;
nextPreciseRealAddress = 0;
nextStringAddress = 0;
nextRealAddress = 0;
nextMessageAddress = 0;
nextObjectAddress = 0;
nextListAddress = 0;
nextSubprogramAddress = 0;
nextBlockAddress = 0;
nextSystemVar = 0;
nextBytesAddress = 0;
nextWindowAddress = 0;
nextButtonAddress = 0;
nextInterpreterAddress = 0; */
}
public static void keepThread(Thread t) {
threads.add(t);
}
public static Pointer getNextSystemVarName() {
nextSystemVar++;
return allocateName("$" + (nextSystemVar - 1));
}
public static void setString(int addr, String value) {
strings.put(addr, value);
if (addr >= nextStringAddress) {
nextStringAddress = addr + 1;
}
}
public static Message dereferenceMessage(int address) {
return messages.get(address);
}
public static String dereferenceString(int address) {
if (!strings.containsKey(address)) {
return null;
}
return strings.get(address);
}
/** Returns the name at the address. Note that this doesn't evaluate
* a name. Name evaluation is handled through environments, not the heap.
*/
public static String dereferenceName(int address) {
return names.get(address);
}
public static Double dereferenceReal(int address) {
return reals.get(address);
}
public static MintObject dereferenceObject(int address) {
return objects.get(address);
}
public static Rational derefRat(int address) {
return rationals.get(address);
}
public static SmartList<Pointer> dereferenceList(int address) {
return lists.get(address);
}
public static Subprogram dereferenceSub(int address) {
return subprograms.get(address);
}
public static Block dereferenceBlock(int address) {
return blocks.get(address);
}
public static BigInteger dereferenceBigInt(int address) {
return bigInts.get(address);
}
public static BigDecimal dereferencePreciseReal(int address) {
return preciseReals.get(address);
}
public static SmartList<Byte> dereferenceBytes(int address) {
return bytes.get(address);
}
public static MintWindow dereferenceWindow(int address) {
return windows.get(address);
}
public static ButtonManager dereferenceButton(int address) {
return buttons.get(address);
}
public static Interpreter dereferenceInterpreter(int address) {
return interpreters.get(address);
}
public static Table dereferenceTable(int address) {
return tables.get(address);
}
public static Shape dereferenceShape(int address) {
return shapes.get(address);
}
public static BufferedImage derefImg(int address) {
return images.get(address);
}
public static Pointer allocImg(BufferedImage value) {
images.put(nextImageAddress, value);
nextImageAddress++;
return new Pointer(Constants.IMG_TYPE, nextImageAddress - 1);
}
public static Pointer allocateName(String name) {
names.put(nextNameAddress, name);
nextNameAddress++;
return new Pointer(Constants.NAME_TYPE, nextNameAddress - 1);
}
public static Pointer allocateReal(double value) {
reals.put(nextRealAddress, value);
nextRealAddress++;
return new Pointer(Constants.REAL_TYPE, nextRealAddress - 1);
}
public static Pointer allocRat(Rational value) {
rationals.put(nextRationalAddress, value);
nextRationalAddress++;
return new Pointer(Constants.RAT_TYPE, nextRationalAddress - 1);
}
public static Pointer allocateTable(Table value) {
tables.put(nextTableAddress, value);
nextTableAddress++;
return new Pointer(Constants.TABLE_TYPE, nextTableAddress - 1);
}
public static Pointer allocateString(String value) {
// String allocation is memoized,
// exactly like how Java Strings are interned.
for (int key : strings.keySet()) {
if (strings.get(key).equals(value)) {
return new Pointer(Constants.STR_TYPE, key);
}
}
strings.put(nextStringAddress, value);
nextStringAddress++;
return new Pointer(Constants.STR_TYPE, nextStringAddress - 1);
}
public static Pointer allocateInt(int value) {
return new Pointer(Constants.INT_TYPE, value);
}
public static Pointer allocateTruth(boolean value) {
if (value)
return new Pointer(Constants.TRUTH_TYPE, 1);
return new Pointer(Constants.TRUTH_TYPE, 0);
}
public static Pointer allocateMessage(Message value) {
messages.put(nextMessageAddress, value);
nextMessageAddress++;
return new Pointer(Constants.MESSAGE_TYPE, nextMessageAddress - 1);
}
public static Pointer allocateObject(MintObject value) {
objects.put(nextObjectAddress, value);
nextObjectAddress++;
return new Pointer(Constants.OBJECT_TYPE, nextObjectAddress - 1);
}
public static Pointer allocateList(SmartList<Pointer> value) {
lists.put(nextListAddress, value);
nextListAddress++;
return new Pointer(Constants.LIST_TYPE, nextListAddress - 1);
}
public static Pointer allocateSub(Subprogram value) {
subprograms.put(nextSubprogramAddress, value);
nextSubprogramAddress++;
return new Pointer(Constants.SUBPROGRAM_TYPE,
nextSubprogramAddress - 1);
}
public static Pointer allocateBlock(Block value) {
blocks.put(nextBlockAddress, value);
nextBlockAddress++;
return new Pointer(Constants.BLOCK_TYPE, nextBlockAddress - 1);
}
public static Pointer allocateBigInt(BigInteger value) {
bigInts.put(nextBigIntAddress, value);
nextBigIntAddress++;
return new Pointer(Constants.BIG_INT_TYPE, nextBigIntAddress - 1);
}
public static Pointer allocatePreciseReal(BigDecimal value) {
preciseReals.put(nextPreciseRealAddress, value);
nextPreciseRealAddress++;
return new Pointer(Constants.PRECISE_REAL_TYPE,
nextPreciseRealAddress - 1);
}
public static Pointer allocateBytes(SmartList<Byte> value) {
bytes.put(nextBytesAddress, value);
nextBytesAddress++;
return new Pointer(Constants.BYTES_TYPE, nextBytesAddress - 1);
}
public static Pointer allocateWindow(MintWindow value) {
windows.put(nextWindowAddress, value);
nextWindowAddress++;
return new Pointer(Constants.WINDOW_TYPE, nextWindowAddress - 1);
}
public static Pointer allocateButton(ButtonManager value) {
buttons.put(nextButtonAddress, value);
nextButtonAddress++;
return new Pointer(Constants.BUTTON_TYPE, nextButtonAddress - 1);
}
public static Pointer allocateInterpreter(Interpreter i) {
interpreters.put(nextInterpreterAddress, i);
nextInterpreterAddress++;
return new Pointer(Constants.INTERPRETER_TYPE,
nextInterpreterAddress - 1);
}
public static Pointer allocateShape(Shape value) {
shapes.put(nextShapeAddress, value);
nextShapeAddress++;
return new Pointer(Constants.SHAPE_TYPE, nextShapeAddress - 1);
}
/** Since deallocation is somewhat buggy, this implementation is commented
* out for now.
*/
public static void deallocate(Pointer p) {
/* switch (p.type) {
case Constants.NAME_TYPE:
unallocatedNameAddresses.add(p.value);
names.remove(p.value);
break;
case Constants.REAL_TYPE:
unallocatedRealAddresses.add(p.value);
reals.remove(p.value);
break;
case Constants.STR_TYPE:
unallocatedStringAddresses.add(p.value);
strings.remove(p.value);
break;
default:
break;
}
*/
}
public static String realsToString() {
return reals.toString();
}
}