package gui;
import builtin.Constant;
import builtin.graphics.ButtonManager;
import builtin.graphics.MintWindow;
import builtin.graphics.Shape;
import builtin.graphics.ShowMessageBox;
import builtin.list.Remove;
import builtin.math.Infinity;
import builtin.string.Split;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Random;
import javax.imageio.ImageIO;
/**
* @author Oliver Chu
*/
public class Interpreter {
private SmartList<String> operators;
private Environment env;
private SmartList<Integer> loopProgramPointerStack;
private SmartList<Boolean> ifStack;
private SmartList<String> imports;
public Interpreter() {
String[] ops = {"=", "+=", "-=", "*=", "/=", "%=", "^=", "==", "!=",
"<", ">", "<=", ">=", "(", ")", "++", "--", ",", "[",
"]", "+", "-", "/", "*", "-/", "%", "^", ".", "//",
"/*", "*/", "..", "{", "}", "...", "?", ":"};
operators = new SmartList<String>(ops);
env = new Environment();
SmartList<Pointer> oneArg = new SmartList<Pointer>();
oneArg.add(Heap.allocateName("obj"));
env.put("alert", Heap.allocateSub(new Subprogram("alert", oneArg,
new ShowMessageBox())));
loopProgramPointerStack = new SmartList<Integer>();
ifStack = new SmartList<Boolean>();
imports = new SmartList<String>();
}
public Environment getEnv() {
return env;
}
public SmartList<String> getImports() {
return imports;
}
public Pointer run(String programNameOrCode, boolean isDirectCode)
throws MintException {
SmartList<SmartList<Pointer>> pointerLists =
loadProgram(programNameOrCode, isDirectCode);
SmartList<String> _imports = new SmartList<String>();
if (!isDirectCode) {
imports.add(programNameOrCode);
}
return execute(pointerLists, _imports, new Environment());
}
private SmartList<Pointer> convertStringsToPointers(
SmartList<String> strings) {
SmartList<Pointer> pointerList = new SmartList<Pointer>();
for (String s : strings) {
pointerList.add(evaluateString(s));
}
return pointerList;
}
/** Get arg is a very poorly written method.
* This is the reason Mint breaks on:
*
* someList = [8, 9, 100, 200]
* otherList = []
* otherList.add(someList[0])
* Which ACTUALLY evaluates to:
* otherList.add(someList([0]))
*
* The seemingly extra closing paren breaks it.
* You need an option for findFirst so that it is not dumb
* and can ignored nexted [ ... ] and ( ... )
*
* This method assumes findFirst is intelligent enough to take
* care of such things. However, findFirst simply does a linear
* search, without bothering to check for nested expressions.
*
* Either rewrite findFirst to be smarter (seems like a good
* and easy choice), or rewrite this particular method
* to be smarter. Or both.
*
* Also, make sure that get args (apparently different?) does NOT
* have this issue!
* @throws MintException
*/
private Pointer getArg(SmartList<Pointer> pointerList, int i, int argNum)
throws MintException {
if (argNum == 0) {
int end = ListTools.findFirst(pointerList, Constants.COMMA);
int end2 = ListTools.findFirst(pointerList, Constants.CLOSE_PAREN);
/* if (end == -1 && end2 == -1)
return null;*/
if (end == -1)
end = pointerList.size();
if (end2 == -1)
end2 = pointerList.size();
return evalExpression(new SmartList<Pointer>(
pointerList.subList(i, Math.max(i, Math.min(end, end2)))),
0);
} else {
while (argNum > 0) {
i = 1 + ListTools.findFirst(pointerList, Constants.COMMA);
argNum--;
}
int end = i + ListTools.findFirst(pointerList.subList(i),
Constants.COMMA);
int end2 = i + ListTools.findFirst(pointerList.subList(i),
Constants.CLOSE_PAREN);
/* if (end == i - 1 && end2 == i - 1)
return null;*/
if (end == i - 1)
end = pointerList.size();
if (end2 == i - 1)
end2 = pointerList.size();
return evalExpression(new SmartList<Pointer>(
pointerList.subList(i, Math.min(end, end2))), 0);
}
}
//<editor-fold defaultstate="collapsed" desc="Method loadProgram">
public SmartList<SmartList<Pointer>> loadProgram(String programNameOrCode,
boolean isDirectCode) throws MintException {
SmartList<SmartList<String>> tokenLists =
new SmartList<SmartList<String>>();
SmartList<SmartList<Pointer>> pointerLists =
new SmartList<SmartList<Pointer>>();
String code = "";
if (isDirectCode) {
code = programNameOrCode;
} else {
code = FileIO.fileToStr(programNameOrCode);
}
// Note: if the user wants a real tab, he must use
// double backslash t. (\\t)
code = code.replace("\t", " ");
// TODO: Make sure that you still have table functionality
// Even WITHOUT these two lines of bad code.
// --> SEE StrTools.splitOnNoQuotes.
/* code = code.replace("{", "[");
code = code.replace("}", "]"); */
int k = 0;
String newCode = "";
while (k < code.length()) {
if (StrTools2.slice(code, k, k + 2).equals("\"\"")) {
if (code.charAt(k - 1) == '\\') {
newCode += "\"";
} else {
newCode += "\"a\".remove(\"a\")";
k++;
}
} else {
newCode += code.charAt(k);
}
k++;
}
code = newCode;
String QUOTE = "\"";
String BACKSLASH = "\\";
//code = code.replace("\"\"", "\"a\".remove(\"a\")");
code = code.replace(BACKSLASH + QUOTE + QUOTE, "\\q\"");
code = code.replace(BACKSLASH + BACKSLASH, "\\");
String[] parts = code.split("\n");
for (int m = 0; m < parts.length; ++m) {
String current = parts[m];
String viewed = current.trim();
if (viewed.startsWith("<define>")) {
// Perform define macro.
} else if (viewed.startsWith("<indexed-by>")) {
// Change indexing.
} else if (viewed.startsWith("<ignore>")) {
// Ignore items.
} else if (viewed.endsWith(":") || viewed.endsWith("{")
|| viewed.endsWith("(") || viewed.endsWith("[") ||
viewed.endsWith("<")) {
parts[m] = StrTools2.slice(current, 0, -1);
} else if (viewed.equals(":") || viewed.equals("}")
|| viewed.equals(")") || viewed.equals("]")
|| viewed.equals(">")) {
parts[m] = "end";
} else if ((viewed.startsWith("if ") ||
viewed.startsWith("when ")) &&
!viewed.contains("==") && !viewed.contains("!=")) {
parts[m] = current.replace("=", "==");
}
String original = parts[m];
parts[m] = parts[m].replace(".append(", "+=[");
parts[m] = parts[m].replace(".add(", "+=[");
if (!original.equals(parts[m])) {
parts[m] = StrTools2.slice(parts[m], 0, -1) + "]";
}
parts[m] = parts[m].replace("**", "//");
parts[m] = parts[m].replace("(*", "__BLOCOMM__");
parts[m] = parts[m].replace("*)", "__/COMM__");
parts[m] = parts[m].replace("/*", "__BLOCOMM__");
parts[m] = parts[m].replace("*/", "__/COMM__");
parts[m] = parts[m].replace("*", " ");
parts[m] = parts[m].replace("__BLOCOMM__", "/*");
parts[m] = parts[m].replace("__/COMM__", "*/");
}
String xCode = "";
for (String part : parts) {
xCode += "\n" + part;
}
code = StrTools2.slice(xCode, 1);
boolean inQuotes = false;
newCode = "";
for (int i = 0; i < code.length(); i++) {
char c = code.charAt(i);
if (c == ';') {
if (!inQuotes) {
newCode += "\n";
} else {
newCode += ";";
}
} else if (c == '"' && i - 1 > 0 && code.charAt(i - 1) != '\\') {
inQuotes = !inQuotes;
newCode += "\"";
} else {
newCode += c;
}
}
code = newCode;
code = code.replace("\r", "\n");
code = code.replace("\n\n", "\n");
String[] lines = code.split("\n");
for (String line : lines) {
String[] pieces = StrTools.splitOnNoQuotes(line, operators);
if (pieces.length > 0) {
// Should we make an inline function?
if (pieces[0].equals(StrTools.MANA) ||
pieces[0].hashCode() == StrTools.MANA.hashCode()) {
// We are naming an inline function.
tokenLists.add(new SmartList<String>(
new String[]{"sub", pieces[1], "(", pieces[2], ")"})
);
SmartList<String> ret = new SmartList<String>();
ret.add("return");
ret.addAll(new SmartList<String>(pieces[3].split(" ")));
tokenLists.add(ret);
tokenLists.add(new SmartList<String>(
new String[]{"end"})
);
} else {
tokenLists.add(new SmartList<String>(pieces));
}
}/*
else { do nothing because why do we need to exec empty lines? }
*/
}
// Pad end statements with nulls:
int j = 0;
boolean skipNext = false;
for (SmartList<String> list : tokenLists) {
for (int i = 0; i < list.size(); i++) {
if (!skipNext) {
if (list.get(i).equals("end")) {
SmartList<String> list1 = new SmartList<String>();
list1.add("null");
SmartList<String> list2 = new SmartList<String>();
list2.add("end");
SmartList<SmartList<String>> bigList =
new SmartList<SmartList<String>>();
bigList.add(list1);
bigList.add(list2);
tokenLists.assignSublist(j, j + 1, bigList);
skipNext = true;
}
} else {
skipNext = false;
}
}
j++;
}
// Pad else statements with nulls:
for (j = 0; j < tokenLists.size(); j++) {
SmartList<String> list = tokenLists.get(j);
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("else")) {
SmartList<String> list1 = new SmartList<String>();
list1.add("null");
SmartList<SmartList<String>> bigList =
new SmartList<SmartList<String>>();
bigList.add(list1);
bigList.add(list);
tokenLists.assignSublist(j, j + 1, bigList);
j++;
}
}
}
// Remove empty strings:
j = 0;
for (SmartList<String> list : tokenLists) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).isEmpty()) {
list.remove(i);
i--;
}
}
j++;
}
for (SmartList<String> list : tokenLists) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).contains(";") &&
!list.get(i).startsWith("\"")) {
list.set(i, list.get(i).replace(";", ""));
if (list.get(i).isEmpty()) {
list.remove(i);
i--;
}
} else if (list.get(i).isEmpty()) {
list.remove(i);
i--;
}
}
}
for (int i = 0; i < tokenLists.size(); i++) {
if (tokenLists.get(i).isEmpty()) {
tokenLists.remove(i);
i--;
}
}
// Combine compound operators:
for (SmartList<String> list : tokenLists) {
for (String op : operators) {
if (op.length() == 2) {
for (int i = 0; i < list.size() - 1; i++) {
boolean isLengthOne = list.get(i).length() == 1 &&
list.get(i + 1).length() == 1;
boolean isCompound = false;
if (isLengthOne) {
isCompound = list.get(i).charAt(0) ==
op.charAt(0) &&
list.get(i + 1).charAt(0) ==
op.charAt(1);
}
if (isLengthOne && isCompound) {
list.assignSublist(i, i + 2, op);
}
}
}
}
}
// Remove line comments and block comments:
int savedJ = 0;
int savedI = 0;
for (j = 0; j < tokenLists.size(); j++) {
SmartList<String> list = tokenLists.get(j);
int counter = 0;
for (int i = 0; i < list.size(); i++) {
String current = list.get(i);
if (current.equals("//")) {
list = new SmartList<String>(list.subList(0, i));
} else if (current.equals("/*")) {
savedJ = j;
savedI = i;
} else if (current.equals("*/")) {
SmartList<String> list2 = list.subList(i + 1);
SmartList<String> list1 = new SmartList<String>(
tokenLists.get(savedJ).subList(0, savedI));
SmartList<String> newList = new SmartList<String>();
newList.addAll(list1);
newList.addAll(list2);
tokenLists.assignSublist(savedJ, j + 1, newList);
j = savedJ;
i = savedI + 1;
}
counter++;
if (counter > 10000)
break;
}
}
for (SmartList<String> list : tokenLists) {
for (int i = 0; i < list.size(); i++) {
String current = list.get(i);
if (current.equals("[")) {
String[] paren = {"(", "["};
list.assignSublist(i, i + 1, new SmartList<String>(paren));
i++;
} else if (current.equals("]")) {
String[] paren = {"]", ")"};
list.assignSublist(i, i + 1, new SmartList<String>(paren));
}
}
}
j = 0;
for (SmartList<String> list : tokenLists) {
for (int i = 0; i < list.size(); i++) {
String current = list.get(i);
if (current.equals("{")) {
/* SmartList<String> list1 = new SmartList<String>(
list.subList(0, i));
SmartList<String> list2 = list.subList(i + 1);
SmartList<SmartList<String>> newList =
new SmartList<SmartList<String>>();
newList.add(list1);
newList.add(list2);
tokenLists.assignSublist(j, j + 1, newList); */
list.remove(i);
i--;
} else if (current.equals("}")) {
SmartList<String> list1 = new SmartList<String>(
list.subList(0, i));
SmartList<String> list2 = new SmartList<String>();
SmartList<String> list3 = list.subList(i + 1);
list2.add("null");
list3.add(0, "end");
SmartList<SmartList<String>> newList =
new SmartList<SmartList<String>>();
newList.add(list1);
newList.add(list2);
newList.add(list3);
tokenLists.assignSublist(j, j + 1, newList);
}
}
j++;
}
//Delete ends before elses (the ends were curly braces):
for (SmartList<String> list : tokenLists) {
if (list.size() >= 2 && list.get(0).equals("end") &&
list.get(1).equals("else")) {
list.assignSublist(0, 2, "else");
}
}
//Combine else and if into elseif:
for (SmartList<String> list : tokenLists) {
if (list.size() >= 2 && list.get(0).equals("else") &&
list.get(1).equals("if")) {
list.assignSublist(0, 2, "elseif");
}
}
//Combine for and each into foreach:
for (SmartList<String> list : tokenLists) {
if (list.size() >= 2 && list.get(0).equals("for") &&
list.get(1).equals("each")) {
list.assignSublist(0, 2, "foreach");
}
}
// Combine floating point literals:
for (SmartList<String> list : tokenLists) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(".") || list.get(i).equals("-") &&
i > 0 && i < list.size() - 1) {
try {
String potentialReal = list.get(i - 1) +
list.get(i) + list.get(i + 1);
Double.parseDouble(potentialReal);
list.assignSublist(i - 1, i + 2, potentialReal);
} catch (NumberFormatException ex) {
// Ignore error.
} catch (IndexOutOfBoundsException ex) {
// Ignore error.
}
}
}
}
for (SmartList<String> tokenList : tokenLists) {
pointerLists.add(convertStringsToPointers(tokenList));
}
return pointerLists;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Method convertKeywordToOperator">
public static String convertKeywordToOperator(int keyword) {
switch (keyword) {
case Constants.PLUS:
return "+";
case Constants.MINUS:
return "-";
case Constants.MULTIPLY:
return "*";
case Constants.DIVIDE:
return "/";
case Constants.FLOOR_DIVIDE:
return "-/";
case Constants.MODULO:
return "%";
case Constants.POWER:
return "^";
case Constants.INPUT:
return "input";
case Constants.OPEN_PAREN:
return "(";
case Constants.CLOSE_PAREN:
return ")";
case Constants.DOT:
return ".";
case Constants.EQUAL:
return "==";
case Constants.NOT_EQUAL:
return "!=";
case Constants.GTR_THAN:
return ">";
case Constants.LESS_THAN:
return "<";
case Constants.GTR_OR_EQUAL:
return ">=";
case Constants.LESS_OR_EQUAL:
return "<=";
case Constants.QUOTE:
return "\"";
case Constants.ASSIGN:
return "=";
case Constants.PRINT:
return "print";
case Constants.AND:
return "and";
case Constants.OR:
return "or";
case Constants.XOR:
return "xor";
case Constants.NOT:
return "not";
case Constants.OPEN_BRACKET:
return "[";
case Constants.CLOSE_BRACKET:
return "]";
case Constants.COMMA:
return ",";
case Constants.DOUBLE_DOT:
return "..";
case Constants.SHOW:
return "show";
case Constants.IMPORT:
return "import";
case Constants.INTO:
return "into";
case Constants.IF:
return "if";
case Constants.END:
return "end";
case Constants.ELSE:
return "else";
case Constants.WHILE:
return "while";
case Constants.BREAK:
return "break";
case Constants.CONTINUE:
return "continue";
case Constants.REPEAT:
return "repeat";
case Constants.RETURN:
return "return";
case Constants.SUB:
return "sub";
case Constants.FOR:
return "for";
case Constants.WHEN:
return "when";
case Constants.FOREACH:
return "foreach";
case Constants.ELSEIF:
return "elseif";
case Constants.INCREMENT:
return "++";
case Constants.DECREMENT:
return "--";
case Constants.RUN:
return "run";
case Constants.BLOCK:
return "block";
case Constants.LEAVE:
return "leave";
case Constants.INHERIT:
return "inherit";
case Constants.OF:
return "of";
case Constants.IN:
return "in";
case Constants.PLUS_ASSIGN:
return "+=";
case Constants.MINUS_ASSIGN:
return "-=";
case Constants.MULTIPLY_ASSIGN:
return "*=";
case Constants.DIVIDE_ASSIGN:
return "/=";
case Constants.MODULO_ASSIGN:
return "%=";
case Constants.POWER_ASSIGN:
return "^=";
case Constants.ELLIPSIS:
return "...";
default:
return "<keyword " + keyword + ">";
}
}
//</editor-fold>
/** Parses a string into a value and returns a pointer to that value. */
//<editor-fold defaultstate="collapsed" desc="Method evaluate string">
private Pointer evaluateString(String s) {
if (operators.contains(s)) {
if (s.equals("+")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.PLUS);
} else if (s.equals("-")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.MINUS);
} else if (s.equals("*")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.MULTIPLY);
} else if (s.equals("^")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.POWER);
} else if (s.equals("/")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.DIVIDE);
} else if (s.equals("-/")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.FLOOR_DIVIDE);
} else if (s.equals("%")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.MODULO);
} else if (s.equals("(")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_PAREN);
} else if (s.equals(")")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.CLOSE_PAREN);
} else if (s.equals(".")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.DOT);
} else if (s.equals("\"")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.QUOTE);
} else if (s.equals("=")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.ASSIGN);
} else if (s.equals("+=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.PLUS_ASSIGN);
} else if (s.equals("-=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.MINUS_ASSIGN);
} else if (s.equals("*=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.MULTIPLY_ASSIGN);
} else if (s.equals("/=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.DIVIDE_ASSIGN);
} else if (s.equals("%=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.MODULO_ASSIGN);
} else if (s.equals("^=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.POWER_ASSIGN);
} else if (s.equals("==")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.EQUAL);
} else if (s.equals("!=")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.NOT_EQUAL);
} else if (s.equals(">")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.GTR_THAN);
} else if (s.equals("<")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.LESS_THAN);
} else if (s.equals(">=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.GTR_OR_EQUAL);
} else if (s.equals("<=")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.LESS_OR_EQUAL);
} else if (s.equals("++")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.INCREMENT);
} else if (s.equals("--")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.DECREMENT);
} else if (s.equals("..")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.DOUBLE_DOT);
} else if (s.equals(",")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.COMMA);
} else if (s.equals("[")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_BRACKET);
} else if (s.equals("]")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.CLOSE_BRACKET);
} else if (s.equals("//")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.LINE_COMMENT);
} else if (s.equals("{")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_BRACE);
} else if (s.equals("}")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.CLOSE_BRACE);
} else if (s.equals("?")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.YIELD);
} else if (s.equals(":")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.OTHERWISE);
}
/* ... etc. */
} else {
if (s.equals("true")) {
return new Pointer(Constants.TRUTH_TYPE, 1);
} else if (s.equals("false")) {
return new Pointer(Constants.TRUTH_TYPE, 0);
} else if (s.equals("null")) {
return new Pointer(Constants.NULL_TYPE, 0);
} else if (s.equals("input")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.INPUT);
} else if (s.equals("print")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.PRINT);
} else if (s.equals("show")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.SHOW);
} else if (s.equals("when")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.WHEN);
} else if (s.equals("if")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.IF);
} else if (s.equals("end")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.END);
} else if (s.equals("else")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.ELSE);
} else if (s.equals("elseif")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.ELSEIF);
} else if (s.equals("while")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.WHILE);
} else if (s.equals("repeat")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.REPEAT);
} else if (s.equals("continue")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.CONTINUE);
} else if (s.equals("break")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.BREAK);
} else if (s.equals("return")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.RETURN);
} else if (s.equals("sub")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.SUB);
} else if (s.equals("and")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.AND);
} else if (s.equals("or")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.OR);
} else if (s.equals("xor")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.XOR);
} else if (s.equals("not")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.NOT);
} else if (s.equals("run")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.RUN);
} else if (s.equals("block")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.BLOCK);
} else if (s.equals("leave")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.LEAVE);
} else if (s.equals("inherit")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.INHERIT);
} else if (s.equals("import")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.IMPORT);
} else if (s.equals("into")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.INTO);
} else if (s.equals("for")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.FOR);
} else if (s.equals("foreach")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.FOREACH);
} else if (s.equals("of")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.OF);
} else if (s.equals("in")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.IN);
} else if (s.equals("erase")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.ERASE);
} else if (s.equals("all")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.ALL);
} else if (s.equals("except")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.EXCEPT);
} else if (s.equals("switch")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.SWITCH);
} else if (s.equals("case")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.CASE);
} else if (s.equals("default")) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.DEFAULT);
} else if (s.startsWith("\"") && s.endsWith("\"")) {
String str = s.substring(1, s.length() - 1);
return Heap.allocateString(StrTools.unescape(str));
} else if (s.equals("given")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.GIVEN);
} else if (s.equals("yield")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.YIELD);
} else if (s.equals("otherwise")) {
return new Pointer(Constants.KEYWORD_TYPE,
Constants.OTHERWISE);
}
try {
int i = Integer.parseInt(s);
return new Pointer(Constants.INT_TYPE, i);
} catch (NumberFormatException ex1) {
try {
double d = Double.parseDouble(s);
return Heap.allocateReal(d);
} catch (NumberFormatException ex2) {
//We cannot parse this literal, so it must be a name.
return Heap.allocateName(s);
}
}
}
// This line will never be executed:
return null;
}
//</editor-fold>
/** Converts a name pointer into a value pointer. If the pointer is not
* a name pointer, simply returns it.
*/
private Pointer evaluateName(Pointer p, Environment env)
throws MintException {
if (p == null || p.type != Constants.NAME_TYPE)
return p;
String name = PointerTools.dereferenceName(p);
return env.getValue(name);
}
private boolean shouldEvalParentheses(SmartList<Pointer> pointerList,
Environment env) {
boolean hasParentheses = ListTools.containsPointer(pointerList,
new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_PAREN));
boolean isNotDefinition = !ListTools.containsPointer(pointerList,
new Pointer(Constants.KEYWORD_TYPE, Constants.SUB));
int beforeParenIndex = Math.max(0, ListTools.findFirst(pointerList,
Constants.OPEN_PAREN) - 1);
String name = null;
if (pointerList.get(beforeParenIndex) != null)
name = PointerTools.dereferenceName(
pointerList.get(beforeParenIndex));
boolean isNotSubprogramCall = name == null ||
(Environment.deepSearchGetValue(name, env) != null &&
Environment.deepSearchGetValue(name, env).type !=
Constants.SUBPROGRAM_TYPE &&
pointerList.get(beforeParenIndex).type !=
Constants.SUBPROGRAM_TYPE &&
!Constants.BUILTIN_METHODS.contains(name));
return hasParentheses && isNotDefinition && isNotSubprogramCall;
}
private boolean shouldEvalDot(SmartList<Pointer> pointerList) {
int i = ListTools.findFirst(pointerList, Constants.DOT);
int j = ListTools.findFirst(pointerList, Constants.ASSIGN);
if (i == -1)
return false;
if (j == -1)
return true;
return j < i;
}
private boolean shouldEvalIndex(SmartList<Pointer> pointerList) {
int i = ListTools.findFirstType(pointerList, Constants.LIST_TYPE);
int j = ListTools.findFirst(pointerList, Constants.ASSIGN);
if (i == -1)
return false;
if (j == -1)
return true;
return j < i;
}
private Pointer showOrPrint(SmartList<Pointer> pointerList, int i,
boolean isShow) throws MintException {
SmartList<Pointer> sList = pointerList.subList(i + 1);
Pointer result;
if (sList.size() == 1)
result = pointerList.get(i + 1);
else
result = evalExpression(sList, 0);
result = evaluateName(result, env);
if (result != null) {
if (result.type == Constants.STR_TYPE) {
if (isShow) {
System.out.print(PointerTools.dereferenceString(result));
} else {
System.out.println(PointerTools.dereferenceString(result));
}
} else {
if (isShow) {
System.out.print(result);
} else {
System.out.println(result);
}
}
} else {
System.out.println("Java Virtual Machine null");
/* throw new MintException(
"Java null passed to print in expression: " + pointerList +
" with scope: " + env.pop()); */
}
return result;
}
private SmartList<Pointer> getArgNames(SmartList<Pointer> pointerList,
int i) {
pointerList = pointerList.subList(i);
int first = ListTools.findFirst(pointerList, Constants.OPEN_PAREN);
int next = ListTools.findMatchingCloseParen(pointerList, first + 1);
SmartList<Pointer> args = new SmartList<Pointer>(
pointerList.subList(first + 1, next));
args = ListTools.removePointers(args,
new Pointer(Constants.KEYWORD_TYPE, Constants.COMMA));
return args;
}
private SmartList<Pointer> getArgs(SmartList<Pointer> pointerList,
int start, int neededArgs)
throws MintException {
if (neededArgs == 0)
return new SmartList<Pointer>();
pointerList = pointerList.subList(start);
int first = ListTools.findFirst(pointerList, Constants.OPEN_PAREN);
int last = ListTools.findMatchingCloseParen(pointerList, first + 1);
SmartList<Pointer> args =
new SmartList<Pointer>(pointerList.subList(first + 1, last));
SmartList<SmartList<Pointer>> argLists =
ListTools.splitListOnCommas(args);
args = new SmartList<Pointer>();
for (SmartList<Pointer> eachArgList : argLists) {
Pointer value = evalExpression(eachArgList, 0);
if (value != null) {
args.add(value);
}
}
return args;
}
private SmartList<Pointer> getElementsTable(SmartList<Pointer> pointerList,
int start)
throws MintException {
pointerList = pointerList.subList(start);
int first = ListTools.findFirst(pointerList, Constants.OPEN_BRACE);
int last = ListTools.findMatchingCloseBracket(pointerList, first + 1);
SmartList<Pointer> elems =
new SmartList<Pointer>(pointerList.subList(first + 1, last));
SmartList<SmartList<Pointer>> elemLists =
ListTools.splitListOnCommas(elems);
elems = new SmartList<Pointer>();
for (SmartList<Pointer> eachElemList : elemLists) {
Pointer value = evalExpression(eachElemList, 0);
if (value != null) {
elems.add(value);
}
}
return elems;
}
private SmartList<Pointer> getElements(SmartList<Pointer> pointerList,
int start)
throws MintException {
pointerList = pointerList.subList(start);
int first = ListTools.findFirst(pointerList, Constants.OPEN_BRACKET);
int last = ListTools.findMatchingCloseBracket(pointerList, first + 1);
SmartList<Pointer> elems =
new SmartList<Pointer>(pointerList.subList(first + 1, last));
SmartList<SmartList<Pointer>> elemLists =
ListTools.splitListOnCommas(elems);
elems = new SmartList<Pointer>();
for (SmartList<Pointer> eachElemList : elemLists) {
Pointer value = evalExpression(eachElemList, 0);
if (value != null) {
elems.add(value);
}
}
return elems;
}
private Subprogram defineSub(SmartList<Pointer> pointerList, int i) {
String subName = PointerTools.dereferenceName(pointerList.get(i + 1));
SmartList<Pointer> argNames = getArgNames(pointerList, i + 2);
return new Subprogram(subName, argNames,
new SmartList<SmartList<Pointer>>());
}
private Block defineBlock(SmartList<Pointer> pointerList, int i) {
String blockName = PointerTools.dereferenceName(pointerList.get(i + 1));
return new Block(blockName, new SmartList<SmartList<Pointer>>());
}
//<editor-fold defaultstate="collapsed" desc="Method Apply Tier0 Keyword">
private SmartList<Pointer> applyTier0Keyword(int keyword,
SmartList<Pointer> pointerList, int i)
throws MintException {
switch (keyword) {
case Constants.ASSIGN: {
if (i - 1 == 0) {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
env.put(name, value);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} else {
SmartList<Pointer> nameRef =
new SmartList<Pointer>(pointerList.subList(0, i));
nameRef = ListTools.removePointers(nameRef,
new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_PAREN));
nameRef = ListTools.removePointers(nameRef,
new Pointer(Constants.KEYWORD_TYPE,
Constants.CLOSE_PAREN));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
int j = 0;
Pointer systemVar = Heap.allocateName("$-1");
while (j < nameRef.size()) {
Pointer nameRef0 = nameRef.get(j);
Pointer nameRef1 = null;
if (j + 1 < nameRef.size())
nameRef1 = nameRef.get(j + 1);
Pointer dot = new Pointer(
Constants.KEYWORD_TYPE, Constants.DOT);
if (nameRef0.type == Constants.LIST_TYPE) {
if (j + 1 == nameRef.size()) {
SmartList<Pointer> newNameRef =
new SmartList<Pointer>();
newNameRef.add(systemVar);
newNameRef.add(nameRef0);
env.put(newNameRef, value);
} else {
SmartList<Pointer> pList =
new SmartList<Pointer>();
Pointer newSystemVar =
Heap.getNextSystemVarName();
pList.add(newSystemVar);
pList.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
pList.add(systemVar);
pList.add(nameRef0);
evalExpression(pList, 0);
systemVar = newSystemVar;
}
j++;
} else if (nameRef1 != null &&
nameRef1.type == Constants.LIST_TYPE) {
if (j + 2 == nameRef.size()) {
env.put(nameRef, value);
} else {
SmartList<Pointer> pList =
new SmartList<Pointer>();
systemVar = Heap.getNextSystemVarName();
pList.add(systemVar);
pList.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
pList.add(nameRef0);
pList.add(nameRef1);
evalExpression(pList, 0);
}
j += 2;
} else if (nameRef1 != null && nameRef1.equals(dot)) {
if (j + 3 == nameRef.size() &&
nameRef0.type != Constants.LIST_TYPE) {
env.put(nameRef, value);
} else {
Pointer nameRef2 = nameRef.get(j + 2);
SmartList<Pointer> pList =
new SmartList<Pointer>();
systemVar = Heap.getNextSystemVarName();
pList.add(systemVar);
pList.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
pList.add(nameRef0);
pList.add(nameRef1);
pList.add(nameRef2);
evalExpression(pList, 0);
}
j += 3;
} else if (nameRef0.equals(dot)) {
if (j + 2 == nameRef.size()) {
SmartList<Pointer> newNameRef =
new SmartList<Pointer>();
newNameRef.add(systemVar);
newNameRef.add(dot);
newNameRef.add(nameRef1);
env.put(newNameRef, value);
} else {
SmartList<Pointer> pList =
new SmartList<Pointer>();
Pointer newSystemVar =
Heap.getNextSystemVarName();
pList.add(newSystemVar);
pList.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
pList.add(systemVar);
pList.add(dot);
pList.add(nameRef1);
evalExpression(pList, 0);
systemVar = newSystemVar;
}
j += 2;
}
if (j == nameRef.size()) {
SmartList<Pointer> pList = new SmartList<Pointer>();
pList.add(systemVar);
pList.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
pList.add(value);
evalExpression(pList, 0);
}
}
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
}
} case Constants.PLUS_ASSIGN: {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
Pointer nameVal = evaluateName(pointerList.get(i - 1), env);
env.put(name,
Operator.additionFamily(Constants.PLUS, nameVal, value));
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} case Constants.MINUS_ASSIGN: {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
Pointer nameVal = evaluateName(pointerList.get(i - 1), env);
env.put(name,
Operator.additionFamily(Constants.MINUS, nameVal, value));
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} case Constants.MULTIPLY_ASSIGN: {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
Pointer nameVal = evaluateName(pointerList.get(i - 1), env);
env.put(name, Operator.multiplicationFamily(
Constants.MULTIPLY, nameVal, value));
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} case Constants.DIVIDE_ASSIGN: {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
Pointer nameVal = evaluateName(pointerList.get(i - 1), env);
env.put(name, Operator.multiplicationFamily(
Constants.DIVIDE, nameVal, value));
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} case Constants.MODULO_ASSIGN: {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
Pointer nameVal = evaluateName(pointerList.get(i - 1), env);
env.put(name, Operator.multiplicationFamily(
Constants.MODULO, nameVal, value));
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} case Constants.POWER_ASSIGN: {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
Pointer value = evalExpression(
pointerList.subList(i + 1), 0);
value = evaluateName(value, env);
Pointer nameVal = evaluateName(pointerList.get(i - 1), env);
env.put(name, Operator.power(nameVal, value));
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(value);
return pointers;
} case Constants.PRINT: {
Pointer result = showOrPrint(pointerList, i, false);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(result);
return pointers;
} case Constants.SHOW: {
Pointer result = showOrPrint(pointerList, i, true);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(result);
return pointers;
} case Constants.WHEN: {
Pointer result = evalExpression(pointerList.subList(i + 1), 0);
if (!PointerTools.dereferenceTruth(result)) {
Message msg = new Message(Constants.ADVANCE_BY_2);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} else {
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(new Pointer(Constants.NULL_TYPE, 0));
return pointers;
}
} case Constants.IF: {
Pointer result = evalExpression(pointerList.subList(i + 1), 0);
if (!PointerTools.dereferenceTruth(result)) {
Message msg = new Message(Constants.CONTINUE_FALSE_IF);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} else {
Message msg = new Message(Constants.PUSH_EMPTY_PTR);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
}
} case Constants.GIVEN:
case Constants.YIELD:
case Constants.OTHERWISE: {
i = ListTools.findFirst(pointerList, Constants.GIVEN);
int j = ListTools.findFirst(pointerList, Constants.YIELD);
int k = ListTools.findFirst(pointerList, Constants.OTHERWISE);
SmartList<Pointer> condition = new SmartList<Pointer>(
pointerList.subList(i + 1, j));
Pointer yield1 = pointerList.get(j + 1);
Pointer yield2 = pointerList.get(k + 1);
SmartList<Pointer> pointers = new SmartList<Pointer>();
if (PointerTools.dereferenceTruth(evalExpression(condition, 0)))
{
pointers.add(yield1);
} else {
pointers.add(yield2);
}
return pointers;
} case Constants.END: {
Message msg = new Message(Constants.POP_PTR);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.ELSE: {
Message msg = new Message(Constants.GO_AFTER_END_AND_POP);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.ELSEIF: {
Message msg;
if (ifStack.get(-1)) {
//If the last if was true, then we don't need to evaluate
//this elseif.
msg = new Message(Constants.GO_AFTER_END_AND_POP);
} else {
Pointer result =
evalExpression(pointerList.subList(i + 1), 0);
if (PointerTools.dereferenceTruth(result)) {
msg = new Message(Constants.CONTINUE_TRUE_ELSEIF);
} else {
msg = new Message(Constants.CONTINUE_FALSE_ELSEIF);
}
}
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.WHILE: {
Pointer result = evalExpression(pointerList.subList(i + 1), 0);
Message msg;
Boolean bool = PointerTools.dereferenceTruth(result);
if (bool == null) {
throw new MintException("Non-truth value used for while " +
"loop condition in expression: " + pointerList);
}
if (bool) {
msg = new Message(Constants.PUSH_PTR);
} else {
msg = new Message(Constants.GO_AFTER_END);
}
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.REPEAT: {
Message msg;
int count = PointerTools.dereferenceInt(
evalExpression(pointerList.subList(i + 1), 0));
if (count <= 0)
msg = new Message(Constants.RESET_REPEAT_AND_GO_AFTER_END);
else
msg = new Message(Constants.PUSH_PTR_AND_DECREMENT);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.CONTINUE: {
Message msg = new Message(Constants.MSG_CONTINUE);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.BREAK: {
Message msg = new Message(Constants.MSG_BREAK);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.LEAVE: {
Message msg = new Message(Constants.MSG_LEAVE);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.RUN: {
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(new Pointer(Constants.NULL_TYPE, 0));
String blockName = PointerTools.dereferenceName(
pointerList.get(i + 1));
Block block = PointerTools.dereferenceBlock(
env.getValue(blockName));
block.execute(env, imports, this);
return pointers;
} case Constants.RETURN: {
// Always pop the last frame when returning from a subprogram.
Message msg;
if (pointerList.size() > 1) {
Pointer p = pointerList.get(i + 1);
String name = PointerTools.dereferenceName(p);
if (name != null && name.equals("this")) {
MintObject lastFrame = env.pop();
SmartList<Pointer> retnValue = new SmartList<Pointer>();
retnValue.add(Heap.allocateObject(lastFrame));
msg = new Message(Constants.RETURN_VALUE, retnValue);
} else {
SmartList<Pointer> retnValue = new SmartList<Pointer>();
Pointer p2 =
evalExpression(pointerList.subList(i + 1), 0);
MintObject lastFrame = env.pop();
if (p2.type == Constants.SUBPROGRAM_TYPE) {
Subprogram sub = PointerTools.dereferenceSub(p2);
sub.setVirtualArgs(lastFrame);
p2 = Heap.allocateSub(sub);
}
retnValue.add(p2);
msg = new Message(Constants.RETURN_VALUE, retnValue);
}
} else {
env.pop();
SmartList<Pointer> retnValue = new SmartList<Pointer>();
retnValue.add(new Pointer(Constants.NULL_TYPE, 0));
msg = new Message(Constants.RETURN_VALUE, retnValue);
}
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.SUB: {
Message msg;
SmartList<Pointer> retnValue = new SmartList<Pointer>();
retnValue.add(Heap.allocateSub(defineSub(pointerList, i)));
msg = new Message(Constants.DEFINE_SUB, retnValue);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.BLOCK: {
Message msg;
SmartList<Pointer> retnValue = new SmartList<Pointer>();
retnValue.add(Heap.allocateBlock(defineBlock(pointerList, i)));
msg = new Message(Constants.DEFINE_BLOCK, retnValue);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.INHERIT: {
MintObject obj = PointerTools.dereferenceObject(
evalExpression(pointerList.subList(i + 1), 0));
if (obj == null) {
throw new MintException(
"Cannot inherit from non-object value.");
}
env.putAll(obj);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(new Pointer(Constants.NULL_TYPE, 0));
return pointers;
} case Constants.IMPORT: {
String fileName =
PointerTools.dereferenceString(pointerList.get(i + 1));
if (fileName == null) {
String importName = PointerTools.dereferenceName(
pointerList.get(i + 1));
MintObject frame = null;
if (importName != null) {
if (importName.equals("operator")) {
frame = Import.importOperator();
} else if (importName.equals("math")) {
frame = Import.importMath();
} else if (importName.equals("type")) {
frame = Import.importType();
} else if (importName.equals("time")) {
frame = Import.importTime();
} else if (importName.equals("system")) {
frame = Import.importSystem(this);
} else if (importName.equals("file")) {
frame = Import.importFile();
} else if (importName.equals("web")) {
frame = Import.importWeb();
} else if (importName.equals("mint")) {
frame = Import.importMint();
} else if (importName.equals("graphics")) {
frame = Import.importGraphics();
} else if (importName.equals("thread")) {
frame = Import.importThread();
} else if (importName.equals("random")) {
frame = Import.importRandom();
} else if (importName.equals("compress")) {
frame = Import.importCompress();
} else if (importName.equals("programming")) {
frame = Import.importProgramming();
} else if (importName.equals("matcher")) {
frame = Import.importMatcher();
} else if (importName.equals("game")) {
frame = Import.importGame();
} else {
throw new MintException("No library named " +
importName);
}
} else {
throw new MintException("Import name does not exist.");
}
if (i + 2 < pointerList.size() &&
pointerList.get(i + 2).equals(new Pointer(
Constants.KEYWORD_TYPE, Constants.INTO))) {
String objName = PointerTools.dereferenceName(
pointerList.get(i + 3));
env.put(objName, Heap.allocateObject(frame));
} else {
env.putAll(frame);
}
} else {
if (!imports.contains(fileName)) {
imports.add(fileName);
if (i + 2 < pointerList.size() &&
pointerList.get(i + 2).equals(new Pointer(
Constants.KEYWORD_TYPE, Constants.INTO))) {
String objName =
PointerTools.dereferenceName(pointerList.get(
i + 3));
MintObject newFrame = new MintObject();
env.addFrame(newFrame);
execute(loadProgram(fileName, false), imports, env);
MintObject frame = env.pop();
env.put(objName, Heap.allocateObject(frame));
} else {
execute(loadProgram(fileName, false), imports, env);
}
}
}
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(new Pointer(Constants.NULL_TYPE, 0));
return pointers;
} case Constants.FOR: {
Message msg = new Message(Constants.MSG_FOR);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.FOREACH: {
Message msg = new Message(Constants.MSG_FOREACH);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.IN: {
Pointer value = evaluateName(pointerList.get(i - 1), env);
Pointer iterable = evaluateName(pointerList.get(i + 1), env);
if (iterable != null) {
switch (iterable.type) {
case Constants.LIST_TYPE: {
SmartList<Pointer> list =
PointerTools.dereferenceList(iterable);
pointerList.assignSublist(i - 1, i + 2,
Heap.allocateTruth(
ListTools.findPointerValue(list,
value) != -1));
return pointerList;
} case Constants.STR_TYPE: {
String s = PointerTools.dereferenceString(iterable);
Pointer t = Heap.allocateTruth(s.contains(
PointerTools.dereferenceString(value)));
pointerList.assignSublist(i - 1, i + 2, t);
return pointerList;
} case Constants.BYTES_TYPE: {
SmartList<Byte> bytes = PointerTools.
dereferenceBytes(iterable);
Pointer t = Heap.allocateTruth(bytes.contains(
(byte)(int)PointerTools.dereferenceInt(
value)));
pointerList.assignSublist(i - 1, i + 2, t);
return pointerList;
} case Constants.OBJECT_TYPE: {
MintObject obj =
PointerTools.dereferenceObject(iterable);
String key = PointerTools.dereferenceString(value);
Pointer t;
if (obj.keys().contains(key))
t = new Pointer(Constants.TRUTH_TYPE, 1);
else
t = new Pointer(Constants.TRUTH_TYPE, 0);
pointerList.assignSublist(i - 1, i + 2, t);
return pointerList;
} default: {
throw new MintException(iterable +
" is not iterable.");
}
}
} else {
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Constants.MINT_NULL);
return pointers;
}
} case Constants.ERASE: {
Pointer next = pointerList.get(i + 1);
if (next.type == Constants.KEYWORD_TYPE &&
next.value == Constants.ALL) {
//Erase all variables, except...
SmartList<String> names = new SmartList<String>();
SmartList<Pointer> values = new SmartList<Pointer>();
if (i + 2 < pointerList.size()) {
Pointer further = pointerList.get(i + 2);
if (further.type == Constants.KEYWORD_TYPE &&
further.value == Constants.EXCEPT) {
//Save the following variables:
int j = i + 3;
for (; j < pointerList.size(); j += 2) {
Pointer n = pointerList.get(j);
String name = PointerTools.dereferenceName(n);
Pointer val = env.getValue(name);
names.add(name);
values.add(val);
}
}
}
int s = env.size();
env.eraseAll();
for (int k = 0; k < s; k++) {
env.addFrame(new MintObject());
}
int k = 0;
for (String name : names) {
env.put(name, values.get(k));
k++;
}
Heap.eraseAllExcept(values);
} else {
int j = i + 1;
for (; j < pointerList.size(); j += 2) {
//Erase all these variables:
Pointer n = pointerList.get(j);
String name = PointerTools.dereferenceName(n);
env.remove(name);
}
}
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(new Pointer(Constants.NULL_TYPE, 0));
return pointers;
} case Constants.SWITCH: {
Message msg = new Message(Constants.MSG_SWITCH);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} case Constants.CASE:
case Constants.DEFAULT: {
Message msg = new Message(Constants.GO_AFTER_END);
SmartList<Pointer> pointers = new SmartList<Pointer>();
pointers.add(Heap.allocateMessage(msg));
return pointers;
} default: {
throw new MintException("Unknown tier 0 keyword: " +
convertKeywordToOperator(keyword));
}
}
}
//</editor-fold>
public void setThisPointer(int value) {
env.setThisPointer(value);
}
public void setThisPointerName(String value) {
env.setThisPointerName(value);
}
//<editor-fold defaultstate="collapsed" desc="Method eval dot">
private Pointer evalDot(SmartList<Pointer> pointerList, int i) throws
MintException {
Pointer previous = pointerList.get(i - 1);
if (pointerList.get(i - 1).type == Constants.KEYWORD_TYPE) {
int kwd = PointerTools.dereferenceKeyword(previous);
if (kwd == Constants.DOUBLE_DOT) {
return new Pointer(Constants.KEYWORD_TYPE, Constants.ELLIPSIS);
}
}
String name = PointerTools.dereferenceName(previous);
Pointer obj = evaluateName(previous, env);
if (obj == null || !Constants.OBJECT_LIKE.contains(obj.type)) {
if (obj == null) {
throw new MintException("Java null is not an object." +
" Expression is: " + pointerList);
}
throw new MintException(obj + " is not an object. Expression is: " +
pointerList);
}
String member = PointerTools.dereferenceName(pointerList.get(i + 1));
Pointer result = null;
switch (obj.type) {
case Constants.OBJECT_TYPE: {
result = PointerTools.dereferenceObject(obj).get(member);
if (result != null && result.type == Constants.SUBPROGRAM_TYPE)
{
Subprogram sub = PointerTools.dereferenceSub(result);
sub.setThisPointer(env.getCurrentFrameIndex());
sub.setThisPointerName(name);
result = Heap.allocateSub(sub);
}
break;
} case Constants.LIST_TYPE: {
SmartList<Pointer> list = PointerTools.dereferenceList(obj);
if (member.equals("length") || member.equals("size") ||
member.equals("numItems") || member.equals("count") ||
member.equals("width") || member.equals("len")) {
int sz = list.size();
Subprogram sub = null;
if (!list.isInfinite()) {
sub = new Subprogram("size",
new SmartList<Pointer>(),
new Constant(Heap.allocateInt(sz)));
} else {
sub = new Subprogram("size",
new SmartList<Pointer>(), new Constant(
Heap.allocateReal(Double.POSITIVE_INFINITY)));
}
result = Heap.allocateSub(sub);
} else if (member.equals("allPositives")) {
list.makeAllReals();
Subprogram allRls = new Subprogram("allPositives",
new SmartList<Pointer>(),
new Constant(Heap.allocateList(list)));
result = Heap.allocateSub(allRls);
} else if (member.equals("pop")) {
if (list.isInfinite()) {
Subprogram sub = new Subprogram("pop",
new SmartList<Pointer>(),
new Constant(Heap.allocateReal(
Double.POSITIVE_INFINITY)));
result = Heap.allocateSub(sub);
} else {
Pointer last = list.pop();
Subprogram sub = new Subprogram("pop",
new SmartList<Pointer>(),
new Constant(last));
if (name != null) {
env.put(name, Heap.allocateList(list));
}
result = Heap.allocateSub(sub);
}
} else if (member.equals("unfreeze") || member.equals("thaw")
|| member.equals("microwave")) {
list.thaw();
Pointer ptr = Heap.allocateList(list);
Subprogram sb = new Subprogram("thaw",
new SmartList<Pointer>(),
new Constant(ptr));
if (name != null) {
env.put(name, ptr);
}
result = Heap.allocateSub(sb);
} else if (member.equals("resetType")) {
list.changeToRegularList();
Pointer ptr = Heap.allocateList(list);
Subprogram sb = new Subprogram("resetType",
new SmartList<Pointer>(),
new Constant(ptr));
if (name != null) {
env.put(name, ptr);
}
result = Heap.allocateSub(sb);
} else if (member.equals("freeze")) {
list.freeze();
Pointer ptr = Heap.allocateList(list);
Subprogram sb = new Subprogram("freeze",
new SmartList<Pointer>(),
new Constant(ptr));
if (name != null) {
env.put(name, ptr);
}
result = Heap.allocateSub(sb);
} else if (member.equals("makeRecursive")) {
list.changeToRecursiveList();
Pointer ptr = Heap.allocateList(list);
Subprogram sb = new Subprogram("makeRecursive",
new SmartList<Pointer>(),
new Constant(ptr));
if (name != null) {
env.put(name, ptr);
}
result = Heap.allocateSub(sb);
} else if (member.equals("choose")) {
Random rng = new Random();
int hCode = new Object().hashCode() *
new Environment().hashCode();
hCode += System.console().hashCode();
hCode ^= (int) System.nanoTime();
rng.setSeed(~hCode);
int jj = rng.nextInt(list.size());
Pointer pp = list.get(jj);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("choose"));
Subprogram sub = new Subprogram("choose", argNames,
new Constant(pp));
result = Heap.allocateSub(sub);
} else if (member.equals("remove")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("i"));
Subprogram sub = new Subprogram("remove", argNames,
new Remove(list));
if (name != null) {
Integer _i = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
if (_i == null) {
throw new MintException(
"Bad argument for remove");
}
env.put(name, Heap.allocateList(list));
}
result = Heap.allocateSub(sub);
} else if (member.equals("reverse")) {
SmartList<Pointer> allocated = list.reverse();
if (list.isInfinite()) {
allocated = new SmartList<Pointer>(
new Subprogram("integersReversed",
new SmartList<Pointer>(
new Pointer[]{Heap.allocateName("x")}),
new Infinity()));
}
Subprogram sub = new Subprogram("reverse",
new SmartList<Pointer>(),
new Constant(Heap.allocateList(allocated)));
result = Heap.allocateSub(sub);
if (name != null) {
env.put(name, Heap.allocateList(list));
}
} else if (member.equals("find")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("elem"));
if (i + 3 >= pointerList.size())
throw new MintException("No argument for find.");
Subprogram sub = new Subprogram("find", argNames,
new Constant(Heap.allocateInt(
ListTools.findPointerValue(list,
getArg(pointerList, i + 3, 0)))));
result = Heap.allocateSub(sub);
} else if (member.equals("add") || member.equals("append")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("item"));
if (i + 3 >= pointerList.size())
throw new MintException("No argument for add.");
list.add(getArg(pointerList, i + 3, 0));
Subprogram sub = new Subprogram("append", argNames,
new Constant(Heap.allocateList(list)));
result = Heap.allocateSub(sub);
if (name != null) {
env.put(name, Heap.allocateList(list));
}
} else if (member.equals("sliceToEnd")) {
int start = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
SmartList<Pointer> slice = list.subList(start);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("start"));
Subprogram sub = new Subprogram("sliceToEnd", argNames,
new Constant(Heap.allocateList(slice)));
result = Heap.allocateSub(sub);
} else if (member.equals("slice")) {
int start = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
Integer end = 0;
SmartList<Pointer> slice;
end = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
if (end == null) {
slice = list.subList(start);
} else {
slice = new SmartList<Pointer>(
list.subList(start, end));
}
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("args"));
argNames.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.DOUBLE_DOT));
Subprogram sub = new Subprogram("slice", argNames,
new Constant(Heap.allocateList(slice)));
result = Heap.allocateSub(sub);
} else if (member.equals("getVal")) {
Pointer key = getArg(pointerList, i + 3, 0);
Table t = new Table();
t.bindAll(list);
Pointer answer = t.getValue(key);
Subprogram sb = new Subprogram("getVal",
new SmartList<Pointer>(
new Pointer[]{Heap.allocateName("x")}),
new Constant(answer));
result = Heap.allocateSub(sb);
} else if (member.equals("hasKey")) {
Pointer key = getArg(pointerList, i + 3, 0);
Table t = new Table();
t.bindAll(list);
Pointer answer = t.hasKey(key);
Subprogram sb = new Subprogram("hasKey",
new SmartList<Pointer>(
new Pointer[]{Heap.allocateName("x")}),
new Constant(answer));
result = Heap.allocateSub(sb);
} else if (member.equals("enumerate")) {
SmartList<Pointer> tbl = new SmartList<Pointer>();
int startAt = 0;
for (Pointer p : list) {
SmartList<Pointer> pair = new SmartList<Pointer>();
pair.add(Heap.allocateInt(startAt));
pair.add(p);
tbl.add(Heap.allocateList(pair));
++startAt;
}
Pointer cons = Heap.allocateList(tbl);
Subprogram sb = new Subprogram("enumerate",
new SmartList<Pointer>(), new Constant(cons));
result = Heap.allocateSub(sb);
} else if (member.equals("markNumbers")) {
SmartList<Pointer> tbl = new SmartList<Pointer>();
int startAt = 1;
for (Pointer p : list) {
SmartList<Pointer> pair = new SmartList<Pointer>();
pair.add(Heap.allocateInt(startAt));
pair.add(p);
tbl.add(Heap.allocateList(pair));
++startAt;
}
Pointer cons = Heap.allocateList(tbl);
Subprogram sb = new Subprogram("markNumbers",
new SmartList<Pointer>(), new Constant(cons));
result = Heap.allocateSub(sb);
} else if (member.equals("replaceSlice")) {
int start = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
int end = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
Pointer sl = getArg(pointerList, i + 3, 2);
SmartList<Pointer> slice = PointerTools.dereferenceList(sl);
list.assignSublist(start, end, slice);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("a"));
argNames.add(Heap.allocateName("b"));
argNames.add(Heap.allocateName("slice"));
Subprogram sub = new Subprogram("replaceSlice", argNames,
new Constant(Heap.allocateList(list)));
result = Heap.allocateSub(sub);
}
break;
} case Constants.REAL_TYPE: {
Double rl = PointerTools.dereferenceReal(obj);
if (rl == null) {
Subprogram s = new Subprogram("nothing",
new SmartList<Pointer>(), new Constant(Constants.ZERO));
result = Heap.allocateSub(s);
} else if (member.equals("wholePart")) {
int irl = rl.intValue();
Subprogram k = new Subprogram("wholePart",
new SmartList<Pointer>(), new Constant(
Heap.allocateInt(irl)));
result = Heap.allocateSub(k);
} else if (member.equals("fracPart")) {
int irl = rl.intValue();
Subprogram j = new Subprogram("fracPart",
new SmartList<Pointer>(), new Constant(
Heap.allocateReal(rl - irl)));
result = Heap.allocateSub(j);
} else if (member.equals("toBaseExponentList")) {
SmartList<Pointer> bExpList = new SmartList<Pointer>();
Integer irl = rl.intValue();
Double frac = rl - irl;
int negExp = -frac.toString().replace(".", "").length();
if (negExp < -16) {
negExp += 16;
} else {
negExp++;
}
String asBig = rl.toString().replace(".", "");
if (asBig.toLowerCase().contains("e")) {
Subprogram failed = new Subprogram("failed",
new SmartList<Pointer>(), new Constant(
Heap.allocateList(new SmartList<Pointer>())));
result = Heap.allocateSub(failed);
} else {
BigInteger bInt = new BigInteger(
rl.toString().replace(".", ""));
bExpList.add(Heap.allocateBigInt(bInt));
bExpList.add(Heap.allocateInt(negExp));
Subprogram kPlus = new Subprogram(
"toBaseExponentList", new SmartList<Pointer>(),
new Constant(Heap.allocateList(bExpList)));
result = Heap.allocateSub(kPlus);
}
}
break;
} case Constants.INT_TYPE: {
Integer aye = PointerTools.dereferenceInt(obj);
if (aye == null) {
Subprogram s = new Subprogram("nothing",
new SmartList<Pointer>(), new Constant(Constants.ZERO));
result = Heap.allocateSub(s);
} else if (member.equals("next")) {
++aye;
Subprogram s = new Subprogram("next",
new SmartList<Pointer>(), new Constant(
Heap.allocateInt(aye)));
result = Heap.allocateSub(s);
} else if (member.equals("previous")) {
--aye;
Subprogram s = new Subprogram("previous",
new SmartList<Pointer>(), new Constant(
Heap.allocateInt(aye)));
result = Heap.allocateSub(s);
} else if (member.equals("numDigits")) {
int digits = ("" + aye).replace("-", "").length();
Subprogram s2 = new Subprogram("previous",
new SmartList<Pointer>(), new Constant(
Heap.allocateInt(digits)));
result = Heap.allocateSub(s2);
} else if (member.equals("bits")) {
String bits = Integer.toBinaryString(aye);
Subprogram bts = new Subprogram("bits",
new SmartList<Pointer>(), new Constant(
Heap.allocateString(bits)));
result = Heap.allocateSub(bts);
} else if (member.equals("bytes")) {
SmartList<Byte> bites = new SmartList<Byte>();
byte firstByte = (byte) (aye.intValue() >>> 24);
byte secondByte =
(byte) ((aye.intValue() & 0x00FF0000) >>> 16);
byte thirdByte =
(byte) ((aye.intValue() & 0x0000FF00) >>> 8);
byte fourthByte = (byte) (aye & 0x000000FF);
bites.add(firstByte);
bites.add(secondByte);
bites.add(thirdByte);
bites.add(fourthByte);
Subprogram chomps = new Subprogram("bytes",
new SmartList<Pointer>(), new Constant(
Heap.allocateBytes(bites)));
result = Heap.allocateSub(chomps);
}
break;
} case Constants.STR_TYPE: {
String str = PointerTools.dereferenceString(obj);
if (member.equals("length") || member.equals("size")) {
Subprogram sub = new Subprogram("size",
new SmartList<Pointer>(),
new Constant(Heap.allocateInt(str.length())));
result = Heap.allocateSub(sub);
} else if (member.equals("split")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("substr"));
Subprogram sub = new Subprogram("split", argNames,
new Split(str));
result = Heap.allocateSub(sub);
} else if (member.equals("charNum")) {
Subprogram sub = new Subprogram("charNum",
new SmartList<Pointer>(),
new Constant(Heap.allocateInt(
(int)str.charAt(0))));
result = Heap.allocateSub(sub);
} else if (member.equals("find")) {
String substr = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
int j;
for (j = 0; j < str.length(); j++) {
if (StrTools2.slice(str, j, j + substr.length()).
equals(substr)) {
break;
}
}
if (j == str.length())
j = -1;
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("substr"));
Subprogram sub = new Subprogram("find", argNames,
new Constant(Heap.allocateInt(j)));
result = Heap.allocateSub(sub);
} else if (member.equals("slice")) {
Pointer arg1 = getArg(pointerList, i + 3, 0);
int start = 0;
if (arg1 != null)
start = PointerTools.dereferenceInt(arg1);
Integer end = 0;
String slice;
Pointer arg2 = getArg(pointerList, i + 3, 1);
if (arg2 != null)
end = PointerTools.dereferenceInt(arg2);
if (arg2 == null || end == null) {
slice = StrTools2.slice(str, start);
} else {
slice = StrTools2.slice(str, start, end);
}
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("args"));
argNames.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.DOUBLE_DOT));
Subprogram sub = new Subprogram("slice", argNames,
new Constant(Heap.allocateString(slice)));
result = Heap.allocateSub(sub);
} else if (member.equals("sliceToEnd")) {
int start = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
String slice = StrTools2.slice(str, start);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("start"));
Subprogram sub = new Subprogram("sliceToEnd", argNames,
new Constant(Heap.allocateString(slice)));
result = Heap.allocateSub(sub);
} else if (member.equals("choose")) {
Random rng = new Random();
int hCode = new Object().hashCode() *
new Environment().hashCode();
hCode += System.console().hashCode();
hCode ^= (int) System.nanoTime();
rng.setSeed(~hCode);
int jj = rng.nextInt(str.length());
char c = str.charAt(jj);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("choose"));
Subprogram sub = new Subprogram("choose", argNames,
new Constant(Heap.allocateString("" + c)));
result = Heap.allocateSub(sub);
} else if (member.equals("replaceSlice")) {
int start = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
int end = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
String slice = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 2));
str = StrTools2.slice(str, 0, start) + slice +
StrTools2.slice(str, end);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("a"));
argNames.add(Heap.allocateName("b"));
argNames.add(Heap.allocateName("slice"));
Subprogram sub = new Subprogram("replaceSlice", argNames,
new Constant(Heap.allocateString(str)));
result = Heap.allocateSub(sub);
} else if (member.equals("call")) {
Pointer answer = new Interpreter().run(str, true);
Subprogram cons = new Subprogram("call",
new SmartList<Pointer>(), new Constant(answer));
result = Heap.allocateSub(cons);
} else if (member.equals("knife")) {
Double start = PointerTools.dereferenceReal(
getArg(pointerList, i + 3, 0));
Double end = PointerTools.dereferenceReal(
getArg(pointerList, i + 3, 1));
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("a"));
argNames.add(Heap.allocateName("b"));
Subprogram nullDriver = new Subprogram("knife", argNames,
new Constant(Constants.MINT_NULL));
if (start == null || end == null) {
result = Heap.allocateSub(nullDriver);
} else if (start.toString().endsWith(".0") ||
end.toString().endsWith(".0")) {
result = Heap.allocateSub(nullDriver);
} else {
int open = start.intValue();
int close = end.intValue();
if (open < 0) {
open = 0;
}
if (close > str.length()) {
close = str.length();
}
String knifed = StrTools2.slice(str, open, close);
Subprogram knifer = new Subprogram("knife", argNames,
new Constant(Heap.allocateString(knifed)));
result = Heap.allocateSub(knifer);
}
} else if (member.equals("upper")) {
str = str.toUpperCase();
Subprogram sub = new Subprogram("upper",
new SmartList<Pointer>(),
new Constant(Heap.allocateString(str)));
result = Heap.allocateSub(sub);
} else if (member.equals("lower")) {
str = str.toLowerCase();
Subprogram sub = new Subprogram("lower",
new SmartList<Pointer>(),
new Constant(Heap.allocateString(str)));
result = Heap.allocateSub(sub);
} else if (member.equals("startsWith")) {
String substr = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
boolean b = str.startsWith(substr);
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("substr"));
Subprogram sub = new Subprogram("startsWith", argNames,
new Constant(Heap.allocateTruth(b)));
result = Heap.allocateSub(sub);
} else if (member.equals("endsWith")) {
String substr = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
boolean b;
if (substr != null) {
b = str.endsWith(substr);
} else {
b = false;
}
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("substr"));
Subprogram sub = new Subprogram("endsWith", argNames,
new Constant(Heap.allocateTruth(b)));
result = Heap.allocateSub(sub);
} else if (member.equals("replace")) {
String substr = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
String replacement = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 1));
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("substr"));
argNames.add(Heap.allocateName("replacement"));
Subprogram sub = new Subprogram("replace", argNames,
new Constant(Heap.allocateString(
str.replace(substr, replacement))));
result = Heap.allocateSub(sub);
} else if (member.equals("remove")) {
String substr = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("substr"));
Subprogram sub = new Subprogram("replace", argNames,
new Constant(Heap.allocateString(
str.replace(substr, ""))));
result = Heap.allocateSub(sub);
}
break;
} case Constants.IMG_TYPE: {
BufferedImage image = PointerTools.derefImg(obj);
if (member.equals("toFile")) {
SmartList<Pointer> args = new SmartList<Pointer>();
args.add(Heap.allocateName("filePath"));
String imageFileName = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
String[] pieces = imageFileName.split("\\.");
String last = pieces[pieces.length - 1];
try {
ImageIO.write(image, last, new File(imageFileName));
} catch (Throwable t) {
System.err.println(t);
Mint.printStackTrace(t.getStackTrace());
}
String msg = "Saved image to file " + imageFileName +
" using format " + last.toUpperCase();
Subprogram toFile = new Subprogram("toFile", args,
new Constant(Heap.allocateString(msg)));
// The time machine feature of Mint means
// that this file will be saved BEFORE
// you call the method and see the result string.
result = Heap.allocateSub(toFile);
} else if (member.equals("toString")) {
String s = image.toString();
s = s.replace("BufferedImage@",
"Mint Programmming Language Image Format - hash code=");
Subprogram asString = new Subprogram("toString",
new SmartList<Pointer>(),
new Constant(Heap.allocateString(s)));
result = Heap.allocateSub(asString);
} else if (member.equals("getPixel")) {
Integer x = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
Integer y = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
if (x == null || y == null) {
System.err.println(
"<error: Non-integer arguments passed" +
" to getPixel(x, y)>"
);
}
int color = image.getRGB(x, y);
Subprogram asClr = new Subprogram("getPixel",
new SmartList<Pointer>(),
new Constant(Heap.allocateInt(color)));
result = Heap.allocateSub(asClr);
} else if (member.equals("setPixel")) {
Integer x = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
Integer y = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
Integer color = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 2));
if (x == null || y == null || color == null) {
System.err.println(
"<error: Non-integer arguments passed" +
" to setPixel(x, y, color)>"
);
}
image.setRGB(x, y, color);
Pointer pointerToImage = Heap.allocImg(image);
if (name != null) {
env.put(name, pointerToImage);
}
Subprogram asImage = new Subprogram("setPixel",
new SmartList<Pointer>(),
new Constant(pointerToImage)
);
result = Heap.allocateSub(asImage);
} else if (member.equals("dimensions")) {
MintObject dims = new MintObject();
int w = image.getWidth();
int h = image.getHeight();
dims.put("width", Heap.allocateInt(w));
dims.put("height", Heap.allocateInt(h));
dims.put("area", Heap.allocateInt(w * h));
dims.put("animationFrames", Constants.ONE);
Subprogram getDims = new Subprogram("dimensions",
new SmartList<Pointer>(), new Constant(
Heap.allocateObject(dims)));
result = Heap.allocateSub(getDims);
}
break;
} case Constants.RAT_TYPE: {
Rational r = PointerTools.derefRat(obj);
if (member.equals("fraction")) {
String asExactFrac = r.exact();
Subprogram frac = new Subprogram("fraction",
new SmartList<Pointer>(),
new Constant(Heap.allocateString(asExactFrac)));
result = Heap.allocateSub(frac);
} else if (member.equals("top") || member.equals("numerator")) {
Subprogram numer = new Subprogram("numerator",
new SmartList<Pointer>(),
new Constant(Heap.allocateBigInt(
new BigInteger("" + r.n))));
result = Heap.allocateSub(numer);
} else if (member.equals("bottom") ||
member.equals("denominator")) {
Subprogram denom = new Subprogram("denominator",
new SmartList<Pointer>(),
new Constant(Heap.allocateBigInt(
new BigInteger("" + r.d))));
result = Heap.allocateSub(denom);
} else if (member.equals("isInfinite") ||
member.equals("isUnbounded")) {
String infStr = r.getInfinity();
boolean isUncountable =
infStr.contains("infi") && !infStr.contains("undef");
Subprogram isInf = new Subprogram("isInfinite",
new SmartList<Pointer>(),
new Constant(Heap.allocateTruth(isUncountable)));
result = Heap.allocateSub(isInf);
} else if (member.equals("isDefined") ||
member.equals("exists")) {
String infStr = r.getInfinity();
boolean isUndef = infStr.contains("undef");
Subprogram isNotDefed = new Subprogram("isDefined",
new SmartList<Pointer>(),
new Constant(Heap.allocateTruth(isUndef)));
result = Heap.allocateSub(isNotDefed);
} else if (member.equals("divideExactly")) {
long numer = r.n;
long denom = r.d;
final int RIDICULOUS_ACCURACY = 256;
final int DISPLAYED_ACCURACY = 200;
BigDecimal seme = new BigDecimal("" + numer);
BigDecimal uke = new BigDecimal("" + denom);
BigDecimal inverted = BigDecimal.ONE.divide(uke,
RIDICULOUS_ACCURACY, BigDecimal.ROUND_HALF_UP);
BigDecimal answer = seme.multiply(inverted);
answer.setScale(DISPLAYED_ACCURACY,
BigDecimal.ROUND_HALF_UP);
Subprogram ans = new Subprogram("divideExactly",
new SmartList<Pointer>(),
new Constant(Heap.allocatePreciseReal(answer)));
result = Heap.allocateSub(ans);
}
} case Constants.BYTES_TYPE: {
SmartList<Byte> bytes = PointerTools.dereferenceBytes(obj);
if (member.equals("length") || member.equals("size")) {
Subprogram sub = new Subprogram("size",
new SmartList<Pointer>(),
new Constant(Heap.allocateInt(bytes.size())));
result = Heap.allocateSub(sub);
} else if (member.equals("add") || member.equals("append")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("byte"));
if (i + 3 >= pointerList.size())
throw new MintException("No argument for add.");
bytes.add((byte)(int)
PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0)));
Subprogram sub = new Subprogram("append", argNames,
new Constant(Heap.allocateBytes(bytes)));
result = Heap.allocateSub(sub);
if (name != null) {
env.put(name, Heap.allocateBytes(bytes));
}
} else if (member.equals("get")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("i"));
if (i + 3 >= pointerList.size())
throw new MintException("No argument for get.");
byte item = bytes.get(PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0)));
Subprogram sub = new Subprogram("get", argNames,
new Constant(Heap.allocateInt((int)item)));
result = Heap.allocateSub(sub);
} else if (member.equals("set")) {
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("i"));
argNames.add(Heap.allocateName("byte"));
if (i + 5 >= pointerList.size()) {
throw new MintException(
"Not enough arguments for set.");
}
int j = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
byte item = (byte)(int)
PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
bytes.set(j, item);
Subprogram sub = new Subprogram("set", argNames,
new Constant(Heap.allocateInt((int)item)));
result = Heap.allocateSub(sub);
if (name != null) {
env.put(name, Heap.allocateBytes(bytes));
}
}
break;
} case Constants.WINDOW_TYPE: {
MintWindow jf = PointerTools.dereferenceWindow(obj);
if (member != null) {
if (member.equals("setSize")) {
int width = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
int height = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
jf.setPreferredSize(new Dimension(width, height));
jf.setSize(width, height);
} else if (member.equals("display")) {
jf.pack();
jf.setVisible(true);
} else if (member.equals("hide")) {
jf.setVisible(false);
} else if (member.equals("setTitle")) {
String title = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
jf.setTitle(title);
} else if (member.equals("pack")) {
jf.pack();
} else if (member.equals("setLocation")) {
int x = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
int y = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
jf.setLocation(x, y);
} else if (member.equals("add")) {
Pointer p = getArg(pointerList, i + 3, 0);
if (p.type == Constants.BUTTON_TYPE) {
jf.add(PointerTools.dereferenceButton(p).
getButton());
}
} else if (member.equals("setBgColor")) {
Pointer p = getArg(pointerList, i + 3, 0);
SmartList<Pointer> list = PointerTools.
dereferenceList(p);
int red = PointerTools.dereferenceInt(list.get(0));
int green = PointerTools.dereferenceInt(list.get(1));
int blue = PointerTools.dereferenceInt(list.get(2));
jf.setBackground(new Color(red, green, blue));
} else if (member.equals("setDrawingColor")) {
Pointer p = getArg(pointerList, i + 3, 0);
SmartList<Pointer> list = PointerTools.
dereferenceList(p);
int red = PointerTools.dereferenceInt(list.get(0));
int green = PointerTools.dereferenceInt(list.get(1));
int blue = PointerTools.dereferenceInt(list.get(2));
ArrayList<Integer> rbg = new ArrayList<Integer>();
rbg.add(red);
rbg.add(green);
rbg.add(blue);
jf.addShape(new Shape(Shape.COLOR, rbg));
} else if (member.equals("drawShape")) {
Shape s = PointerTools.dereferenceShape(
getArg(pointerList, i + 3, 0));
jf.addShape(s);
} else if (member.equals("clearShapes")) {
jf.clearShapes();
}
}
env.put(name, Heap.allocateWindow(jf));
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("args"));
argNames.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.DOUBLE_DOT));
Subprogram sub = new Subprogram(member, argNames,
new Constant(new Pointer(Constants.NULL_TYPE, 0)));
result = Heap.allocateSub(sub);
break;
} case Constants.BUTTON_TYPE: {
ButtonManager bm = PointerTools.dereferenceButton(obj);
if (member.equals("enable")) {
bm.getButton().setEnabled(true);
} else if (member.equals("disable")) {
bm.getButton().setEnabled(false);
} else if (member.equals("setText")) {
String text = PointerTools.dereferenceString(
getArg(pointerList, i + 3, 0));
bm.getButton().setText(text);
} else if (member.equals("setSubprogram")) {
Subprogram sub = PointerTools.dereferenceSub(
getArg(pointerList, i + 3, 0));
bm.addSubprogram(sub);
} else if (member.equals("setSize")) {
int width = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
int height = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
bm.getButton().setSize(new Dimension(width, height));
bm.getButton().setPreferredSize(
new Dimension(width, height));
} else if (member.equals("setPosition")) {
int x = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 0));
int y = PointerTools.dereferenceInt(
getArg(pointerList, i + 3, 1));
Dimension size = bm.getButton().getPreferredSize();
bm.getButton().setBounds(x, y, size.width, size.height);
}
SmartList<Pointer> argNames = new SmartList<Pointer>();
argNames.add(Heap.allocateName("args"));
argNames.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.DOUBLE_DOT));
Subprogram sub = new Subprogram(member, argNames,
new Constant(new Pointer(Constants.NULL_TYPE, 0)));
result = Heap.allocateSub(sub);
break;
} default: {
throw new MintException("Unknown object type: " + obj.type);
}
}
return result;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Method eval expression">
public Pointer evalExpression(SmartList<Pointer> pointerList,
int programPointer) throws MintException {
String codeLine = pointerList.toString();
// Note: This is not what it looks like.
// Square brackets and commas are generated by the
// toString() method of any list.
codeLine = codeLine.replace("[", "").replace("]", "").replace(",", "");
if (codeLine.startsWith("flip")) {
codeLine = codeLine.replace("flip", "").trim();
for (int i = 0; i < 10; i++) {
codeLine = codeLine.replace(" ", " ");
}
String[] vars = codeLine.split(" ");
/* The following 3 lines are equivalent to:
* temp = a
* a = b
* b = temp
* Which is the same as Python's a, b = b, a.
*/
Pointer temp = env.getValue(vars[0]);
env.put(vars[0], env.getValue(vars[1]));
env.put(vars[1], temp);
return Constants.MINT_NULL;
}
if (pointerList.isEmpty()) {
return Constants.MINT_NULL;
}
// Evaluate parentheses:
while (shouldEvalParentheses(pointerList, env)) {
int start = ListTools.findFirst(pointerList, Constants.OPEN_PAREN);
int end = ListTools.findMatchingCloseParen(pointerList, start + 1);
if (start != -1 && end != -1) {
//Recursively evaluate what is inside the parentheses:
SmartList<Pointer> subList = new SmartList<Pointer>(
pointerList.subList(start + 1, end));
Pointer insideParens = evalExpression(subList, programPointer);
pointerList.assignSublist(start, end + 1, insideParens);
} else {
throw new MintException(
"Mismatched parentheses for expression: " + pointerList);
}
}
// Correct unary plus and minus signs:
Pointer first = pointerList.get(0);
if (first != null && first.type == Constants.KEYWORD_TYPE) {
if (first.value == Constants.PLUS)
pointerList.remove(0);
else if (first.value == Constants.MINUS) {
pointerList.remove(0);
Pointer toBeNegated = evaluateName(pointerList.get(0), env);
pointerList.set(0, Operator.negate(toBeNegated));
}
}
int j = 1;
while (j + 1 < pointerList.size()) {
Pointer current = pointerList.get(j);
if (current != null && current.type == Constants.KEYWORD_TYPE) {
int keyword = PointerTools.dereferenceKeyword(current);
if (Constants.OP_FAMILY.contains(keyword) &&
keyword != Constants.OPEN_PAREN &&
keyword != Constants.CLOSE_PAREN) {
Pointer next = pointerList.get(j + 1);
if (next.type == Constants.KEYWORD_TYPE) {
int keyword2 = PointerTools.dereferenceKeyword(next);
if (keyword2 == Constants.PLUS)
pointerList.remove(j + 1);
else if (keyword2 == Constants.MINUS) {
pointerList.remove(j + 1);
Pointer p = evaluateName(pointerList.get(j + 1),
env);
pointerList.set(j + 1, Operator.negate(p));
}
}
}
}
j++;
}
int simplificationLimit = 10000;
int simplificationLevel = 0;
Integer[] singleKwds = {Constants.INPUT, Constants.ELSE, Constants.END,
Constants.RETURN, Constants.CONTINUE,
Constants.BREAK, Constants.LEAVE,
Constants.DEFAULT};
SmartList<Integer> singleKeywords = new SmartList<Integer>(singleKwds);
int precedence = 6;
int i = 0;
while (pointerList.size() > 1 ||
(pointerList.get(0) != null &&
singleKeywords.contains(PointerTools.dereferenceKeyword(
pointerList.get(0))))) {
simplificationLevel++;
if (simplificationLevel > simplificationLimit) {
throw new MintException("Cannot simplify expression: " +
pointerList);
}
Pointer current = pointerList.get(i);
String n = "";
if (current != null) {
n = PointerTools.dereferenceName(current);
}
boolean isName = n != null;
if (isName) {
try {
Pointer value = env.getValue(n);
boolean isEither = value != null &&
value.type == Constants.SUBPROGRAM_TYPE;
if (isEither && i + 1 < pointerList.size() &&
PointerTools.dereferenceKeyword(pointerList.get(i + 1))
== Constants.OPEN_PAREN) {
Pointer result;
Subprogram sub = PointerTools.dereferenceSub(value);
if (sub == null) {
System.err.println("Warning: " +
PointerTools.dereferenceAsString(value) +
" is not a subprogram.");
result = Constants.MINT_NULL;
} else {
int neededArgs = sub.getArgNamesLength();
result = sub.execute(env, imports,
getArgs(pointerList, i + 1, neededArgs),
this);
}
int end =
ListTools.findMatchingCloseParen(pointerList, i + 2);
pointerList.assignSublist(i, end + 1, result);
i = -1;
}
} catch (MintException ex) {
String msg = ex.getMessage();
if (!msg.endsWith("is not defined.")) {
throw new MintException(msg.replace("Error: ", ""));
}
} catch (NullPointerException ex) {
}
} else if (current.type == Constants.SUBPROGRAM_TYPE) {
Integer keyword =
PointerTools.dereferenceKeyword(pointerList.get(i + 1));
if (i + 1 < pointerList.size() && keyword != null &&
keyword == Constants.OPEN_PAREN) {
Subprogram sub = PointerTools.dereferenceSub(current);
int neededArgs = sub.getArgNamesLength();
Pointer result = sub.execute(env, imports,
getArgs(pointerList, i + 1, neededArgs),
this);
int end =
ListTools.findMatchingCloseParen(pointerList, i + 2);
pointerList.assignSublist(i, end + 1, result);
i = -1;
}
} else if (current.type == Constants.LIST_TYPE &&
shouldEvalIndex(pointerList)) {
boolean inBounds = i - 1 >= 0;
Pointer ptr = null;
boolean isIndexable = false;
if (inBounds) {
ptr = evaluateName(pointerList.get(i - 1), env);
isIndexable = ptr.type == Constants.LIST_TYPE ||
ptr.type == Constants.STR_TYPE ||
ptr.type == Constants.OBJECT_TYPE ||
ptr.type == Constants.BYTES_TYPE;
}
if (isIndexable) {
// Index strings:
if (ptr.type == Constants.STR_TYPE) {
String str = PointerTools.dereferenceString(
evaluateName(pointerList.get(i - 1), env));
int index = PointerTools.dereferenceInt(
evaluateName(PointerTools.dereferenceList(
pointerList.get(i)).get(0), env));
try {
if (index < 0)
index += str.length();
pointerList.assignSublist(i - 1, i + 1,
Heap.allocateString("" + str.charAt(index)));
} catch (IndexOutOfBoundsException ex) {
throw new MintException("Index " + index +
" is out of bounds. Must be between -" +
str.length() + " and " +
(str.length() - 1) + ", inclusive." +
" Expression is: " + pointerList);
}
} else if (ptr.type == Constants.BYTES_TYPE) {
SmartList<Byte> bytes = PointerTools.dereferenceBytes(
evaluateName(pointerList.get(i - 1), env));
int index = PointerTools.dereferenceInt(
evaluateName(PointerTools.dereferenceList(
pointerList.get(i)).get(0), env));
try {
pointerList.assignSublist(i - 1, i + 1,
Heap.allocateInt(bytes.get(index)));
} catch (IndexOutOfBoundsException ex) {
throw new MintException("Index " + index +
" is out of bounds. Must be between -" +
bytes.size() + " and " +
(bytes.size() - 1) + ", inclusive." +
" Expression is: " + pointerList);
}
// Index objects with a "get" method:
} else if (ptr.type == Constants.OBJECT_TYPE) {
MintObject obj = PointerTools.dereferenceObject(
evaluateName(pointerList.get(i - 1), env));
int index = PointerTools.dereferenceInt(
evaluateName(PointerTools.dereferenceList(
pointerList.get(i)).get(0), env));
try {
Subprogram get = PointerTools.dereferenceSub(
obj.get("get"));
SmartList<Pointer> args = new SmartList<Pointer>();
args.add(Heap.allocateInt(index));
Pointer val = get.execute(env, imports, args, this);
pointerList.assignSublist(i - 1, i + 1, val);
} catch (IndexOutOfBoundsException ex) {
throw new MintException("Index " + index +
" is out of bounds.");
}
// Index lists:
} else {
SmartList<Pointer> list =
PointerTools.dereferenceList(
evaluateName(pointerList.get(i - 1), env));
Integer index = PointerTools.dereferenceInt(
evaluateName(PointerTools.dereferenceList(
pointerList.get(i)).get(0), env));
if (ListTools.isTable(list)) {
Table t = ListTools.toTable(list);
Pointer idx =
evaluateName(PointerTools.dereferenceList(
pointerList.get(i)).get(0), env);
try {
Pointer val = t.getValue(idx);
if (val.type == Constants.NULL_TYPE) {
try {
pointerList.assignSublist(i - 1, i + 1,
list.get(index));
} catch (IndexOutOfBoundsException ex) {
throw new MintException(
"Index " + index +
" is out of bounds. Must be between -" +
list.size() + " and " +
(list.size() - 1) + ", inclusive." +
" Expression is: " + pointerList);
}
} else {
pointerList.assignSublist(i - 1, i + 1,
val);
}
} catch (IndexOutOfBoundsException ex) {
throw new MintException("Key " +
idx.toString() +
" does not exist for this table." +
pointerList);
}
} else {
Pointer p = list.get(index);
if (p.type == Constants.KEYWORD_TYPE) {
int keyword = PointerTools.dereferenceKeyword(
p);
SmartList<Pointer> newList =
new SmartList<Pointer>();
newList.add(Heap.allocateList(list));
if (keyword == Constants.ELLIPSIS) {
pointerList.assignSublist(i - 1, i + 1,
newList);
}
} else {
try {
pointerList.assignSublist(i - 1, i + 1,
list.get(index));
} catch (IndexOutOfBoundsException ex) {
throw new MintException("Index " + index +
" is out of bounds. Must be between -" +
list.size() + " and " +
(list.size() - 1) + ", inclusive." +
" Expression is: " + pointerList);
}
}
}
}
}
} else if (current.type == Constants.INT_TYPE ||
current.type == Constants.REAL_TYPE ||
current.type == Constants.NAME_TYPE) {
if (current.type == Constants.NAME_TYPE)
current = evaluateName(current, env);
if ((current.type == Constants.INT_TYPE ||
current.type == Constants.REAL_TYPE) &&
i + 1 < pointerList.size()) {
Pointer next = pointerList.get(i + 1);
if (next.type == Constants.INT_TYPE ||
next.type == Constants.REAL_TYPE ||
next.type == Constants.NAME_TYPE) {
pointerList.assignSublist(i, i + 2,
Operator.multiplicationFamily(
Constants.MULTIPLY, current, next));
}
}
}
Integer keyword = null;
if (current != null) {
keyword = PointerTools.dereferenceKeyword(current);
}
if (keyword != null) {
if (keyword == Constants.LINE_COMMENT) {
if (i == 0)
return Constants.MINT_NULL;
pointerList = new SmartList<Pointer>(
pointerList.subList(0, i));
i = -1;
} else if (keyword == Constants.INPUT) {
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
String input;
try {
input = keyboard.readLine();
} catch (IOException ex) {
throw new MintException("Cannot read user input.");
}
pointerList.set(i, Heap.allocateString(input));
} else if (keyword == Constants.OPEN_BRACKET) {
// Build a list:
SmartList<Pointer> elems = getElements(pointerList, i);
int end =
ListTools.findMatchingCloseBracket(pointerList,
i + 1);
if (end == i + 1) {
pointerList.assignSublist(i, end + 1,
Heap.allocateList(new SmartList<Pointer>()));
} else {
pointerList.assignSublist(i, end + 1,
Heap.allocateList(elems));
}
} else if (keyword == Constants.OPEN_BRACE) {
// Build a list:
SmartList<Pointer> elems = getElementsTable(pointerList, i);
int end =
ListTools.findMatchingCloseBrace(pointerList,
i + 1);
if (end == i + 1) {
pointerList.assignSublist(i, end + 1,
Heap.allocateTable(new Table()));
} else {
Table t = new Table();
t.addAll(elems);
pointerList.assignSublist(i, end + 1,
Heap.allocateTable(t));
}
} else if (Constants.UNARY_FAMILY.contains(keyword) ||
keyword == Constants.DOT &&
precedence <= 6) {
if (keyword == Constants.DOT) {
if (shouldEvalDot(pointerList)) {
pointerList.assignSublist(i - 1, i + 2,
evalDot(pointerList, i));
}
} else {
Pointer p;
Pointer result;
if (keyword == Constants.NOT) {
p = evaluateName(pointerList.get(i + 1), env);
result = Operator.not(p);
} else {
String name = PointerTools.dereferenceName(
pointerList.get(i - 1));
p = evaluateName(pointerList.get(i - 1), env);
result = p;
if (keyword == Constants.INCREMENT) {
p = Operator.increment(p);
} else {
p = Operator.decrement(p);
}
env.put(name, p);
}
if (keyword == Constants.NOT)
pointerList.assignSublist(i, i + 2, result);
else {
pointerList = new SmartList<Pointer>();
pointerList.add(result);
}
}
} else if (keyword == Constants.POWER && precedence <= 5) {
Pointer p1 = evaluateName(pointerList.get(i - 1), env);
Pointer p2 = evaluateName(pointerList.get(i + 1), env);
Pointer result = Operator.power(p1, p2);
pointerList.assignSublist(i - 1, i + 2, result);
} else if (Constants.MULT_FAMILY.contains(keyword) &&
precedence <= 4) {
Pointer p1 = evaluateName(pointerList.get(i - 1), env);
Pointer p2 = evaluateName(pointerList.get(i + 1), env);
Pointer result = Operator.multiplicationFamily(keyword,
p1, p2);
pointerList.assignSublist(i - 1, i + 2, result);
} else if (Constants.ADD_FAMILY.contains(keyword) &&
precedence <= 3) {
Pointer p1 = evaluateName(pointerList.get(i - 1), env);
Pointer p2 = evaluateName(pointerList.get(i + 1), env);
Pointer result = Operator.additionFamily(keyword, p1, p2);
pointerList.assignSublist(i - 1, i + 2, result);
} else if (Constants.COMP_FAMILY.contains(keyword) &&
precedence <= 2) {
Pointer p1 = evaluateName(pointerList.get(i - 1), env);
Pointer p2 = evaluateName(pointerList.get(i + 1), env);
Pointer result = Operator.comparisonFamily(keyword, p1, p2);
pointerList.assignSublist(i - 1, i + 2, result);
} else if (Constants.LOGIC_FAMILY.contains(keyword) &&
precedence <= 1) {
Pointer p1 = evaluateName(pointerList.get(i - 1), env);
Pointer p2 = evaluateName(pointerList.get(i + 1), env);
Pointer result = Operator.logicFamily(keyword, p1, p2);
pointerList.assignSublist(i - 1, i + 2, result);
} else if (Constants.TIER0_KEYWORDS.contains(keyword)) {
pointerList = applyTier0Keyword(keyword, pointerList, i);
}
} /* else {
if (current.type == Constants.NULL_TYPE) {
Pointer p = pointerList.get(i - 1);
if (p.type == Constants.STR_TYPE) {
String s = PointerTools.dereferenceString(p);
// Execute the string as a function!
pointerList.assignSublist(i - 1, i + 1, run(s, true));
} else {
// Ignore the null.
pointerList.assignSublist(i - 1, i + 1, p);
}
}
} */
i++;
if (i >= pointerList.size()) {
i = 0;
precedence--;
}
}
if (pointerList.isEmpty())
return Constants.MINT_NULL;
return evaluateName(pointerList.get(0), env);
}
//</editor-fold>
private int goAfterEnd(int programPointer, SmartList<SmartList<Pointer>>
pointerLists) {
//Increment the program pointer to avoid the while loop or whatever
//called this method.
programPointer++;
int neededEndStatements = 1;
while (programPointer < pointerLists.size()) {
SmartList<Pointer> currentList = pointerLists.get(programPointer);
Pointer end = new Pointer(Constants.KEYWORD_TYPE, Constants.END);
if (currentList.size() > 0 && currentList.get(0).equals(end)) {
neededEndStatements--;
}
if (neededEndStatements <= 0) {
return programPointer + 1;
}
if (currentList.size() > 0 &&
ListTools.containsPointer(Constants.BLOCK_STARTERS,
currentList.get(0))) {
neededEndStatements++;
}
programPointer++;
}
return programPointer;
}
private int goAfterCase(int programPointer,
SmartList<SmartList<Pointer>> pointerLists, int value) {
programPointer++;
while (programPointer < pointerLists.size()) {
SmartList<Pointer> line = pointerLists.get(programPointer);
Pointer first = line.get(0);
Integer kwd = PointerTools.dereferenceKeyword(first);
if (kwd != null && kwd == Constants.CASE) {
for (int i = 1; i < line.size(); i += 2) {
int j = PointerTools.dereferenceInt(line.get(i));
if (j == value)
return programPointer + 1;
}
} else if (kwd != null && kwd == Constants.DEFAULT) {
return programPointer + 1;
}
programPointer++;
}
return programPointer;
}
private int continueFalseIf(int programPointer,
SmartList<SmartList<Pointer>>
pointerLists, boolean appendNull) {
programPointer++;
if (appendNull)
loopProgramPointerStack.add(null);
SmartList<Pointer> currentList = pointerLists.get(programPointer);
SmartList<Pointer> endElseElseif = new SmartList<Pointer>();
Pointer end = new Pointer(Constants.KEYWORD_TYPE, Constants.END);
Pointer _else = new Pointer(Constants.KEYWORD_TYPE, Constants.ELSE);
Pointer elseif = new Pointer(Constants.KEYWORD_TYPE, Constants.ELSEIF);
endElseElseif.add(end);
endElseElseif.add(_else);
endElseElseif.add(elseif);
while (currentList.size() >= 1 &&
!ListTools.containsPointer(endElseElseif, currentList.get(0))) {
if (ListTools.containsPointer(Constants.BLOCK_STARTERS,
currentList.get(0))) {
programPointer = goAfterEnd(programPointer, pointerLists);
} else {
programPointer++;
}
currentList = pointerLists.get(programPointer);
}
if (!pointerLists.get(programPointer).isEmpty()) {
if (pointerLists.get(programPointer).get(0).equals(_else)) {
programPointer++;
} else if (pointerLists.get(programPointer).get(0).equals(end)) {
programPointer++;
loopProgramPointerStack.pop();
}
}
return programPointer;
}
//<editor-fold defaultstate="collapsed" desc="Method execute">
public Pointer execute(SmartList<SmartList<Pointer>> pointerLists,
SmartList<String> imports, Environment env)
throws MintException {
if (env != null) {
this.env = env;
}
if (imports != null) {
this.imports = imports;
}
int programPointer = 0;
while (programPointer < pointerLists.size()) {
try {
SmartList<Pointer> origPointerList = new SmartList<Pointer>();
for (Pointer p : pointerLists.get(programPointer)) {
origPointerList.add(p);
}
Pointer value = evalExpression(pointerLists.get(programPointer),
programPointer);
pointerLists.set(programPointer, origPointerList);
if (value == null || value.type != Constants.MESSAGE_TYPE)
programPointer++;
else {
Message msg = PointerTools.dereferenceMessage(value);
switch (msg.message) {
case Constants.ADVANCE_BY_2:
programPointer += 2;
break;
case Constants.CONTINUE_FALSE_IF:
ifStack.add(false);
programPointer = continueFalseIf(programPointer,
pointerLists, true);
break;
case Constants.POP_PTR:
if (!loopProgramPointerStack.isEmpty()) {
Integer newPtr = loopProgramPointerStack.pop();
if (newPtr != null) {
programPointer = newPtr;
} else {
programPointer++;
ifStack.pop();
}
} else {
programPointer++;
}
break;
case Constants.PUSH_EMPTY_PTR:
ifStack.add(true);
loopProgramPointerStack.add(null);
programPointer++;
break;
case Constants.GO_AFTER_END_AND_POP:
programPointer = goAfterEnd(programPointer,
pointerLists);
if (loopProgramPointerStack.size() > 0 &&
loopProgramPointerStack.get(-1) == null) {
loopProgramPointerStack.pop();
ifStack.pop();
}
break;
case Constants.CONTINUE_TRUE_ELSEIF:
ifStack.set(-1, true);
programPointer++;
break;
case Constants.CONTINUE_FALSE_ELSEIF:
ifStack.set(-1, false);
programPointer = continueFalseIf(programPointer,
pointerLists, false);
break;
case Constants.GO_AFTER_END:
programPointer = goAfterEnd(programPointer,
pointerLists);
break;
case Constants.PUSH_PTR:
loopProgramPointerStack.add(programPointer);
programPointer++;
break;
case Constants.MSG_CONTINUE:
if (loopProgramPointerStack.isEmpty()) {
programPointer++;
} else {
int newPointer = loopProgramPointerStack.get(-1);
programPointer = newPointer + 1;
}
break;
case Constants.MSG_BREAK:
programPointer = goAfterEnd(programPointer,
pointerLists);
if (!loopProgramPointerStack.isEmpty()) {
loopProgramPointerStack.pop();
}
break;
case Constants.RETURN_VALUE:
return msg.contents.get(0);
case Constants.RESET_REPEAT_AND_GO_AFTER_END:
SmartList<Pointer> newList = new SmartList<Pointer>();
newList.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.REPEAT));
newList.add(pointerLists.get(programPointer).get(0));
pointerLists.set(programPointer, newList);
programPointer = goAfterEnd(programPointer,
pointerLists);
break;
case Constants.PUSH_PTR_AND_DECREMENT:
loopProgramPointerStack.add(programPointer);
SmartList<Pointer> currentList =
pointerLists.get(programPointer);
if (currentList.get(0).equals(
new Pointer(Constants.KEYWORD_TYPE,
Constants.REPEAT))) {
currentList.add(0, currentList.get(1));
}
SmartList<Pointer> nList = currentList.subList(2);
currentList.assignSublist(2, currentList.size(),
Heap.allocateInt(
PointerTools.dereferenceInt(
evalExpression(nList, 0)) - 1));
programPointer++;
break;
case Constants.DEFINE_SUB: {
Subprogram sub = PointerTools.dereferenceSub(
msg.contents.get(0));
programPointer++;
int neededEnds = 1;
while (programPointer < pointerLists.size()) {
SmartList<Pointer> line =
pointerLists.get(programPointer);
if (line.size() > 0) {
Pointer p = line.get(0);
Pointer end = new Pointer(
Constants.KEYWORD_TYPE, Constants.END);
if (p != null && p.equals(end)) {
neededEnds--;
if (neededEnds <= 0) {
programPointer++;
break;
}
} else if (ListTools.containsPointer(
Constants.BLOCK_STARTERS, p)) {
neededEnds++;
}
}
sub.addToBody(line);
programPointer++;
}
SmartList<Pointer> retn = new SmartList<Pointer>();
retn.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.RETURN));
// All subs must execute a return statement:
sub.addToBody(retn);
env.put(sub.getName(), Heap.allocateSub(sub));
break;
} case Constants.DEFINE_BLOCK: {
Block block = PointerTools.dereferenceBlock(
msg.contents.get(0));
programPointer++;
int neededEnds = 1;
while (programPointer < pointerLists.size()) {
SmartList<Pointer> line =
pointerLists.get(programPointer);
if (line.size() > 0) {
Pointer p = line.get(0);
Pointer end = new Pointer(
Constants.KEYWORD_TYPE, Constants.END);
if (p.equals(end)) {
neededEnds--;
if (neededEnds <= 0) {
programPointer++;
break;
}
} else if (ListTools.containsPointer(
Constants.BLOCK_STARTERS, p)) {
neededEnds++;
}
}
block.addToBody(line);
programPointer++;
SmartList<Pointer> leave = new SmartList<Pointer>();
leave.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.LEAVE));
// All subs must execute a return statement:
block.addToBody(leave);
env.put(block.getName(), Heap.allocateBlock(block));
}
break;
} case Constants.MSG_LEAVE: {
return new Pointer(Constants.NULL_TYPE, 0);
} case Constants.MSG_FOR: {
// Convert for loop into a while loop:
SmartList<Pointer> _while =
pointerLists.get(programPointer + 1);
_while.add(0, new Pointer(Constants.KEYWORD_TYPE,
Constants.WHILE));
SmartList<Pointer> initialization =
pointerLists.get(programPointer);
initialization.remove(0);
pointerLists.set(programPointer, initialization);
pointerLists.set(programPointer + 1, _while);
int p = goAfterEnd(programPointer + 1,
pointerLists);
p -= 2;
SmartList<SmartList<Pointer>> pLists =
new SmartList<SmartList<Pointer>>();
SmartList<Pointer> change =
pointerLists.remove(programPointer + 2);
pLists.add(change);
SmartList<Pointer> end = new SmartList<Pointer>();
end.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.END));
pLists.add(end);
pointerLists.assignSublist(p, p + 1, pLists);
break;
} case Constants.MSG_FOREACH: {
Pointer name = pointerLists.get(programPointer).get(1);
Pointer iterable =
pointerLists.get(programPointer).get(3);
Pointer sysVar = Heap.getNextSystemVarName();
SmartList<Pointer> assign0 = new SmartList<Pointer>();
assign0.add(sysVar);
assign0.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
assign0.add(new Pointer(Constants.INT_TYPE, 0));
SmartList<Pointer> _while = new SmartList<Pointer>();
_while.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.WHILE));
_while.add(sysVar);
_while.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.LESS_THAN));
_while.add(iterable);
_while.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.DOT));
_while.add(Heap.allocateName("size"));
_while.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_PAREN));
_while.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.CLOSE_PAREN));
SmartList<Pointer> assignI = new SmartList<Pointer>();
assignI.add(name);
assignI.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.ASSIGN));
assignI.add(iterable);
assignI.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.OPEN_BRACKET));
assignI.add(sysVar);
assignI.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.CLOSE_BRACKET));
SmartList<Pointer> increment = new SmartList<Pointer>();
increment.add(sysVar);
increment.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.INCREMENT));
SmartList<SmartList<Pointer>> pLists =
new SmartList<SmartList<Pointer>>();
pLists.add(assign0);
pLists.add(_while);
pLists.add(assignI);
pointerLists.assignSublist(programPointer,
programPointer + 1, pLists);
int p = goAfterEnd(programPointer + 2,
pointerLists);
p -= 2;
pLists = new SmartList<SmartList<Pointer>>();
pLists.add(increment);
SmartList<Pointer> end = new SmartList<Pointer>();
end.add(new Pointer(Constants.KEYWORD_TYPE,
Constants.END));
pLists.add(end);
pointerLists.assignSublist(p, p + 1, pLists);
break;
} case Constants.MSG_SWITCH: {
Pointer val = pointerLists.get(programPointer).get(1);
val = evaluateName(val, env);
programPointer = goAfterCase(programPointer,
pointerLists, PointerTools.dereferenceInt(val));
break;
} default: {
throw new MintException("Unknown message: " +
msg.message);
}
}
}
} catch (Throwable t) {
String exceptionInfo = "" + t;
if (!Mint.seduced) {
System.err.println("An error occurred at line: " +
(programPointer + 1));
System.err.println("The line contains this expression: " +
pointerLists.get(programPointer));
System.err.println();
System.err.println(exceptionInfo);
Mint.printStackTrace(t.getStackTrace());
/* System.exit(1); */
} else {
try {
StackTraceElement[] stElems = t.getStackTrace();
String stkTrce = "";
for (StackTraceElement ste : stElems) {
stkTrce +=
ste.toString().replace(".java:", " @ ") +
"\r\n";
}
FileIO.appendStrToFile(
exceptionInfo + "\r\n\r\n[STACK TRACE]\r\n" +
stkTrce +
"\r\n================\r\n",
"mint.error.log"
);
} catch (Throwable t2) {}
// Let's just move on to the next line,
// ignoring this line.
++programPointer;
}
}
}
return Constants.MINT_NULL;
}
//</editor-fold>
public void runFromFile(String ol) throws MintException {
String mintCode = FileIO.fileToStr(ol);
mintCode = mintCode.replace("\r", "\n");
for (int i = 0; i < 50 && mintCode.contains("\n\n"); i++) {
mintCode = mintCode.replace("\n\n", "\n");
}
execute(loadProgram(mintCode, true), new SmartList<String>(), env);
}
}