package builtin.system;
import builtin.BuiltinSub;
import gui.Constants;
import gui.Environment;
import gui.Heap;
import gui.Interpreter;
import gui.MintException;
import gui.Pointer;
import gui.PointerTools;
import gui.SmartList;
/**
*
* @author Oliver Chu
*/
public class Extract extends BuiltinSub {
private Interpreter habitat;
private Pointer gottenValue = null;
private static final long ONE_SECOND = 1000000000L;
private static final long TIME_LIMIT = ONE_SECOND * 8L;
private Thread thread = null;
public Extract(Interpreter i) {
habitat = i;
}
private Environment getEnvirons() {
return habitat.getEnv();
}
@Override
public Pointer apply(SmartList<Pointer> args) throws MintException {
Pointer singleArg = args.get(0);
if (singleArg.type == Constants.INT_TYPE) {
return Heap.allocateInt(~PointerTools.dereferenceInt(singleArg));
}
if (singleArg.type == Constants.TRUTH_TYPE) {
if (singleArg.value == 1) {
return Constants.ONE;
} else {
return new Pointer(Constants.INT_TYPE, 2);
}
}
if (singleArg.type == Constants.NULL_TYPE) {
return Constants.ZERO;
}
if (singleArg.type == Constants.REAL_TYPE) {
String realStr = PointerTools.dereferenceAsString(singleArg);
if (realStr.contains("inf")) {
return Heap.allocateInt(-2);
} else if (realStr.contains("undef") || realStr.contains("nan")) {
return Heap.allocateInt(-1);
}
}
String named = PointerTools.dereferenceString(singleArg);
if (named == null) {
return Constants.MINT_NULL;
}
Environment self = getEnvirons();
try {
long startTime = System.nanoTime();
thread = new Thread(new GetVariable(named, self));
thread.start();
while (gottenValue == null) {
if ((System.nanoTime() - startTime) > TIME_LIMIT) {
throw new MintException("Time limit exceeded.");
}
}
} catch (Throwable t) {
return Heap.allocateString("<error: " + t + ">");
}
if (gottenValue == null ||
(gottenValue.type == Constants.NULL_TYPE &&
gottenValue.value == 0)) {
return Constants.MINT_NULL;
}
SmartList<Pointer> listOfInts = new SmartList<Pointer>();
listOfInts.add(Heap.allocateInt(gottenValue.type));
listOfInts.add(Heap.allocateInt(gottenValue.value));
thread.interrupt();
thread = null;
return Heap.allocateList(listOfInts);
}
private class GetVariable implements Runnable {
private String varName = "NONE";
private Environment environs = null;
public GetVariable(String variableName, Environment e) {
varName = variableName;
environs = e;
}
@Override
public void run() {
try {
gottenValue =
Environment.deepSearchGetValue(varName, environs);
} catch (Throwable t) {
gottenValue = Constants.MINT_NULL;
}
}
}
}