package gui;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
/**
* @author Oliver Chu
*/
public class Operator {
public static Pointer power(Pointer a, Pointer b) throws MintException {
if (a.type == Constants.OBJECT_TYPE &&
b.type == Constants.OBJECT_TYPE) {
Environment e = Mint.getOverloadEnv();
Pointer value;
value = e.getValue("pow");
if (value != null && value.type != Constants.NULL_TYPE) {
Subprogram power = PointerTools.dereferenceSub(value);
SmartList<Pointer> arguments = new SmartList<Pointer>();
arguments.add(a);
arguments.add(b);
return power.execute(e, new SmartList<String>(), arguments,
new Interpreter());
}
return Constants.MINT_NULL;
} else if (a.type == Constants.BIG_INT_TYPE &&
b.type == Constants.BIG_INT_TYPE) {
int operand2 = Integer.parseInt(
PointerTools.dereferenceBigInt(b).toString());
BigInteger operand1 = PointerTools.dereferenceBigInt(a);
return Heap.allocateBigInt(operand1.pow(operand2));
} else if (a.type == Constants.PRECISE_REAL_TYPE &&
b.type == Constants.PRECISE_REAL_TYPE) {
BigDecimal operand1 = PointerTools.dereferencePreciseReal(a);
BigDecimal operand2 = PointerTools.dereferencePreciseReal(b);
try {
int op2 = Integer.parseInt(operand2.toString());
return Heap.allocatePreciseReal(operand1.pow(op2));
} catch (NumberFormatException ex) {
double op1 = Double.parseDouble(operand1.toString());
double op2 = Double.parseDouble(operand2.toString());
return Heap.allocateReal(Math.pow(op1, op2));
}
}
boolean isIntResult = false;
if (a.type == Constants.INT_TYPE && b.type == Constants.INT_TYPE) {
isIntResult = true;
}
Double operand1 = PointerTools.dereferenceReal(a);
Double operand2 = PointerTools.dereferenceReal(b);
if (operand1 == null || operand2 == null) {
badTypeException(Constants.POWER, a, b);
}
double result = Math.pow(operand1, operand2);
if (isIntResult) {
return Heap.allocateInt((int)result);
}
return Heap.allocateReal(result);
}
public static Pointer multiplicationFamily(int keyword, Pointer a,
Pointer b) throws MintException {
if (a.type == Constants.KEYWORD_TYPE ||
a.type == Constants.NAME_TYPE) {
return b;
} else if (b.type == Constants.KEYWORD_TYPE ||
b.type == Constants.NAME_TYPE) {
return a;
}
if (a.type == Constants.RAT_TYPE &&
b.type == Constants.INT_TYPE) {
int bee = b.value;
b = Heap.allocRat(Rational.makeRat((long) bee, 1L));
} else if (a.type == Constants.RAT_TYPE &&
b.type == Constants.INT_TYPE) {
int ey = a.value;
a = Heap.allocRat(Rational.makeRat((long) ey, 1L));
} else if (a.type == Constants.RAT_TYPE &&
b.type == Constants.PRECISE_REAL_TYPE) {
a = Heap.allocatePreciseReal(
PointerTools.derefRat(a).toBigDecimal());
} else if (b.type == Constants.RAT_TYPE &&
a.type == Constants.PRECISE_REAL_TYPE) {
b = Heap.allocatePreciseReal(
PointerTools.derefRat(b).toBigDecimal());
} else if (a.type == Constants.RAT_TYPE &&
b.type != Constants.RAT_TYPE) {
a = Heap.allocateReal(PointerTools.derefRat(a).toDouble());
} else if (b.type == Constants.RAT_TYPE &&
a.type != Constants.RAT_TYPE) {
b = Heap.allocateReal(PointerTools.derefRat(b).toDouble());
}
if (a.type == Constants.OBJECT_TYPE &&
b.type == Constants.OBJECT_TYPE) {
Environment e = Mint.getOverloadEnv();
Pointer value;
switch (keyword) {
case Constants.MULTIPLY: {
value = e.getValue("times");
break;
} case Constants.DIVIDE: {
value = e.getValue("divide");
break;
} case Constants.MODULO: {
value = e.getValue("remainder");
break;
} case Constants.FLOOR_DIVIDE: {
value = e.getValue("divideRoundDown");
break;
} default: {
throw new MintException(
"Operator not in multiplication family: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
if (value != null && value.type != Constants.NULL_TYPE) {
Subprogram multiplication = PointerTools.dereferenceSub(value);
SmartList<Pointer> arguments = new SmartList<Pointer>();
arguments.add(a);
arguments.add(b);
return multiplication.execute(e, new SmartList<String>(),
arguments, new Interpreter());
}
return Constants.MINT_NULL;
} else if (a.type == Constants.BIG_INT_TYPE &&
b.type == Constants.BIG_INT_TYPE) {
BigInteger op1 = PointerTools.dereferenceBigInt(a);
BigInteger op2 = PointerTools.dereferenceBigInt(b);
switch (keyword) {
case Constants.MULTIPLY: {
return Heap.allocateBigInt(op1.multiply(op2));
} case Constants.DIVIDE: {
BigDecimal o1 = new BigDecimal(op1);
BigDecimal o2 = new BigDecimal(op2);
return Heap.allocatePreciseReal(o1.divide(o2, 200,
RoundingMode.HALF_UP));
} case Constants.MODULO: {
return Heap.allocateBigInt(op1.remainder(op2));
} case Constants.FLOOR_DIVIDE: {
return Heap.allocateBigInt(op1.divide(op2));
} default: {
throw new MintException(
"Operator not in multiplication family: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
} else if (a.type == Constants.PRECISE_REAL_TYPE &&
b.type == Constants.PRECISE_REAL_TYPE) {
BigDecimal op1 = PointerTools.dereferencePreciseReal(a);
BigDecimal op2 = PointerTools.dereferencePreciseReal(b);
switch (keyword) {
case Constants.MULTIPLY: {
return Heap.allocatePreciseReal(op1.multiply(op2));
} case Constants.DIVIDE: {
return Heap.allocatePreciseReal(op1.divide(op2, 200,
RoundingMode.HALF_UP));
} case Constants.MODULO: {
BigInteger o1 = new BigInteger(op1.toString());
BigInteger o2 = new BigInteger(op2.toString());
return Heap.allocateBigInt(o1.remainder(o2));
} case Constants.FLOOR_DIVIDE: {
BigInteger o1 = new BigInteger(op1.toString());
BigInteger o2 = new BigInteger(op2.toString());
return Heap.allocateBigInt(o1.divide(o2));
} default: {
throw new MintException(
"Operator not in multiplication family: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
}
if (a.type == Constants.RAT_TYPE && b.type == Constants.RAT_TYPE) {
Rational rat1 = PointerTools.derefRat(a);
Rational rat2 = PointerTools.derefRat(b);
switch (keyword) {
case Constants.MULTIPLY: {
Rational ans = rat1.mul(rat2);
return Heap.allocRat(ans);
} case Constants.DIVIDE: {
Rational ans = rat1.div(rat2);
return Heap.allocRat(ans);
} case Constants.FLOOR_DIVIDE: {
Rational ans = rat1.div(rat2);
return Heap.allocateInt((int) ans.toDouble());
} case Constants.MODULO: {
BigDecimal upper = rat1.toBigDecimal();
BigDecimal lower = rat2.toBigDecimal();
BigDecimal modded = upper.remainder(lower,
MathContext.DECIMAL128);
return Heap.allocatePreciseReal(modded);
}
}
}
if (a.type == Constants.REAL_TYPE || b.type == Constants.REAL_TYPE) {
Double operand1 = PointerTools.dereferenceReal(a);
Double operand2 = PointerTools.dereferenceReal(b);
if (operand1 == null || operand2 == null) {
badTypeException(keyword, a, b);
}
switch (keyword) {
case Constants.MULTIPLY: {
double result = operand1 * operand2;
return Heap.allocateReal(result);
} case Constants.DIVIDE: {
double result =
Rational.divideCorrectly(
(double) operand1, (double) operand2);
return Heap.allocateReal(result);
} case Constants.FLOOR_DIVIDE: {
double op1 = operand1;
double op2 = operand2;
int result = (int) op1 / (int) op2;
return Heap.allocateInt(result);
} case Constants.MODULO: {
double op1 = operand1;
double op2 = operand2;
double result = op1 % op2;
return Heap.allocateReal(result);
} default:
throw new MintException(
"Operator not in multiplication family: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
Integer operand1 = PointerTools.dereferenceInt(a);
Integer operand2 = PointerTools.dereferenceInt(b);
if (operand1 == null || operand2 == null) {
badTypeException(keyword, a, b);
}
switch (keyword) {
case Constants.MULTIPLY: {
int result = operand1 * operand2;
return Heap.allocateInt(result);
} case Constants.DIVIDE: {
// To divide integers, we simply create a new
// rational number, and don't really divide anything.
Rational result = Rational.makeRat(
operand1.longValue(), operand2.longValue());
return Heap.allocRat(result);
} case Constants.FLOOR_DIVIDE: {
int result = operand1 / operand2;
return Heap.allocateInt(result);
} case Constants.MODULO: {
int result = operand1 % operand2;
return Heap.allocateInt(result);
} default:
throw new MintException(
"Operator not in multiplication family: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
public static Pointer additionFamily(int keyword, Pointer a, Pointer b)
throws MintException {
if (a.type == Constants.RAT_TYPE && b.type == Constants.RAT_TYPE) {
Rational ey = PointerTools.derefRat(a);
Rational bee = PointerTools.derefRat(b);
if (keyword == Constants.PLUS) {
return Heap.allocRat(ey.add(bee));
} else {
return Heap.allocRat(ey.sub(bee));
}
}
if (a.type == Constants.RAT_TYPE) {
a = Heap.allocateReal(PointerTools.derefRat(a).toDouble());
}
if (b.type == Constants.RAT_TYPE) {
b = Heap.allocateReal(PointerTools.derefRat(b).toDouble());
}
if (a.type == Constants.OBJECT_TYPE &&
b.type == Constants.OBJECT_TYPE) {
Environment e = Mint.getOverloadEnv();
Pointer value;
if (keyword == Constants.PLUS) {
value = e.getValue("plus");
} else {
value = e.getValue("minus");
}
if (value != null && value.type != Constants.NULL_TYPE) {
Subprogram addition = PointerTools.dereferenceSub(value);
SmartList<Pointer> arguments = new SmartList<Pointer>();
arguments.add(a);
arguments.add(b);
return addition.execute(e, new SmartList<String>(), arguments,
new Interpreter());
}
return Constants.MINT_NULL;
} else if (a.type == Constants.BIG_INT_TYPE &&
b.type == Constants.BIG_INT_TYPE) {
BigInteger op1 = PointerTools.dereferenceBigInt(a);
BigInteger op2 = PointerTools.dereferenceBigInt(b);
if (keyword == Constants.PLUS) {
return Heap.allocateBigInt(op1.add(op2));
} else {
return Heap.allocateBigInt(op1.subtract(op2));
}
} else if (a.type == Constants.PRECISE_REAL_TYPE &&
b.type == Constants.PRECISE_REAL_TYPE) {
BigDecimal op1 = PointerTools.dereferencePreciseReal(a);
BigDecimal op2 = PointerTools.dereferencePreciseReal(b);
if (keyword == Constants.PLUS) {
return Heap.allocatePreciseReal(op1.add(op2));
} else {
return Heap.allocatePreciseReal(op1.subtract(op2));
}
}
if (a.type == Constants.STR_TYPE && b.type == Constants.STR_TYPE) {
String operand1 = PointerTools.dereferenceString(a);
String operand2 = PointerTools.dereferenceString(b);
if (operand1 == null || operand2 == null) {
badTypeException(keyword, a, b);
}
if (keyword == Constants.PLUS) {
return Heap.allocateString(operand1 + operand2);
} else {
return Heap.allocateString(operand1.replace(operand2, ""));
}
} else if (a.type == Constants.LIST_TYPE &&
b.type == Constants.LIST_TYPE) {
SmartList<Pointer> list1 = PointerTools.dereferenceList(a);
SmartList<Pointer> list2 = PointerTools.dereferenceList(b);
if (list1 == null || list2 == null) {
badTypeException(keyword, a, b);
}
if (keyword == Constants.PLUS) {
SmartList<Pointer> finalList = new SmartList<Pointer>();
finalList.addAll(list1);
finalList.addAll(list2);
return Heap.allocateList(finalList);
} else {
for (Pointer pTwo : list2) {
int i = 0;
for (Pointer pOne : list1) {
if (PointerTools.dereferenceAsString(pOne).equals(
PointerTools.dereferenceAsString(pTwo))) {
list1.remove(i);
}
++i;
}
}
return Heap.allocateList(list1);
}
} else if (a.type == Constants.REAL_TYPE ||
b.type == Constants.REAL_TYPE) {
Double operand1 = PointerTools.dereferenceReal(a);
Double operand2 = PointerTools.dereferenceReal(b);
if (operand1 == null || operand2 == null) {
badTypeException(keyword, a, b);
}
if (keyword == Constants.PLUS) {
double result = operand1 + operand2;
return Heap.allocateReal(result);
} else {
double result = operand1 - operand2;
return Heap.allocateReal(result);
}
}
Integer operand1 = PointerTools.dereferenceInt(a);
Integer operand2 = PointerTools.dereferenceInt(b);
if (operand1 == null || operand2 == null) {
badTypeException(keyword, a, b);
}
if (keyword == Constants.PLUS) {
int result = operand1 + operand2;
return Heap.allocateInt(result);
} else {
int result = operand1 - operand2;
return Heap.allocateInt(result);
}
}
public static Pointer negate(Pointer p) throws MintException {
if (p.type == Constants.RAT_TYPE) {
Rational r = PointerTools.derefRat(p);
if (r.d >= 0) {
return Heap.allocRat(Rational.makeRat(-r.n, r.d));
} else {
/** The following two lines do NOT change
* the value of the rational. We know r.d < 0 is true.
*/
r.d = -r.d;
r.n = -r.n;
return Heap.allocRat(Rational.makeRat(-r.n, r.d));
}
}
if (p.type == Constants.BIG_INT_TYPE) {
return Heap.allocateBigInt(
PointerTools.dereferenceBigInt(p).negate());
} else if (p.type == Constants.PRECISE_REAL_TYPE) {
return Heap.allocatePreciseReal(
PointerTools.dereferencePreciseReal(p).negate());
}
if (p.type == Constants.INT_TYPE) {
return Heap.allocateInt(-p.value);
} else if (p.type == Constants.REAL_TYPE) {
return Heap.allocateReal(-PointerTools.dereferenceReal(p));
} else if (p.type == Constants.STR_TYPE) {
String text = PointerTools.dereferenceString(p);
return Heap.allocateString(
new StringBuffer(text).reverse().toString());
} else {
badTypeException(Constants.MINUS, p);
}
//Will not be executed:
return null;
}
public static Pointer comparisonFamily(int keyword, Pointer a, Pointer b)
throws MintException {
if (a == null || b == null) {
switch (keyword) {
case Constants.EQUAL:
return a == b ? Constants.MINT_TRUE : Constants.MINT_FALSE;
case Constants.NOT_EQUAL:
return a != b ? Constants.MINT_TRUE : Constants.MINT_FALSE;
default: {
return Heap.allocateString(
"<error: Trying to compare Java null with " +
"itself or with Mint objects without " +
"using the == or != operators.>"
);
}
}
}
if (a.type == Constants.RAT_TYPE) {
a = Heap.allocateReal(PointerTools.derefRat(a).toDouble());
}
if (b.type == Constants.RAT_TYPE) {
b = Heap.allocateReal(PointerTools.derefRat(b).toDouble());
}
if (a.type == Constants.OBJECT_TYPE &&
b.type == Constants.OBJECT_TYPE) {
Environment e = Mint.getOverloadEnv();
Pointer value;
switch (keyword) {
case Constants.EQUAL:
value = e.getValue("equal");
break;
case Constants.NOT_EQUAL:
value = e.getValue("notEqual");
break;
case Constants.GTR_THAN:
value = e.getValue("greater");
break;
case Constants.LESS_THAN:
value = e.getValue("lesser");
break;
case Constants.GTR_OR_EQUAL:
value = e.getValue("greaterEqual");
break;
case Constants.LESS_OR_EQUAL:
value = e.getValue("lesserEqual");
break;
default:
throw new MintException("Unknown comparison operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
if (value != null && value.type != Constants.NULL_TYPE) {
Subprogram power = PointerTools.dereferenceSub(value);
SmartList<Pointer> arguments = new SmartList<Pointer>();
arguments.add(a);
arguments.add(b);
return power.execute(e, new SmartList<String>(), arguments,
new Interpreter());
}
return Constants.MINT_NULL;
} else if (a.type == Constants.BIG_INT_TYPE &&
b.type == Constants.BIG_INT_TYPE) {
BigInteger op1 = PointerTools.dereferenceBigInt(a);
BigInteger op2 = PointerTools.dereferenceBigInt(b);
switch (keyword) {
case Constants.EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) == 0);
case Constants.NOT_EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) != 0);
case Constants.GTR_THAN:
return Heap.allocateTruth(op1.compareTo(op2) > 0);
case Constants.LESS_THAN:
return Heap.allocateTruth(op1.compareTo(op2) < 0);
case Constants.GTR_OR_EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) >= 0);
case Constants.LESS_OR_EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) <= 0);
default:
throw new MintException("Unknown comparison operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
} else if (a.type == Constants.PRECISE_REAL_TYPE &&
b.type == Constants.PRECISE_REAL_TYPE) {
BigDecimal op1 = PointerTools.dereferencePreciseReal(a);
BigDecimal op2 = PointerTools.dereferencePreciseReal(b);
switch (keyword) {
case Constants.EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) == 0);
case Constants.NOT_EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) != 0);
case Constants.GTR_THAN:
return Heap.allocateTruth(op1.compareTo(op2) > 0);
case Constants.LESS_THAN:
return Heap.allocateTruth(op1.compareTo(op2) < 0);
case Constants.GTR_OR_EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) >= 0);
case Constants.LESS_OR_EQUAL:
return Heap.allocateTruth(op1.compareTo(op2) <= 0);
default:
throw new MintException("Unknown comparison operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
if (a.type == Constants.STR_TYPE && b.type == Constants.STR_TYPE) {
String oStr1 = PointerTools.dereferenceString(a);
String oStr2 = PointerTools.dereferenceString(b);
switch (keyword) {
case Constants.EQUAL:
return Heap.allocateTruth(oStr1.equals(oStr2));
case Constants.NOT_EQUAL:
return Heap.allocateTruth(!oStr1.equals(oStr2));
case Constants.GTR_THAN:
return Heap.allocateTruth(oStr1.length() > oStr2.length());
case Constants.LESS_THAN:
return Heap.allocateTruth(oStr1.length() < oStr2.length());
case Constants.GTR_OR_EQUAL:
return Heap.allocateTruth(oStr1.length() >= oStr2.length());
case Constants.LESS_OR_EQUAL:
return Heap.allocateTruth(oStr1.length() <= oStr2.length());
default:
throw new MintException("Unknown comparison operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
} else if ((a.type == Constants.INT_TYPE ||
a.type == Constants.REAL_TYPE) &&
(b.type == Constants.INT_TYPE ||
b.type == Constants.REAL_TYPE)) {
Double operand1 = PointerTools.dereferenceReal(a);
Double operand2 = PointerTools.dereferenceReal(b);
boolean areCloseEnough = Rational.closeEnough(operand1, operand2);
switch (keyword) {
case Constants.EQUAL:
return Heap.allocateTruth(areCloseEnough);
case Constants.NOT_EQUAL:
return Heap.allocateTruth(!areCloseEnough);
case Constants.GTR_THAN:
return Heap.allocateTruth(operand1 > operand2);
case Constants.LESS_THAN:
return Heap.allocateTruth(operand1 < operand2);
case Constants.GTR_OR_EQUAL:
return Heap.allocateTruth((operand1 > operand2) ||
areCloseEnough);
case Constants.LESS_OR_EQUAL:
return Heap.allocateTruth((operand1 < operand2) ||
areCloseEnough);
default:
throw new MintException("Unknown comparison operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
} else if (a.type == Constants.NULL_TYPE &&
b.type == Constants.NULL_TYPE) {
if (keyword == Constants.EQUAL) {
return Heap.allocateTruth(true);
} else if (keyword == Constants.NOT_EQUAL) {
return Heap.allocateTruth(false);
}
badTypeException(keyword, a, b);
} else if (a.type == Constants.TRUTH_TYPE &&
b.type == Constants.TRUTH_TYPE) {
Boolean operand1 = PointerTools.dereferenceTruth(a);
Boolean operand2 = PointerTools.dereferenceTruth(b);
if (keyword == Constants.EQUAL) {
return Heap.allocateTruth(operand1 == operand2);
} else if (keyword == Constants.NOT_EQUAL) {
return Heap.allocateTruth(operand1 != operand2);
}
badTypeException(keyword, a, b);
} else {
if (keyword == Constants.EQUAL) {
return Heap.allocateTruth(false);
} else if (keyword == Constants.NOT_EQUAL) {
return Heap.allocateTruth(true);
}
}
badTypeException(keyword, a, b);
// Will not be executed:
return null;
}
private static char shiftChr(char c) {
if (Character.isLetter(c)) {
// Toggle 0x20, a.k.a. 32 or the space character,
// to turn uppercase into lowercase and vice versa.
return (char) (c ^ ' ');
} else if (Character.isDigit(c)) {
c -= '0';
if (!(c >= 0 && c <= 9)) {
return '?';
}
return ")!@#$%^&*(".charAt(c);
} else {
switch (c) {
case '`':
return '~';
case '\t':
return ' ';
case '\\':
return '|';
case '[':
return '{';
case ']':
return '}';
case ',':
return '<';
case '.':
return '>';
case '/':
return '?';
case '-':
return '_';
case '=':
return '+';
default:
return c;
}
}
}
public static Pointer not(Pointer p) throws MintException {
if (p.type == Constants.RAT_TYPE) {
// Invert the rational number.
Rational rat = PointerTools.derefRat(p);
return Heap.allocRat(Rational.makeRat(rat.d, rat.n));
}
if (p.type == Constants.STR_TYPE) {
String text = PointerTools.dereferenceString(p);
String nText = "";
for (char c : text.toCharArray()) {
nText += shiftChr(c);
}
return Heap.allocateString(nText);
}
Double really = PointerTools.dereferenceReal(p);
if (p.type == Constants.REAL_TYPE) {
return Heap.allocateReal(1.0 - really);
}
if (p.type != Constants.TRUTH_TYPE) {
badTypeException(Constants.NOT, p);
}
return Heap.allocateTruth(!PointerTools.dereferenceTruth(p));
}
public static Pointer increment(Pointer p) throws MintException {
if (p.type == Constants.BIG_INT_TYPE) {
return Heap.allocateBigInt(
PointerTools.dereferenceBigInt(p).add(BigInteger.ONE));
} else if (p.type == Constants.PRECISE_REAL_TYPE) {
return Heap.allocatePreciseReal(
PointerTools.dereferencePreciseReal(p).add(BigDecimal.ONE));
}
switch (p.type) {
case Constants.INT_TYPE: {
int x = PointerTools.dereferenceInt(p);
return Heap.allocateInt(x + 1);
} case Constants.REAL_TYPE: {
double x = PointerTools.dereferenceReal(p);
return Heap.allocateReal(x + 1);
} case Constants.STR_TYPE: {
return Heap.allocateString(
PointerTools.dereferenceString(p) + ' ');
} default: {
badTypeException(Constants.INCREMENT, p);
}
}
return null;
}
public static Pointer decrement(Pointer p) throws MintException {
if (p.type == Constants.BIG_INT_TYPE) {
return Heap.allocateBigInt(
PointerTools.dereferenceBigInt(p).subtract(BigInteger.ONE));
} else if (p.type == Constants.PRECISE_REAL_TYPE) {
return Heap.allocatePreciseReal(
PointerTools.dereferencePreciseReal(p).subtract(
BigDecimal.ONE));
}
switch (p.type) {
case Constants.STR_TYPE: {
String text = PointerTools.dereferenceString(p);
if (text.isEmpty()) {
return Heap.allocateString("");
}
return Heap.allocateString(text.substring(0,
text.length() - 1));
} case Constants.INT_TYPE: {
int x = PointerTools.dereferenceInt(p);
return Heap.allocateInt(x - 1);
} case Constants.REAL_TYPE: {
double x = PointerTools.dereferenceReal(p);
return Heap.allocateReal(x - 1);
} default: {
badTypeException(Constants.DECREMENT, p);
}
}
return null;
}
public static Pointer logicFamily(int keyword, Pointer a, Pointer b) throws
MintException {
if (a.type == Constants.STR_TYPE && b.type == Constants.STR_TYPE) {
String txtA = PointerTools.dereferenceString(a);
String txtB = PointerTools.dereferenceString(b);
// Fuzzy logic:
switch (keyword) {
case Constants.AND:
// textA and textB
// First part holds characters a (for each a of A)
// that are contained in B.
// Second part holds characters a (for each a of A)
// that are not contained in B.
String chrAinB = "";
String chrAnotInB = "";
for (char c : txtA.toCharArray()) {
if (txtB.contains("" + c)) {
chrAinB += c;
} else {
chrAnotInB += c;
}
}
SmartList<Pointer> ptrList = new SmartList<Pointer>();
ptrList.add(Heap.allocateString(chrAinB));
ptrList.add(Heap.allocateString(chrAnotInB));
return Heap.allocateList(ptrList);
case Constants.OR:
// textA or textB returns textA if and only if
// textA is alphabetically before textB, such as
// ABCD coming before CATGIRL.
if (txtA.compareTo(txtB) < 0) {
// Don't reallocate pointers!
return a;
} else {
return b;
}
case Constants.XOR:
// textA xor textB
// First value is a string that contains
// all chars a is b, with (for a in A) and (for b in B)
// running simultaneously.
// Second value is a list that contains
// pairs "ab" such that a != b with (for a in A) and
// (for b in B)
// running simultaneously.
// Ignores leftover characters.
// Run for a in A and for b in B at the same time:
int limit = Math.min(txtA.length(), txtB.length());
String indexMatches = "";
SmartList<Pointer> failedMatches = new SmartList<Pointer>();
for (int i = 0; i < limit; ++i) {
char alpha = txtA.charAt(i);
char beta = txtB.charAt(i);
if (alpha == beta) {
indexMatches += alpha;
} else {
failedMatches.add(
Heap.allocateString(alpha + "" + beta));
}
}
SmartList<Pointer> listOfSequences =
new SmartList<Pointer>();
listOfSequences.add(Heap.allocateString(indexMatches));
listOfSequences.add(Heap.allocateList(failedMatches));
return Heap.allocateList(listOfSequences);
default:
throw new MintException("Unknown logical operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
// textA or textB
// extracts only the characters that do not match.
}
Double aDbl = PointerTools.dereferenceReal(a);
Double bDbl = PointerTools.dereferenceReal(b);
if (aDbl != null && bDbl != null) {
// Fuzzy logic:
switch (keyword) {
case Constants.AND:
return Heap.allocateReal(Math.max(aDbl, bDbl));
case Constants.OR:
return Heap.allocateReal(Math.min(aDbl, bDbl));
case Constants.XOR:
double result = Math.min(Math.max(aDbl, 1 - bDbl),
Math.max(1 - aDbl, bDbl));
return Heap.allocateReal(result);
default:
throw new MintException("Unknown logical operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
if (a.type != Constants.TRUTH_TYPE || b.type != Constants.TRUTH_TYPE) {
System.err.println(
"The correct way to write a condition such as...\n\n" +
// <br /><br />
"x == 3 or 4 or 5\n\n" +
// <br /><br />
"is: (x == 3) or (x == 4) or (x == 5).\n" +
"You may also use (x in [3, 4, 5]), which is equivalent."
);
badTypeException(keyword, a, b);
}
Boolean operand1 = PointerTools.dereferenceTruth(a);
Boolean operand2 = PointerTools.dereferenceTruth(b);
switch (keyword) {
case Constants.AND:
return Heap.allocateTruth(operand1 && operand2);
case Constants.OR:
return Heap.allocateTruth(operand1 || operand2);
case Constants.XOR:
boolean result = (operand1 && !operand2) ||
(!operand1 && operand2);
return Heap.allocateTruth(result);
default:
throw new MintException("Unknown comparison operator: " +
Interpreter.convertKeywordToOperator(keyword));
}
}
private static void badTypeException(int keyword, Pointer a, Pointer b)
throws MintException {
throw new MintException("Operator " +
Interpreter.convertKeywordToOperator(keyword) +
" cannot be applied to " + a + " and " +
b + ".");
}
private static void badTypeException(int keyword, Pointer p) throws
MintException {
throw new MintException("Operator " +
Interpreter.convertKeywordToOperator(keyword) +
" cannot be applied to " + p + ".");
}
}