package gui;
import java.util.Iterator;
/**
*
* @author Oliver Chu
*/
public class Environment {
private SmartList<MintObject> frames;
private int thisPointer;
private String thisPointerName;
SmartList<Integer> thisPointers;
SmartList<String> thisPointerNames;
public Environment() {
frames = new SmartList<MintObject>();
frames.add(new MintObject());
thisPointer = -1;
thisPointerName = "";
thisPointers = new SmartList<Integer>();
thisPointerNames = new SmartList<String>();
thisPointers.add(-1);
thisPointerNames.add("");
}
public void eraseAll() {
frames = new SmartList<MintObject>();
}
void addFrame(MintObject frame) {
frames.add(frame);
}
MintObject pop() {
/* thisPointer = -1;
thisPointerName = ""; */
if (!thisPointers.isEmpty()) {
thisPointer = thisPointers.pop();
thisPointerName = thisPointerNames.pop();
}
return frames.pop();
}
public Pointer getValue(String name) throws MintException {
try {
if (name == null) {
return null;
}
if (thisPointer != -1) {
try {
Pointer p = frames.get(thisPointer).get(thisPointerName);
if (p != null) {
//System.out.println("P: " + p);
MintObject obj = PointerTools.dereferenceObject(p);
if (obj != null && obj.containsName(name)) {
return obj.get(name);
}
}
} catch (IndexOutOfBoundsException ex) {
}
}
for (int i = frames.size() - 1; i >= 0; i--) {
MintObject currentFrame = frames.get(i);
if (currentFrame.containsName(name)) {
return currentFrame.get(name);
}
}
Pointer p = deepSearchGetValue(name, this);
if (p != null) {
return p;
}
p = forwardSearchGetValue(name, this);
if (p != null) {
return p;
}
throw new MintException(name + " is not defined.");
} catch (NullPointerException ex) {
}
return Constants.MINT_NULL;
}
SmartList<MintObject> getFrames() {
return frames;
}
public int getCurrentFrameIndex() {
return frames.size() - 1;
}
public static Pointer forwardSearchGetValue(String name, Environment env) {
SmartList<MintObject> fr = env.getFrames();
for (int i = fr.size() - 3; i >= 0; i--) {
MintObject currentFrame = fr.get(i);
if (currentFrame.containsName(name))
return currentFrame.get(name);
for (Pointer p : currentFrame.values()) {
if (p.type == Constants.OBJECT_TYPE) {
Environment newEnv = new Environment();
newEnv.addFrame(PointerTools.dereferenceObject(p));
Pointer result = deepSearchGetValue(name, newEnv);
if (result != null)
return result;
}
}
}
return null;
}
public static Pointer deepSearchGetValue(String name, Environment env) {
SmartList<MintObject> fr = env.getFrames();
for (int i = fr.size() - 1; i >= 0; i--) {
MintObject currentFrame = fr.get(i);
if (currentFrame.containsName(name))
return currentFrame.get(name);
for (Pointer p : currentFrame.values()) {
if (p.type == Constants.OBJECT_TYPE) {
Environment newEnv = new Environment();
newEnv.addFrame(PointerTools.dereferenceObject(p));
Pointer result = deepSearchGetValue(name, newEnv);
if (result != null)
return result;
}
}
}
return null;
}
public void setThisPointer(int value) {
thisPointers.add(thisPointer);
thisPointer = value;
}
public void setThisPointerName(String value) {
thisPointerNames.add(thisPointerName);
thisPointerName = value;
}
void remove(String name) {
frames.get(frames.size() - 1).remove(name);
}
void put(SmartList<Pointer> nameReference, Pointer value)
throws MintException {
nameReference = ListTools.removePointers(nameReference,
new Pointer(Constants.KEYWORD_TYPE, Constants.OPEN_PAREN));
nameReference = ListTools.removePointers(nameReference,
new Pointer(Constants.KEYWORD_TYPE, Constants.CLOSE_PAREN));
SmartList<Pointer> objects = new SmartList<Pointer>();
SmartList<Pointer> lists = new SmartList<Pointer>();
SmartList<Integer> indexList = new SmartList<Integer>();
//SmartList<Boolean> nextIsList = new SmartList<Boolean>();
for (int i = 0; i < nameReference.size(); i++) {
Pointer p = nameReference.get(i);
Integer keyword = PointerTools.dereferenceKeyword(p);
if (keyword != null) {
switch (keyword) {
case Constants.DOT:
String objName = PointerTools.dereferenceName(
nameReference.get(i - 1));
MintObject obj = null;
SmartList<Pointer> list = null;
Iterator<Integer> indexIterator = indexList.iterator();
if (!lists.isEmpty() || !objects.isEmpty()) {
boolean gotFirst = false;
for (Pointer objN : objects) {
if (gotFirst) {
Pointer newObj = null;
if (objN.type == Constants.OBJECT_TYPE) {
obj = PointerTools.dereferenceObject(
objN);
} else if (obj != null) {
newObj = obj.get(PointerTools.
dereferenceName(objN));
}
String newObjName = null;
if (newObj != null)
newObjName = PointerTools.
dereferenceName(newObj);
if (newObj != null && (
obj.containsName(newObjName) ||
getValue(newObjName) != null)) {
Pointer newObjPtr = obj.get(newObjName);
if (newObjPtr.type ==
Constants.OBJECT_TYPE) {
obj =
PointerTools.dereferenceObject(
newObjPtr);
} else if (newObjPtr.type ==
Constants.LIST_TYPE) {
list = PointerTools.
dereferenceList(newObjPtr);
do {
Pointer next = list.get(
indexIterator.next());
if (next.type ==
Constants.LIST_TYPE) {
list = PointerTools.
dereferenceList(next);
continue;
} else if (next.type ==
Constants.OBJECT_TYPE) {
obj = PointerTools.
dereferenceObject(next);
}
} while (false);
//lastWasList = true;
}
}
} else {
if (objN != null) {
if (objN.type ==
Constants.OBJECT_TYPE) {
obj = PointerTools.
dereferenceObject(objN);
} else {
obj = PointerTools.
dereferenceObject(getValue(
PointerTools.dereferenceName(
objN)));
}
}
}
gotFirst = true;
}
} else {
if (objName != null) {
obj = PointerTools.dereferenceObject(
getValue(objName));
}
}
String member = PointerTools.dereferenceName(
nameReference.get(i + 1));
if (i + 1 == nameReference.size() - 1) {
obj.put(member, value);
return;
}
if (objName == null)
objects.add(nameReference.get(i - 1));
else
objects.add(Heap.allocateName(objName));
Pointer mem = Heap.allocateName(member);
try {
if (ListTools.findPointerValue(objects, mem) == -1)
{
objects.add(mem);
}
} catch (NullPointerException ex) {
}
break;
default:
throw new MintException("Unknown keyword: " + keyword);
}
}
if (p.type == Constants.LIST_TYPE) {
SmartList<Pointer> indexL = PointerTools.dereferenceList(p);
Integer index = PointerTools.dereferenceInt(indexL.get(0));
SmartList<Pointer> list = null;
String listName = PointerTools.dereferenceName(
nameReference.get(i - 1));
if (!lists.isEmpty() || !objects.isEmpty()) {
if (index != null)
indexList.add(index);
boolean gotFirst = false;
Iterator<Pointer> nameIterator = lists.iterator();
MintObject obj = null;
for (Integer _i : indexList) {
Iterator<Pointer> objNameIterator = objects.iterator();
if (gotFirst) {
Pointer newList = null;
if (list != null)
newList = list.get(_i);
if (newList != null) {
if (newList.type == Constants.LIST_TYPE) {
list = PointerTools.dereferenceList(
newList);
} else if (newList.type ==
Constants.OBJECT_TYPE) {
do {
obj = PointerTools.dereferenceObject(
newList);
Pointer n = objNameIterator.next();
Pointer next;
if (n.type == Constants.OBJECT_TYPE) {
next = n;
} else {
next = obj.get(PointerTools.
dereferenceName(n));
}
if (next.type ==
Constants.LIST_TYPE) {
list = PointerTools.
dereferenceList(next);
} else if (next.type ==
Constants.OBJECT_TYPE) {
obj = PointerTools.
dereferenceObject(next);
continue;
}
} while (false);
}
}
} else {
Pointer nxt = nameIterator.next();
if (nxt.type == Constants.NAME_TYPE) {
list = PointerTools.dereferenceList(getValue(
PointerTools.dereferenceName(nxt)));
} else {
list = PointerTools.dereferenceList(nxt);
}
list = PointerTools.dereferenceList(list.get(_i));
}
gotFirst = true;
}
} else {
if (listName != null) {
list = PointerTools.dereferenceList(
getValue(listName));
}
}
if (i == nameReference.size() - 1) {
list.set(index, value);
return;
}
if (listName == null)
lists.add(nameReference.get(i - 1));
else
lists.add(Heap.allocateName(listName));
indexList.add(index);
try {
if (list.get(index).type == Constants.OBJECT_TYPE) {
objects.add(list.get(index));
}
} catch (NullPointerException ex) {
}
}
}
}
void putAll(MintObject mo) {
if (frames.isEmpty())
frames.add(new MintObject());
frames.get(frames.size() - 1).putAll(mo);
}
public void put(String name, Pointer value) {
if (thisPointer != -1) {
Pointer po = frames.get(thisPointer).get(thisPointerName);
MintObject obj = null;
if (po != null)
obj = PointerTools.dereferenceObject(po);
if (obj != null && obj.containsName(name)) {
obj.put(name, value);
frames.get(thisPointer).put(thisPointerName,
Heap.allocateObject(obj));
} else {
frames.get(frames.size() - 1).put(name, value);
}
} else {
if (frames.isEmpty())
frames.add(new MintObject());
frames.get(frames.size() - 1).put(name, value);
}
}
@Override
public String toString() {
return frames.toString();
}
public int size() {
return frames.size();
}
}